• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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