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 32namespace __asan { 33 34void 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 47static void (*tsd_destructor)(void *tsd) = nullptr; 48 49struct 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 59static thread_local struct tsd_key key; 60 61void AsanTSDInit(void (*destructor)(void *tsd)) { 62 CHECK(!tsd_destructor); 63 tsd_destructor = destructor; 64} 65 66void *AsanTSDGet() { 67 CHECK(tsd_destructor); 68 return key.key; 69} 70 71void AsanTSDSet(void *tsd) { 72 CHECK(tsd_destructor); 73 CHECK(tsd); 74 CHECK(!key.key); 75 key.key = tsd; 76} 77 78void 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 87static pthread_key_t tsd_key; 88static bool tsd_key_inited = false; 89void 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 95void *AsanTSDGet() { 96 CHECK(tsd_key_inited); 97 return pthread_getspecific(tsd_key); 98} 99 100void AsanTSDSet(void *tsd) { 101 CHECK(tsd_key_inited); 102 pthread_setspecific(tsd_key, tsd); 103} 104 105void 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