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 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 { 51 tsd_key() : key(nullptr) {} 52 ~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 62 void AsanTSDInit(void (*destructor)(void *tsd)) { 63 CHECK(!tsd_destructor); 64 tsd_destructor = destructor; 65 } 66 67 void *AsanTSDGet() { 68 CHECK(tsd_destructor); 69 return key.key; 70 } 71 72 void AsanTSDSet(void *tsd) { 73 CHECK(tsd_destructor); 74 CHECK(tsd); 75 CHECK(!key.key); 76 key.key = tsd; 77 } 78 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; 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 96 void *AsanTSDGet() { 97 CHECK(tsd_key_inited); 98 return pthread_getspecific(tsd_key); 99 } 100 101 void AsanTSDSet(void *tsd) { 102 CHECK(tsd_key_inited); 103 pthread_setspecific(tsd_key, tsd); 104 } 105 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