re PR tree-optimization/59100 (requesting optimization of safe rotate function)
[official-gcc.git] / libsanitizer / asan / asan_posix.cc
blobac4ec9e01911e624659f3f8f1dd618bdad03c806
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 //===----------------------------------------------------------------------===//
13 #include "sanitizer_common/sanitizer_platform.h"
14 #if SANITIZER_LINUX || SANITIZER_MAC
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"
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>
31 static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough.
33 namespace __asan {
35 static void MaybeInstallSigaction(int signum,
36 void (*handler)(int, siginfo_t *, void *)) {
37 if (!AsanInterceptsSignal(signum))
38 return;
39 struct sigaction sigact;
40 REAL(memset)(&sigact, 0, sizeof(sigact));
41 sigact.sa_sigaction = handler;
42 sigact.sa_flags = SA_SIGINFO;
43 if (flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
44 CHECK_EQ(0, REAL(sigaction)(signum, &sigact, 0));
45 if (common_flags()->verbosity >= 1) {
46 Report("Installed the sigaction for signal %d\n", signum);
50 static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) {
51 uptr addr = (uptr)siginfo->si_addr;
52 // Write the first message using the bullet-proof write.
53 if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die();
54 uptr pc, sp, bp;
55 GetPcSpBp(context, &pc, &sp, &bp);
56 ReportSIGSEGV(pc, sp, bp, addr);
59 void SetAlternateSignalStack() {
60 stack_t altstack, oldstack;
61 CHECK_EQ(0, sigaltstack(0, &oldstack));
62 // If the alternate stack is already in place, do nothing.
63 if ((oldstack.ss_flags & SS_DISABLE) == 0) return;
64 // TODO(glider): the mapped stack should have the MAP_STACK flag in the
65 // future. It is not required by man 2 sigaltstack now (they're using
66 // malloc()).
67 void* base = MmapOrDie(kAltStackSize, __FUNCTION__);
68 altstack.ss_sp = base;
69 altstack.ss_flags = 0;
70 altstack.ss_size = kAltStackSize;
71 CHECK_EQ(0, sigaltstack(&altstack, 0));
72 if (common_flags()->verbosity > 0) {
73 Report("Alternative stack for T%d set: [%p,%p)\n",
74 GetCurrentTidOrInvalid(),
75 altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size);
79 void UnsetAlternateSignalStack() {
80 stack_t altstack, oldstack;
81 altstack.ss_sp = 0;
82 altstack.ss_flags = SS_DISABLE;
83 altstack.ss_size = 0;
84 CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
85 UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
88 void InstallSignalHandlers() {
89 // Set the alternate signal stack for the main thread.
90 // This will cause SetAlternateSignalStack to be called twice, but the stack
91 // will be actually set only once.
92 if (flags()->use_sigaltstack) SetAlternateSignalStack();
93 MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV);
94 MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV);
97 // ---------------------- TSD ---------------- {{{1
99 static pthread_key_t tsd_key;
100 static bool tsd_key_inited = false;
101 void AsanTSDInit(void (*destructor)(void *tsd)) {
102 CHECK(!tsd_key_inited);
103 tsd_key_inited = true;
104 CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
107 void *AsanTSDGet() {
108 CHECK(tsd_key_inited);
109 return pthread_getspecific(tsd_key);
112 void AsanTSDSet(void *tsd) {
113 CHECK(tsd_key_inited);
114 pthread_setspecific(tsd_key, tsd);
117 void PlatformTSDDtor(void *tsd) {
118 AsanThreadContext *context = (AsanThreadContext*)tsd;
119 if (context->destructor_iterations > 1) {
120 context->destructor_iterations--;
121 CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
122 return;
124 AsanThread::TSDDtor(tsd);
126 } // namespace __asan
128 #endif // SANITIZER_LINUX || SANITIZER_MAC