1 //===-- asan_linux.cc -----------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
10 // Linux-specific details.
11 //===----------------------------------------------------------------------===//
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"
23 #include <sys/resource.h>
25 #include <sys/syscall.h>
26 #include <sys/types.h>
34 // FIXME: where to get ucontext on Android?
35 #include <sys/ucontext.h>
38 extern "C" void* _DYNAMIC
;
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
) {
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
];
70 # error "Unsupported arch"
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
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_
);
93 owner_
= (uptr
)pthread_self();
96 void AsanLock::Unlock() {
97 CHECK(owner_
== (uptr
)pthread_self());
99 pthread_mutex_unlock((pthread_mutex_t
*)&opaque_storage_
);
103 #define UNWIND_STOP _URC_END_OF_STACK
104 #define UNWIND_CONTINUE _URC_NO_REASON
106 #define UNWIND_STOP _URC_NORMAL_STOP
107 #define UNWIND_CONTINUE _URC_NO_REASON
110 uptr
Unwind_GetIP(struct _Unwind_Context
*ctx
) {
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;
119 return _Unwind_GetIP(ctx
);
123 _Unwind_Reason_Code
Unwind_Trace(struct _Unwind_Context
*ctx
,
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
) {
135 stack
->trace
[0] = pc
;
137 stack
->max_size
= max_s
;
139 _Unwind_Backtrace(Unwind_Trace
, stack
);
141 if (!asan_inited
) return;
142 if (AsanThread
*t
= asanThreadRegistry().GetCurrent())
143 stack
->FastUnwindStack(pc
, bp
, t
->stack_top(), t
->stack_bottom());
148 } // namespace __asan