2012-10-29 Wei Mi <wmi@google.com>
[official-gcc.git] / libasan / asan_linux.cc
blob2922740e7f2b7e5cf081333fbc6b769c9fdb47bd
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__
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"
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>
33 #if !ASAN_ANDROID
34 // FIXME: where to get ucontext on Android?
35 #include <sys/ucontext.h>
36 #endif
38 extern "C" void* _DYNAMIC;
40 namespace __asan {
42 void MaybeReexec() {
43 // No need to re-exec on Linux.
46 void *AsanDoesNotSupportStaticLinkage() {
47 // This will fail to link with -static.
48 return &_DYNAMIC; // defined in link.h
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 #else
70 # error "Unsupported arch"
71 #endif
74 bool AsanInterceptsSignal(int signum) {
75 return signum == SIGSEGV && flags()->handle_segv;
78 void AsanPlatformThreadInit() {
79 // Nothing here for now.
82 AsanLock::AsanLock(LinkerInitialized) {
83 // We assume that pthread_mutex_t initialized to all zeroes is a valid
84 // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers
85 // a gcc warning:
86 // extended initializer lists only available with -std=c++0x or -std=gnu++0x
89 void AsanLock::Lock() {
90 CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_));
91 pthread_mutex_lock((pthread_mutex_t*)&opaque_storage_);
92 CHECK(!owner_);
93 owner_ = (uptr)pthread_self();
96 void AsanLock::Unlock() {
97 CHECK(owner_ == (uptr)pthread_self());
98 owner_ = 0;
99 pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_);
102 #ifdef __arm__
103 #define UNWIND_STOP _URC_END_OF_STACK
104 #define UNWIND_CONTINUE _URC_NO_REASON
105 #else
106 #define UNWIND_STOP _URC_NORMAL_STOP
107 #define UNWIND_CONTINUE _URC_NO_REASON
108 #endif
110 uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
111 #ifdef __arm__
112 uptr val;
113 _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
114 15 /* r15 = PC */, _UVRSD_UINT32, &val);
115 CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
116 // Clear the Thumb bit.
117 return val & ~(uptr)1;
118 #else
119 return _Unwind_GetIP(ctx);
120 #endif
123 _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx,
124 void *param) {
125 StackTrace *b = (StackTrace*)param;
126 CHECK(b->size < b->max_size);
127 uptr pc = Unwind_GetIP(ctx);
128 b->trace[b->size++] = pc;
129 if (b->size == b->max_size) return UNWIND_STOP;
130 return UNWIND_CONTINUE;
133 void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
134 stack->size = 0;
135 stack->trace[0] = pc;
136 if ((max_s) > 1) {
137 stack->max_size = max_s;
138 #ifdef __arm__
139 _Unwind_Backtrace(Unwind_Trace, stack);
140 #else
141 if (!asan_inited) return;
142 if (AsanThread *t = asanThreadRegistry().GetCurrent())
143 stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
144 #endif
148 } // namespace __asan
150 #endif // __linux__