1//===-- asan_posix.cc -----------------------------------------------------===// 2// 3// This file is distributed under the University of Illinois Open Source 4// License. See LICENSE.TXT for details. 5// 6//===----------------------------------------------------------------------===// 7// 8// This file is a part of AddressSanitizer, an address sanity checker. 9// 10// Posix-specific details. 11//===----------------------------------------------------------------------===// 12 13#include "sanitizer_common/sanitizer_platform.h" 14#if SANITIZER_POSIX 15 16#include "asan_internal.h" 17#include "asan_interceptors.h" 18#include "asan_mapping.h" 19#include "asan_report.h" 20#include "asan_stack.h" 21#include "sanitizer_common/sanitizer_libc.h" 22#include "sanitizer_common/sanitizer_procmaps.h" 23 24#include <pthread.h> 25#include <signal.h> 26#include <stdlib.h> 27#include <sys/time.h> 28#include <sys/resource.h> 29#include <unistd.h> 30 31namespace __asan { 32 33void AsanOnSIGSEGV(int, void *siginfo, void *context) { 34 ScopedDeadlySignal signal_scope(GetCurrentThread()); 35 uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr; 36 int code = (int)((siginfo_t*)siginfo)->si_code; 37 // Write the first message using the bullet-proof write. 38 if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die(); 39 uptr pc, sp, bp; 40 GetPcSpBp(context, &pc, &sp, &bp); 41 42 // Access at a reasonable offset above SP, or slightly below it (to account 43 // for x86_64 or PowerPC redzone, ARM push of multiple registers, etc) is 44 // probably a stack overflow. 45 // We also check si_code to filter out SEGV caused by something else other 46 // then hitting the guard page or unmapped memory, like, for example, 47 // unaligned memory access. 48 if (addr + 512 > sp && addr < sp + 0xFFFF && 49 (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) 50 ReportStackOverflow(pc, sp, bp, context, addr); 51 else 52 ReportSIGSEGV("SEGV", pc, sp, bp, context, addr); 53} 54 55// ---------------------- TSD ---------------- {{{1 56 57static pthread_key_t tsd_key; 58static bool tsd_key_inited = false; 59void AsanTSDInit(void (*destructor)(void *tsd)) { 60 CHECK(!tsd_key_inited); 61 tsd_key_inited = true; 62 CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 63} 64 65void *AsanTSDGet() { 66 CHECK(tsd_key_inited); 67 return pthread_getspecific(tsd_key); 68} 69 70void AsanTSDSet(void *tsd) { 71 CHECK(tsd_key_inited); 72 pthread_setspecific(tsd_key, tsd); 73} 74 75void PlatformTSDDtor(void *tsd) { 76 AsanThreadContext *context = (AsanThreadContext*)tsd; 77 if (context->destructor_iterations > 1) { 78 context->destructor_iterations--; 79 CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 80 return; 81 } 82 AsanThread::TSDDtor(tsd); 83} 84} // namespace __asan 85 86#endif // SANITIZER_POSIX 87