Home | History | Annotate | Line # | Download | only in asan
      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