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 // Linux-specific details.
13 //===----------------------------------------------------------------------===//
14 #ifdef __linux__
15
16 #include "asan_interceptors.h"
17 #include "asan_internal.h"
18 #include "asan_lock.h"
19 #include "asan_thread.h"
20 #include "asan_thread_registry.h"
21 #include "sanitizer_common/sanitizer_libc.h"
22 #include "sanitizer_common/sanitizer_procmaps.h"
23
24 #include <sys/time.h>
25 #include <sys/resource.h>
26 #include <sys/mman.h>
27 #include <sys/syscall.h>
28 #include <sys/types.h>
29 #include <fcntl.h>
30 #include <pthread.h>
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <unwind.h>
34
35 #if !ASAN_ANDROID
36 // FIXME: where to get ucontext on Android?
37 #include <sys/ucontext.h>
38 #endif
39
40 extern "C" void* _DYNAMIC;
41
42 namespace __asan {
43
MaybeReexec()44 void MaybeReexec() {
45 // No need to re-exec on Linux.
46 }
47
AsanDoesNotSupportStaticLinkage()48 void *AsanDoesNotSupportStaticLinkage() {
49 // This will fail to link with -static.
50 return &_DYNAMIC; // defined in link.h
51 }
52
GetPcSpBp(void * context,uptr * pc,uptr * sp,uptr * bp)53 void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
54 #if ASAN_ANDROID
55 *pc = *sp = *bp = 0;
56 #elif defined(__arm__)
57 ucontext_t *ucontext = (ucontext_t*)context;
58 *pc = ucontext->uc_mcontext.arm_pc;
59 *bp = ucontext->uc_mcontext.arm_fp;
60 *sp = ucontext->uc_mcontext.arm_sp;
61 # elif defined(__x86_64__)
62 ucontext_t *ucontext = (ucontext_t*)context;
63 *pc = ucontext->uc_mcontext.gregs[REG_RIP];
64 *bp = ucontext->uc_mcontext.gregs[REG_RBP];
65 *sp = ucontext->uc_mcontext.gregs[REG_RSP];
66 # elif defined(__i386__)
67 ucontext_t *ucontext = (ucontext_t*)context;
68 *pc = ucontext->uc_mcontext.gregs[REG_EIP];
69 *bp = ucontext->uc_mcontext.gregs[REG_EBP];
70 *sp = ucontext->uc_mcontext.gregs[REG_ESP];
71 #else
72 # error "Unsupported arch"
73 #endif
74 }
75
AsanInterceptsSignal(int signum)76 bool AsanInterceptsSignal(int signum) {
77 return signum == SIGSEGV && flags()->handle_segv;
78 }
79
AsanPlatformThreadInit()80 void AsanPlatformThreadInit() {
81 // Nothing here for now.
82 }
83
AsanLock(LinkerInitialized)84 AsanLock::AsanLock(LinkerInitialized) {
85 // We assume that pthread_mutex_t initialized to all zeroes is a valid
86 // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers
87 // a gcc warning:
88 // extended initializer lists only available with -std=c++0x or -std=gnu++0x
89 }
90
Lock()91 void AsanLock::Lock() {
92 CHECK(sizeof(pthread_mutex_t) <= sizeof(opaque_storage_));
93 pthread_mutex_lock((pthread_mutex_t*)&opaque_storage_);
94 CHECK(!owner_);
95 owner_ = (uptr)pthread_self();
96 }
97
Unlock()98 void AsanLock::Unlock() {
99 CHECK(owner_ == (uptr)pthread_self());
100 owner_ = 0;
101 pthread_mutex_unlock((pthread_mutex_t*)&opaque_storage_);
102 }
103
104 #ifdef __arm__
105 #define UNWIND_STOP _URC_END_OF_STACK
106 #define UNWIND_CONTINUE _URC_NO_REASON
107 #else
108 #define UNWIND_STOP _URC_NORMAL_STOP
109 #define UNWIND_CONTINUE _URC_NO_REASON
110 #endif
111
Unwind_GetIP(struct _Unwind_Context * ctx)112 uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
113 #ifdef __arm__
114 uptr val;
115 _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
116 15 /* r15 = PC */, _UVRSD_UINT32, &val);
117 CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
118 // Clear the Thumb bit.
119 return val & ~(uptr)1;
120 #else
121 return _Unwind_GetIP(ctx);
122 #endif
123 }
124
Unwind_Trace(struct _Unwind_Context * ctx,void * param)125 _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx,
126 void *param) {
127 StackTrace *b = (StackTrace*)param;
128 CHECK(b->size < b->max_size);
129 uptr pc = Unwind_GetIP(ctx);
130 b->trace[b->size++] = pc;
131 if (b->size == b->max_size) return UNWIND_STOP;
132 return UNWIND_CONTINUE;
133 }
134
GetStackTrace(StackTrace * stack,uptr max_s,uptr pc,uptr bp)135 void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) {
136 stack->size = 0;
137 stack->trace[0] = pc;
138 if ((max_s) > 1) {
139 stack->max_size = max_s;
140 #ifdef __arm__
141 _Unwind_Backtrace(Unwind_Trace, stack);
142 #else
143 if (!asan_inited) return;
144 if (AsanThread *t = asanThreadRegistry().GetCurrent())
145 stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
146 #endif
147 }
148 }
149
150 } // namespace __asan
151
152 #endif // __linux__
153