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_procmaps.h" 25 26 #include <pthread.h> 27 #include <signal.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 AsanOnSIGSEGV(int, void *siginfo, void *context) { 36 uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr; 37 int code = (int)((siginfo_t*)siginfo)->si_code; 38 // Write the first message using the bullet-proof write. 39 if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die(); 40 uptr pc, sp, bp; 41 GetPcSpBp(context, &pc, &sp, &bp); 42 43 // Access at a reasonable offset above SP, or slightly below it (to account 44 // for x86_64 redzone, ARM push of multiple registers, etc) is probably a 45 // stack overflow. 46 // We also check si_code to filter out SEGV caused by something else other 47 // then hitting the guard page or unmapped memory, like, for example, 48 // unaligned memory access. 49 if (addr + 128 > sp && addr < sp + 0xFFFF && 50 (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) 51 ReportStackOverflow(pc, sp, bp, context, addr); 52 else 53 ReportSIGSEGV(pc, sp, bp, context, addr); 54 } 55 56 // ---------------------- TSD ---------------- {{{1 57 58 static pthread_key_t tsd_key; 59 static bool tsd_key_inited = false; 60 void AsanTSDInit(void (*destructor)(void *tsd)) { 61 CHECK(!tsd_key_inited); 62 tsd_key_inited = true; 63 CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 64 } 65 66 void *AsanTSDGet() { 67 CHECK(tsd_key_inited); 68 return pthread_getspecific(tsd_key); 69 } 70 71 void AsanTSDSet(void *tsd) { 72 CHECK(tsd_key_inited); 73 pthread_setspecific(tsd_key, tsd); 74 } 75 76 void PlatformTSDDtor(void *tsd) { 77 AsanThreadContext *context = (AsanThreadContext*)tsd; 78 if (context->destructor_iterations > 1) { 79 context->destructor_iterations--; 80 CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 81 return; 82 } 83 AsanThread::TSDDtor(tsd); 84 } 85 } // namespace __asan 86 87 #endif // SANITIZER_POSIX 88