| //===-- asan_posix.cc -----------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file is a part of AddressSanitizer, an address sanity checker. |
| // |
| // Posix-specific details. |
| //===----------------------------------------------------------------------===// |
| |
| #include "sanitizer_common/sanitizer_platform.h" |
| #if SANITIZER_POSIX |
| |
| #include "asan_internal.h" |
| #include "asan_interceptors.h" |
| #include "asan_mapping.h" |
| #include "asan_report.h" |
| #include "asan_stack.h" |
| #include "sanitizer_common/sanitizer_libc.h" |
| #include "sanitizer_common/sanitizer_posix.h" |
| #include "sanitizer_common/sanitizer_procmaps.h" |
| |
| #include <pthread.h> |
| #include <stdlib.h> |
| #include <sys/time.h> |
| #include <sys/resource.h> |
| #include <unistd.h> |
| |
| namespace __asan { |
| |
| void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { |
| StartReportDeadlySignal(); |
| SignalContext sig(siginfo, context); |
| ReportDeadlySignal(sig); |
| } |
| |
| // ---------------------- TSD ---------------- {{{1 |
| |
| #if SANITIZER_NETBSD && !ASAN_DYNAMIC |
| // Thread Static Data cannot be used in early static ASan init on NetBSD. |
| // Reuse the Asan TSD API for compatibility with existing code |
| // with an alternative implementation. |
| |
| static void (*tsd_destructor)(void *tsd) = nullptr; |
| |
| struct tsd_key { |
| tsd_key() : key(nullptr) {} |
| ~tsd_key() { |
| CHECK(tsd_destructor); |
| if (key) |
| (*tsd_destructor)(key); |
| } |
| void *key; |
| }; |
| |
| static thread_local struct tsd_key key; |
| |
| void AsanTSDInit(void (*destructor)(void *tsd)) { |
| CHECK(!tsd_destructor); |
| tsd_destructor = destructor; |
| } |
| |
| void *AsanTSDGet() { |
| CHECK(tsd_destructor); |
| return key.key; |
| } |
| |
| void AsanTSDSet(void *tsd) { |
| CHECK(tsd_destructor); |
| CHECK(tsd); |
| CHECK(!key.key); |
| key.key = tsd; |
| } |
| |
| void PlatformTSDDtor(void *tsd) { |
| CHECK(tsd_destructor); |
| CHECK_EQ(key.key, tsd); |
| key.key = nullptr; |
| // Make sure that signal handler can not see a stale current thread pointer. |
| atomic_signal_fence(memory_order_seq_cst); |
| AsanThread::TSDDtor(tsd); |
| } |
| #else |
| static pthread_key_t tsd_key; |
| static bool tsd_key_inited = false; |
| void AsanTSDInit(void (*destructor)(void *tsd)) { |
| CHECK(!tsd_key_inited); |
| tsd_key_inited = true; |
| CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); |
| } |
| |
| void *AsanTSDGet() { |
| CHECK(tsd_key_inited); |
| return pthread_getspecific(tsd_key); |
| } |
| |
| void AsanTSDSet(void *tsd) { |
| CHECK(tsd_key_inited); |
| pthread_setspecific(tsd_key, tsd); |
| } |
| |
| void PlatformTSDDtor(void *tsd) { |
| AsanThreadContext *context = (AsanThreadContext*)tsd; |
| if (context->destructor_iterations > 1) { |
| context->destructor_iterations--; |
| CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); |
| return; |
| } |
| AsanThread::TSDDtor(tsd); |
| } |
| #endif |
| } // namespace __asan |
| |
| #endif // SANITIZER_POSIX |