xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/asan/asan_posix.cc (revision a8c3f321e2de95a2da9013a2169edbf5acc5bd76)
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