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