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 118