Home | History | Annotate | Line # | Download | only in asan
      1  1.1  kamil //===-- asan_posix.cc -----------------------------------------------------===//
      2  1.1  kamil //
      3  1.1  kamil //                     The LLVM Compiler Infrastructure
      4  1.1  kamil //
      5  1.1  kamil // This file is distributed under the University of Illinois Open Source
      6  1.1  kamil // License. See LICENSE.TXT for details.
      7  1.1  kamil //
      8  1.1  kamil //===----------------------------------------------------------------------===//
      9  1.1  kamil //
     10  1.1  kamil // This file is a part of AddressSanitizer, an address sanity checker.
     11  1.1  kamil //
     12  1.1  kamil // Posix-specific details.
     13  1.1  kamil //===----------------------------------------------------------------------===//
     14  1.1  kamil 
     15  1.1  kamil #include "sanitizer_common/sanitizer_platform.h"
     16  1.1  kamil #if SANITIZER_POSIX
     17  1.1  kamil 
     18  1.1  kamil #include "asan_internal.h"
     19  1.1  kamil #include "asan_interceptors.h"
     20  1.1  kamil #include "asan_mapping.h"
     21  1.1  kamil #include "asan_report.h"
     22  1.1  kamil #include "asan_stack.h"
     23  1.1  kamil #include "sanitizer_common/sanitizer_libc.h"
     24  1.1  kamil #include "sanitizer_common/sanitizer_posix.h"
     25  1.1  kamil #include "sanitizer_common/sanitizer_procmaps.h"
     26  1.1  kamil 
     27  1.1  kamil #include <pthread.h>
     28  1.1  kamil #include <stdlib.h>
     29  1.1  kamil #include <sys/time.h>
     30  1.1  kamil #include <sys/resource.h>
     31  1.1  kamil #include <unistd.h>
     32  1.1  kamil 
     33  1.1  kamil namespace __asan {
     34  1.1  kamil 
     35  1.1  kamil void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
     36  1.1  kamil   StartReportDeadlySignal();
     37  1.1  kamil   SignalContext sig(siginfo, context);
     38  1.1  kamil   ReportDeadlySignal(sig);
     39  1.1  kamil }
     40  1.1  kamil 
     41  1.1  kamil // ---------------------- TSD ---------------- {{{1
     42  1.1  kamil 
     43  1.2  kamil #if (SANITIZER_NETBSD && !ASAN_DYNAMIC) || SANITIZER_FREEBSD
     44  1.2  kamil // Thread Static Data cannot be used in early static ASan init on NetBSD.
     45  1.1  kamil // Reuse the Asan TSD API for compatibility with existing code
     46  1.1  kamil // with an alternative implementation.
     47  1.1  kamil 
     48  1.1  kamil static void (*tsd_destructor)(void *tsd) = nullptr;
     49  1.1  kamil 
     50  1.1  kamil struct tsd_key {
     51  1.1  kamil   tsd_key() : key(nullptr) {}
     52  1.1  kamil   ~tsd_key() {
     53  1.1  kamil     CHECK(tsd_destructor);
     54  1.1  kamil     if (key)
     55  1.1  kamil       (*tsd_destructor)(key);
     56  1.1  kamil   }
     57  1.1  kamil   void *key;
     58  1.1  kamil };
     59  1.1  kamil 
     60  1.1  kamil static thread_local struct tsd_key key;
     61  1.1  kamil 
     62  1.1  kamil void AsanTSDInit(void (*destructor)(void *tsd)) {
     63  1.1  kamil   CHECK(!tsd_destructor);
     64  1.1  kamil   tsd_destructor = destructor;
     65  1.1  kamil }
     66  1.1  kamil 
     67  1.1  kamil void *AsanTSDGet() {
     68  1.1  kamil   CHECK(tsd_destructor);
     69  1.1  kamil   return key.key;
     70  1.1  kamil }
     71  1.1  kamil 
     72  1.1  kamil void AsanTSDSet(void *tsd) {
     73  1.1  kamil   CHECK(tsd_destructor);
     74  1.1  kamil   CHECK(tsd);
     75  1.1  kamil   CHECK(!key.key);
     76  1.1  kamil   key.key = tsd;
     77  1.1  kamil }
     78  1.1  kamil 
     79  1.1  kamil void PlatformTSDDtor(void *tsd) {
     80  1.1  kamil   CHECK(tsd_destructor);
     81  1.1  kamil   CHECK_EQ(key.key, tsd);
     82  1.1  kamil   key.key = nullptr;
     83  1.1  kamil   // Make sure that signal handler can not see a stale current thread pointer.
     84  1.1  kamil   atomic_signal_fence(memory_order_seq_cst);
     85  1.1  kamil   AsanThread::TSDDtor(tsd);
     86  1.1  kamil }
     87  1.1  kamil #else
     88  1.1  kamil static pthread_key_t tsd_key;
     89  1.1  kamil static bool tsd_key_inited = false;
     90  1.1  kamil void AsanTSDInit(void (*destructor)(void *tsd)) {
     91  1.1  kamil   CHECK(!tsd_key_inited);
     92  1.1  kamil   tsd_key_inited = true;
     93  1.1  kamil   CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
     94  1.1  kamil }
     95  1.1  kamil 
     96  1.1  kamil void *AsanTSDGet() {
     97  1.1  kamil   CHECK(tsd_key_inited);
     98  1.1  kamil   return pthread_getspecific(tsd_key);
     99  1.1  kamil }
    100  1.1  kamil 
    101  1.1  kamil void AsanTSDSet(void *tsd) {
    102  1.1  kamil   CHECK(tsd_key_inited);
    103  1.1  kamil   pthread_setspecific(tsd_key, tsd);
    104  1.1  kamil }
    105  1.1  kamil 
    106  1.1  kamil void PlatformTSDDtor(void *tsd) {
    107  1.1  kamil   AsanThreadContext *context = (AsanThreadContext*)tsd;
    108  1.1  kamil   if (context->destructor_iterations > 1) {
    109  1.1  kamil     context->destructor_iterations--;
    110  1.1  kamil     CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
    111  1.1  kamil     return;
    112  1.1  kamil   }
    113  1.1  kamil   AsanThread::TSDDtor(tsd);
    114  1.1  kamil }
    115  1.1  kamil #endif
    116  1.1  kamil }  // namespace __asan
    117  1.1  kamil 
    118  1.1  kamil #endif  // SANITIZER_POSIX
    119