Add libstdc++-raw-cxx.m4 and use it in libsanitizer
[gcc.git] / libsanitizer / asan / asan_linux.cc
1 //===-- asan_linux.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 // Linux-specific details.
11 //===----------------------------------------------------------------------===//
12 #ifdef __linux__
13
14 #include "asan_interceptors.h"
15 #include "asan_internal.h"
16 #include "asan_lock.h"
17 #include "asan_thread.h"
18 #include "asan_thread_registry.h"
19 #include "sanitizer_common/sanitizer_libc.h"
20 #include "sanitizer_common/sanitizer_procmaps.h"
21
22 #include <sys/time.h>
23 #include <sys/resource.h>
24 #include <sys/mman.h>
25 #include <sys/syscall.h>
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #include <pthread.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <unwind.h>
32
33 #if !ASAN_ANDROID
34 // FIXME: where to get ucontext on Android?
35 #include <sys/ucontext.h>
36 #endif
37
38 extern "C" void* _DYNAMIC;
39
40 namespace __asan {
41
42 void MaybeReexec() {
43 // No need to re-exec on Linux.
44 }
45
46 void *AsanDoesNotSupportStaticLinkage() {
47 // This will fail to link with -static.
48 return &_DYNAMIC; // defined in link.h
49 }
50
51 void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
52 #if ASAN_ANDROID
53 *pc = *sp = *bp = 0;
54 #elif defined(__arm__)
55 ucontext_t *ucontext = (ucontext_t*)context;
56 *pc = ucontext->uc_mcontext.arm_pc;
57 *bp = ucontext->uc_mcontext.arm_fp;
58 *sp = ucontext->uc_mcontext.arm_sp;
59 # elif defined(__x86_64__)
60 ucontext_t *ucontext = (ucontext_t*)context;
61 *pc = ucontext->uc_mcontext.gregs[REG_RIP];
62 *bp = ucontext->uc_mcontext.gregs[REG_RBP];
63 *sp = ucontext->uc_mcontext.gregs[REG_RSP];
64 # elif defined(__i386__)
65 ucontext_t *ucontext = (ucontext_t*)context;
66 *pc = ucontext->uc_mcontext.gregs[REG_EIP];
67 *bp = ucontext->uc_mcontext.gregs[REG_EBP];
68 *sp = ucontext->uc_mcontext.gregs[REG_ESP];
69 # elif defined(__powerpc__) || defined(__powerpc64__)
70 ucontext_t *ucontext = (ucontext_t*)context;
71 *pc = ucontext->uc_mcontext.regs->nip;
72 *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
73 // The powerpc{,64}-linux ABIs do not specify r31 as the frame
74 // pointer, but GCC always uses r31 when we need a frame pointer.
75 *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
76 # elif defined(__sparc__)
77 ucontext_t *ucontext = (ucontext_t*)context;
78 uptr *stk_ptr;
79 # if defined (__arch64__)
80 *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
81 *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
82 stk_ptr = (uptr *) (*sp + 2047);
83 *bp = stk_ptr[15];
84 # else
85 *pc = ucontext->uc_mcontext.gregs[REG_PC];
86 *sp = ucontext->uc_mcontext.gregs[REG_O6];
87 stk_ptr = (uptr *) *sp;
88 *bp = stk_ptr[15];
89 # endif
90 #else
91 # error "Unsupported arch"
92 #endif
93 }
94
95 bool AsanInterceptsSignal(int signum) {
96 return signum == SIGSEGV && flags()->handle_segv;
97 }
98
99 void AsanPlatformThreadInit() {
100 // Nothing here for now.
101 }
102
103 AsanLock::AsanLock(LinkerInitialized) {
104 // We assume that pthread_mutex_t initialized to all zeroes is a valid
105 // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers
106 // a gcc warning:
107 // extended initializer lists only available with -std=c++0x or -std=gnu++0x
108 }
109
110 void AsanLock::Lock() {
111 CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_));
112 pthread_mutex_lock((pthread_mutex_t*)&opaque_storage_);
113 CHECK(!owner_);
114 owner_ = (uptr)pthread_self();
115 }
116
117 void AsanLock::Unlock() {
118 CHECK(owner_ == (uptr)pthread_self());
119 owner_ = 0;
120 pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_);
121 }
122
123 #ifdef __arm__
124 #define UNWIND_STOP _URC_END_OF_STACK
125 #define UNWIND_CONTINUE _URC_NO_REASON
126 #else
127 #define UNWIND_STOP _URC_NORMAL_STOP
128 #define UNWIND_CONTINUE _URC_NO_REASON
129 #endif
130
131 uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
132 #ifdef __arm__
133 uptr val;
134 _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
135 15 /* r15 = PC */, _UVRSD_UINT32, &val);
136 CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
137 // Clear the Thumb bit.
138 return val & ~(uptr)1;
139 #else
140 return _Unwind_GetIP(ctx);
141 #endif
142 }
143
144 _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx,
145 void *param) {
146 StackTrace *b = (StackTrace*)param;
147 CHECK(b->size < b->max_size);
148 uptr pc = Unwind_GetIP(ctx);
149 b->trace[b->size++] = pc;
150 if (b->size == b->max_size) return UNWIND_STOP;
151 return UNWIND_CONTINUE;
152 }
153
154 void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
155 stack->size = 0;
156 stack->trace[0] = pc;
157 if ((max_s) > 1) {
158 stack->max_size = max_s;
159 #if defined(__arm__) || \
160 defined(__powerpc__) || defined(__powerpc64__) || \
161 defined(__sparc__)
162 _Unwind_Backtrace(Unwind_Trace, stack);
163 // Pop off the two ASAN functions from the backtrace.
164 stack->PopStackFrames(2);
165 #else
166 if (!asan_inited) return;
167 if (AsanThread *t = asanThreadRegistry().GetCurrent())
168 stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
169 #endif
170 }
171 }
172
173 #if !ASAN_ANDROID
174 void ClearShadowMemoryForContext(void *context) {
175 ucontext_t *ucp = (ucontext_t*)context;
176 uptr sp = (uptr)ucp->uc_stack.ss_sp;
177 uptr size = ucp->uc_stack.ss_size;
178 // Align to page size.
179 uptr PageSize = GetPageSizeCached();
180 uptr bottom = sp & ~(PageSize - 1);
181 size += sp - bottom;
182 size = RoundUpTo(size, PageSize);
183 PoisonShadow(bottom, size, 0);
184 }
185 #else
186 void ClearShadowMemoryForContext(void *context) {
187 UNIMPLEMENTED();
188 }
189 #endif
190
191 } // namespace __asan
192
193 #endif // __linux__