145
|
1 //===-- asan_posix.cpp ----------------------------------------------------===//
|
|
2 //
|
|
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4 // See https://llvm.org/LICENSE.txt for license information.
|
|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8 //
|
|
9 // This file is a part of AddressSanitizer, an address sanity checker.
|
|
10 //
|
|
11 // Posix-specific details.
|
|
12 //===----------------------------------------------------------------------===//
|
|
13
|
|
14 #include "sanitizer_common/sanitizer_platform.h"
|
|
15 #if SANITIZER_POSIX
|
|
16
|
|
17 #include "asan_internal.h"
|
|
18 #include "asan_interceptors.h"
|
|
19 #include "asan_mapping.h"
|
|
20 #include "asan_report.h"
|
|
21 #include "asan_stack.h"
|
|
22 #include "sanitizer_common/sanitizer_libc.h"
|
|
23 #include "sanitizer_common/sanitizer_posix.h"
|
|
24 #include "sanitizer_common/sanitizer_procmaps.h"
|
|
25
|
|
26 #include <pthread.h>
|
|
27 #include <stdlib.h>
|
|
28 #include <sys/time.h>
|
|
29 #include <sys/resource.h>
|
|
30 #include <unistd.h>
|
|
31
|
|
32 namespace __asan {
|
|
33
|
|
34 void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
|
|
35 StartReportDeadlySignal();
|
|
36 SignalContext sig(siginfo, context);
|
|
37 ReportDeadlySignal(sig);
|
|
38 }
|
|
39
|
|
40 // ---------------------- TSD ---------------- {{{1
|
|
41
|
|
42 #if SANITIZER_NETBSD && !ASAN_DYNAMIC
|
|
43 // Thread Static Data cannot be used in early static ASan init on NetBSD.
|
|
44 // Reuse the Asan TSD API for compatibility with existing code
|
|
45 // with an alternative implementation.
|
|
46
|
|
47 static void (*tsd_destructor)(void *tsd) = nullptr;
|
|
48
|
|
49 struct tsd_key {
|
|
50 tsd_key() : key(nullptr) {}
|
|
51 ~tsd_key() {
|
|
52 CHECK(tsd_destructor);
|
|
53 if (key)
|
|
54 (*tsd_destructor)(key);
|
|
55 }
|
|
56 void *key;
|
|
57 };
|
|
58
|
|
59 static thread_local struct tsd_key key;
|
|
60
|
|
61 void AsanTSDInit(void (*destructor)(void *tsd)) {
|
|
62 CHECK(!tsd_destructor);
|
|
63 tsd_destructor = destructor;
|
|
64 }
|
|
65
|
|
66 void *AsanTSDGet() {
|
|
67 CHECK(tsd_destructor);
|
|
68 return key.key;
|
|
69 }
|
|
70
|
|
71 void AsanTSDSet(void *tsd) {
|
|
72 CHECK(tsd_destructor);
|
|
73 CHECK(tsd);
|
|
74 CHECK(!key.key);
|
|
75 key.key = tsd;
|
|
76 }
|
|
77
|
|
78 void PlatformTSDDtor(void *tsd) {
|
|
79 CHECK(tsd_destructor);
|
|
80 CHECK_EQ(key.key, tsd);
|
|
81 key.key = nullptr;
|
|
82 // Make sure that signal handler can not see a stale current thread pointer.
|
|
83 atomic_signal_fence(memory_order_seq_cst);
|
|
84 AsanThread::TSDDtor(tsd);
|
|
85 }
|
|
86 #else
|
|
87 static pthread_key_t tsd_key;
|
|
88 static bool tsd_key_inited = false;
|
|
89 void AsanTSDInit(void (*destructor)(void *tsd)) {
|
|
90 CHECK(!tsd_key_inited);
|
|
91 tsd_key_inited = true;
|
|
92 CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
|
|
93 }
|
|
94
|
|
95 void *AsanTSDGet() {
|
|
96 CHECK(tsd_key_inited);
|
|
97 return pthread_getspecific(tsd_key);
|
|
98 }
|
|
99
|
|
100 void AsanTSDSet(void *tsd) {
|
|
101 CHECK(tsd_key_inited);
|
|
102 pthread_setspecific(tsd_key, tsd);
|
|
103 }
|
|
104
|
|
105 void PlatformTSDDtor(void *tsd) {
|
|
106 AsanThreadContext *context = (AsanThreadContext*)tsd;
|
|
107 if (context->destructor_iterations > 1) {
|
|
108 context->destructor_iterations--;
|
|
109 CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
|
|
110 return;
|
|
111 }
|
|
112 AsanThread::TSDDtor(tsd);
|
|
113 }
|
|
114 #endif
|
|
115 } // namespace __asan
|
|
116
|
|
117 #endif // SANITIZER_POSIX
|