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 33namespace __asan { 34 35void 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 58static pthread_key_t tsd_key; 59static bool tsd_key_inited = false; 60void 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 66void *AsanTSDGet() { 67 CHECK(tsd_key_inited); 68 return pthread_getspecific(tsd_key); 69} 70 71void AsanTSDSet(void *tsd) { 72 CHECK(tsd_key_inited); 73 pthread_setspecific(tsd_key, tsd); 74} 75 76void 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