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 //===----------------------------------------------------------------------===//
13 #include "sanitizer_common/sanitizer_platform.h"
14 #if SANITIZER_FREEBSD || SANITIZER_LINUX
16 #include "asan_interceptors.h"
17 #include "asan_internal.h"
18 #include "asan_thread.h"
19 #include "sanitizer_common/sanitizer_flags.h"
20 #include "sanitizer_common/sanitizer_libc.h"
21 #include "sanitizer_common/sanitizer_procmaps.h"
24 #include <sys/resource.h>
26 #include <sys/syscall.h>
27 #include <sys/types.h>
35 #include <sys/link_elf.h>
38 #if SANITIZER_ANDROID || SANITIZER_FREEBSD
40 extern "C" void* _DYNAMIC
;
42 #include <sys/ucontext.h>
47 // x86_64 FreeBSD 9.2 and older define 64-bit register names in both 64-bit
50 #include <sys/param.h>
51 # if __FreeBSD_version <= 902001 // v9.2
52 # define mc_eip mc_rip
53 # define mc_ebp mc_rbp
54 # define mc_esp mc_rsp
59 ASAN_RT_VERSION_UNDEFINED
= 0,
60 ASAN_RT_VERSION_DYNAMIC
,
61 ASAN_RT_VERSION_STATIC
,
64 // FIXME: perhaps also store abi version here?
66 SANITIZER_INTERFACE_ATTRIBUTE
67 asan_rt_version_t __asan_rt_version
;
73 // No need to re-exec on Linux.
76 void *AsanDoesNotSupportStaticLinkage() {
77 // This will fail to link with -static.
78 return &_DYNAMIC
; // defined in link.h
82 // FIXME: should we do anything for Android?
83 void AsanCheckDynamicRTPrereqs() {}
84 void AsanCheckIncompatibleRT() {}
86 static int FindFirstDSOCallback(struct dl_phdr_info
*info
, size_t size
,
88 // Continue until the first dynamic library is found
89 if (!info
->dlpi_name
|| info
->dlpi_name
[0] == 0)
93 if (internal_strncmp(info
->dlpi_name
, "linux-", sizeof("linux-") - 1) == 0)
96 *(const char **)data
= info
->dlpi_name
;
100 static bool IsDynamicRTName(const char *libname
) {
101 return internal_strstr(libname
, "libclang_rt.asan") ||
102 internal_strstr(libname
, "libasan.so");
105 static void ReportIncompatibleRT() {
106 Report("Your application is linked against incompatible ASan runtimes.\n");
110 void AsanCheckDynamicRTPrereqs() {
111 // Ensure that dynamic RT is the first DSO in the list
112 const char *first_dso_name
= 0;
113 dl_iterate_phdr(FindFirstDSOCallback
, &first_dso_name
);
114 if (first_dso_name
&& !IsDynamicRTName(first_dso_name
)) {
115 Report("ASan runtime does not come first in initial library list; "
116 "you should either link runtime to your application or "
117 "manually preload it with LD_PRELOAD.\n");
122 void AsanCheckIncompatibleRT() {
124 if (__asan_rt_version
== ASAN_RT_VERSION_UNDEFINED
) {
125 __asan_rt_version
= ASAN_RT_VERSION_DYNAMIC
;
126 } else if (__asan_rt_version
!= ASAN_RT_VERSION_DYNAMIC
) {
127 ReportIncompatibleRT();
130 if (__asan_rt_version
== ASAN_RT_VERSION_UNDEFINED
) {
131 // Ensure that dynamic runtime is not present. We should detect it
132 // as early as possible, otherwise ASan interceptors could bind to
133 // the functions in dynamic ASan runtime instead of the functions in
134 // system libraries, causing crashes later in ASan initialization.
135 MemoryMappingLayout
proc_maps(/*cache_enabled*/true);
137 while (proc_maps
.Next(0, 0, 0, filename
, sizeof(filename
), 0)) {
138 if (IsDynamicRTName(filename
)) {
139 Report("Your application is linked against "
140 "incompatible ASan runtimes.\n");
144 __asan_rt_version
= ASAN_RT_VERSION_STATIC
;
145 } else if (__asan_rt_version
!= ASAN_RT_VERSION_STATIC
) {
146 ReportIncompatibleRT();
150 #endif // SANITIZER_ANDROID
152 void GetPcSpBp(void *context
, uptr
*pc
, uptr
*sp
, uptr
*bp
) {
154 ucontext_t
*ucontext
= (ucontext_t
*)context
;
155 *pc
= ucontext
->uc_mcontext
.arm_pc
;
156 *bp
= ucontext
->uc_mcontext
.arm_fp
;
157 *sp
= ucontext
->uc_mcontext
.arm_sp
;
158 #elif defined(__aarch64__)
159 ucontext_t
*ucontext
= (ucontext_t
*)context
;
160 *pc
= ucontext
->uc_mcontext
.pc
;
161 *bp
= ucontext
->uc_mcontext
.regs
[29];
162 *sp
= ucontext
->uc_mcontext
.sp
;
163 #elif defined(__hppa__)
164 ucontext_t
*ucontext
= (ucontext_t
*)context
;
165 *pc
= ucontext
->uc_mcontext
.sc_iaoq
[0];
166 /* GCC uses %r3 whenever a frame pointer is needed. */
167 *bp
= ucontext
->uc_mcontext
.sc_gr
[3];
168 *sp
= ucontext
->uc_mcontext
.sc_gr
[30];
169 #elif defined(__x86_64__)
170 # if SANITIZER_FREEBSD
171 ucontext_t
*ucontext
= (ucontext_t
*)context
;
172 *pc
= ucontext
->uc_mcontext
.mc_rip
;
173 *bp
= ucontext
->uc_mcontext
.mc_rbp
;
174 *sp
= ucontext
->uc_mcontext
.mc_rsp
;
176 ucontext_t
*ucontext
= (ucontext_t
*)context
;
177 *pc
= ucontext
->uc_mcontext
.gregs
[REG_RIP
];
178 *bp
= ucontext
->uc_mcontext
.gregs
[REG_RBP
];
179 *sp
= ucontext
->uc_mcontext
.gregs
[REG_RSP
];
181 #elif defined(__i386__)
182 # if SANITIZER_FREEBSD
183 ucontext_t
*ucontext
= (ucontext_t
*)context
;
184 *pc
= ucontext
->uc_mcontext
.mc_eip
;
185 *bp
= ucontext
->uc_mcontext
.mc_ebp
;
186 *sp
= ucontext
->uc_mcontext
.mc_esp
;
188 ucontext_t
*ucontext
= (ucontext_t
*)context
;
189 *pc
= ucontext
->uc_mcontext
.gregs
[REG_EIP
];
190 *bp
= ucontext
->uc_mcontext
.gregs
[REG_EBP
];
191 *sp
= ucontext
->uc_mcontext
.gregs
[REG_ESP
];
193 #elif defined(__powerpc__) || defined(__powerpc64__)
194 ucontext_t
*ucontext
= (ucontext_t
*)context
;
195 *pc
= ucontext
->uc_mcontext
.regs
->nip
;
196 *sp
= ucontext
->uc_mcontext
.regs
->gpr
[PT_R1
];
197 // The powerpc{,64}-linux ABIs do not specify r31 as the frame
198 // pointer, but GCC always uses r31 when we need a frame pointer.
199 *bp
= ucontext
->uc_mcontext
.regs
->gpr
[PT_R31
];
200 #elif defined(__sparc__)
201 ucontext_t
*ucontext
= (ucontext_t
*)context
;
203 # if defined (__arch64__)
204 *pc
= ucontext
->uc_mcontext
.mc_gregs
[MC_PC
];
205 *sp
= ucontext
->uc_mcontext
.mc_gregs
[MC_O6
];
206 stk_ptr
= (uptr
*) (*sp
+ 2047);
209 *pc
= ucontext
->uc_mcontext
.gregs
[REG_PC
];
210 *sp
= ucontext
->uc_mcontext
.gregs
[REG_O6
];
211 stk_ptr
= (uptr
*) *sp
;
214 #elif defined(__mips__)
215 ucontext_t
*ucontext
= (ucontext_t
*)context
;
216 *pc
= ucontext
->uc_mcontext
.gregs
[31];
217 *bp
= ucontext
->uc_mcontext
.gregs
[30];
218 *sp
= ucontext
->uc_mcontext
.gregs
[29];
220 # error "Unsupported arch"
224 bool AsanInterceptsSignal(int signum
) {
225 return signum
== SIGSEGV
&& common_flags()->handle_segv
;
228 void AsanPlatformThreadInit() {
229 // Nothing here for now.
232 #if !SANITIZER_ANDROID
233 void ReadContextStack(void *context
, uptr
*stack
, uptr
*ssize
) {
234 ucontext_t
*ucp
= (ucontext_t
*)context
;
235 *stack
= (uptr
)ucp
->uc_stack
.ss_sp
;
236 *ssize
= ucp
->uc_stack
.ss_size
;
239 void ReadContextStack(void *context
, uptr
*stack
, uptr
*ssize
) {
244 } // namespace __asan
246 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX