asan_posix.cc revision f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41
1//===-- asan_linux.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#if defined(__linux__) || defined(__APPLE__) 15 16#include "asan_internal.h" 17#include "asan_interceptors.h" 18#include "asan_procmaps.h" 19#include "asan_stack.h" 20#include "asan_thread_registry.h" 21 22#include <pthread.h> 23#include <signal.h> 24#include <stdlib.h> 25#include <sys/time.h> 26#include <sys/resource.h> 27#include <unistd.h> 28 29#ifdef ANDROID 30#include <sys/atomics.h> 31#endif 32 33// Should not add dependency on libstdc++, 34// since most of the stuff here is inlinable. 35#include <algorithm> 36 37static const size_t kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. 38 39namespace __asan { 40 41static void MaybeInstallSigaction(int signum, 42 void (*handler)(int, siginfo_t *, void *)) { 43 if (!AsanInterceptsSignal(signum)) 44 return; 45 struct sigaction sigact; 46 REAL(memset)(&sigact, 0, sizeof(sigact)); 47 sigact.sa_sigaction = handler; 48 sigact.sa_flags = SA_SIGINFO; 49 if (FLAG_use_sigaltstack) sigact.sa_flags |= SA_ONSTACK; 50 CHECK(0 == REAL(sigaction)(signum, &sigact, 0)); 51} 52 53static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) { 54 uintptr_t addr = (uintptr_t)siginfo->si_addr; 55 // Write the first message using the bullet-proof write. 56 if (13 != AsanWrite(2, "ASAN:SIGSEGV\n", 13)) AsanDie(); 57 uintptr_t pc, sp, bp; 58 GetPcSpBp(context, &pc, &sp, &bp); 59 Report("ERROR: AddressSanitizer crashed on unknown address %p" 60 " (pc %p sp %p bp %p T%d)\n", 61 addr, pc, sp, bp, 62 asanThreadRegistry().GetCurrentTidOrMinusOne()); 63 Printf("AddressSanitizer can not provide additional info. ABORTING\n"); 64 GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp); 65 stack.PrintStack(); 66 ShowStatsAndAbort(); 67} 68 69void SetAlternateSignalStack() { 70 stack_t altstack, oldstack; 71 CHECK(0 == sigaltstack(NULL, &oldstack)); 72 // If the alternate stack is already in place, do nothing. 73 if ((oldstack.ss_flags & SS_DISABLE) == 0) return; 74 // TODO(glider): the mapped stack should have the MAP_STACK flag in the 75 // future. It is not required by man 2 sigaltstack now (they're using 76 // malloc()). 77 void* base = AsanMmapSomewhereOrDie(kAltStackSize, __FUNCTION__); 78 altstack.ss_sp = base; 79 altstack.ss_flags = 0; 80 altstack.ss_size = kAltStackSize; 81 CHECK(0 == sigaltstack(&altstack, NULL)); 82 if (FLAG_v > 0) { 83 Report("Alternative stack for T%d set: [%p,%p)\n", 84 asanThreadRegistry().GetCurrentTidOrMinusOne(), 85 altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size); 86 } 87} 88 89void UnsetAlternateSignalStack() { 90 stack_t altstack, oldstack; 91 altstack.ss_sp = NULL; 92 altstack.ss_flags = SS_DISABLE; 93 altstack.ss_size = 0; 94 CHECK(0 == sigaltstack(&altstack, &oldstack)); 95 AsanUnmapOrDie(oldstack.ss_sp, oldstack.ss_size); 96} 97 98void InstallSignalHandlers() { 99 // Set the alternate signal stack for the main thread. 100 // This will cause SetAlternateSignalStack to be called twice, but the stack 101 // will be actually set only once. 102 if (FLAG_use_sigaltstack) SetAlternateSignalStack(); 103 MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV); 104 MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV); 105} 106 107void AsanDisableCoreDumper() { 108 struct rlimit nocore; 109 nocore.rlim_cur = 0; 110 nocore.rlim_max = 0; 111 setrlimit(RLIMIT_CORE, &nocore); 112} 113 114void AsanDumpProcessMap() { 115 AsanProcMaps proc_maps; 116 uintptr_t start, end; 117 const intptr_t kBufSize = 4095; 118 char filename[kBufSize]; 119 Report("Process memory map follows:\n"); 120 while (proc_maps.Next(&start, &end, /* file_offset */NULL, 121 filename, kBufSize)) { 122 Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename); 123 } 124 Report("End of process memory map.\n"); 125} 126 127int GetPid() { 128 return getpid(); 129} 130 131uintptr_t GetThreadSelf() { 132 return (uintptr_t)pthread_self(); 133} 134 135void SleepForSeconds(int seconds) { 136 sleep(seconds); 137} 138 139void Exit(int exitcode) { 140 _exit(exitcode); 141} 142 143int Atexit(void (*function)(void)) { 144 return atexit(function); 145} 146 147int AtomicInc(int *a) { 148#ifdef ANDROID 149 return __atomic_inc(a) + 1; 150#else 151 return __sync_add_and_fetch(a, 1); 152#endif 153} 154 155void SortArray(uintptr_t *array, size_t size) { 156 std::sort(array, array + size); 157} 158 159// ---------------------- TSD ---------------- {{{1 160 161static pthread_key_t tsd_key; 162static bool tsd_key_inited = false; 163void AsanTSDInit(void (*destructor)(void *tsd)) { 164 CHECK(!tsd_key_inited); 165 tsd_key_inited = true; 166 CHECK(0 == pthread_key_create(&tsd_key, destructor)); 167} 168 169void *AsanTSDGet() { 170 CHECK(tsd_key_inited); 171 return pthread_getspecific(tsd_key); 172} 173 174void AsanTSDSet(void *tsd) { 175 CHECK(tsd_key_inited); 176 pthread_setspecific(tsd_key, tsd); 177} 178 179} // namespace __asan 180 181#endif // __linux__ || __APPLE_ 182