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_freebsd.h"
21 #include "sanitizer_common/sanitizer_libc.h"
22 #include "sanitizer_common/sanitizer_procmaps.h"
25 #include <sys/resource.h>
27 #include <sys/syscall.h>
28 #include <sys/types.h>
37 #include <sys/link_elf.h>
40 #if SANITIZER_ANDROID || SANITIZER_FREEBSD
42 extern "C" void* _DYNAMIC
;
44 #include <sys/ucontext.h>
48 // x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
50 #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
51 __FreeBSD_version <= 902001 // v9.2
52 #define ucontext_t xucontext_t
56 ASAN_RT_VERSION_UNDEFINED
= 0,
57 ASAN_RT_VERSION_DYNAMIC
,
58 ASAN_RT_VERSION_STATIC
,
61 // FIXME: perhaps also store abi version here?
63 SANITIZER_INTERFACE_ATTRIBUTE
64 asan_rt_version_t __asan_rt_version
;
70 // No need to re-exec on Linux.
73 void *AsanDoesNotSupportStaticLinkage() {
74 // This will fail to link with -static.
75 return &_DYNAMIC
; // defined in link.h
79 // FIXME: should we do anything for Android?
80 void AsanCheckDynamicRTPrereqs() {}
81 void AsanCheckIncompatibleRT() {}
83 static int FindFirstDSOCallback(struct dl_phdr_info
*info
, size_t size
,
85 // Continue until the first dynamic library is found
86 if (!info
->dlpi_name
|| info
->dlpi_name
[0] == 0)
90 if (internal_strncmp(info
->dlpi_name
, "linux-", sizeof("linux-") - 1) == 0)
93 *(const char **)data
= info
->dlpi_name
;
97 static bool IsDynamicRTName(const char *libname
) {
98 return internal_strstr(libname
, "libclang_rt.asan") ||
99 internal_strstr(libname
, "libasan.so");
102 static void ReportIncompatibleRT() {
103 Report("Your application is linked against incompatible ASan runtimes.\n");
107 void AsanCheckDynamicRTPrereqs() {
108 // Ensure that dynamic RT is the first DSO in the list
109 const char *first_dso_name
= 0;
110 dl_iterate_phdr(FindFirstDSOCallback
, &first_dso_name
);
111 if (first_dso_name
&& !IsDynamicRTName(first_dso_name
)) {
112 Report("ASan runtime does not come first in initial library list; "
113 "you should either link runtime to your application or "
114 "manually preload it with LD_PRELOAD.\n");
119 void AsanCheckIncompatibleRT() {
121 if (__asan_rt_version
== ASAN_RT_VERSION_UNDEFINED
) {
122 __asan_rt_version
= ASAN_RT_VERSION_DYNAMIC
;
123 } else if (__asan_rt_version
!= ASAN_RT_VERSION_DYNAMIC
) {
124 ReportIncompatibleRT();
127 if (__asan_rt_version
== ASAN_RT_VERSION_UNDEFINED
) {
128 // Ensure that dynamic runtime is not present. We should detect it
129 // as early as possible, otherwise ASan interceptors could bind to
130 // the functions in dynamic ASan runtime instead of the functions in
131 // system libraries, causing crashes later in ASan initialization.
132 MemoryMappingLayout
proc_maps(/*cache_enabled*/true);
134 while (proc_maps
.Next(0, 0, 0, filename
, sizeof(filename
), 0)) {
135 if (IsDynamicRTName(filename
)) {
136 Report("Your application is linked against "
137 "incompatible ASan runtimes.\n");
141 __asan_rt_version
= ASAN_RT_VERSION_STATIC
;
142 } else if (__asan_rt_version
!= ASAN_RT_VERSION_STATIC
) {
143 ReportIncompatibleRT();
147 #endif // SANITIZER_ANDROID
149 void GetPcSpBp(void *context
, uptr
*pc
, uptr
*sp
, uptr
*bp
) {
151 ucontext_t
*ucontext
= (ucontext_t
*)context
;
152 *pc
= ucontext
->uc_mcontext
.arm_pc
;
153 *bp
= ucontext
->uc_mcontext
.arm_fp
;
154 *sp
= ucontext
->uc_mcontext
.arm_sp
;
155 #elif defined(__aarch64__)
156 ucontext_t
*ucontext
= (ucontext_t
*)context
;
157 *pc
= ucontext
->uc_mcontext
.pc
;
158 *bp
= ucontext
->uc_mcontext
.regs
[29];
159 *sp
= ucontext
->uc_mcontext
.sp
;
160 #elif defined(__hppa__)
161 ucontext_t
*ucontext
= (ucontext_t
*)context
;
162 *pc
= ucontext
->uc_mcontext
.sc_iaoq
[0];
163 /* GCC uses %r3 whenever a frame pointer is needed. */
164 *bp
= ucontext
->uc_mcontext
.sc_gr
[3];
165 *sp
= ucontext
->uc_mcontext
.sc_gr
[30];
166 #elif defined(__x86_64__)
167 # if SANITIZER_FREEBSD
168 ucontext_t
*ucontext
= (ucontext_t
*)context
;
169 *pc
= ucontext
->uc_mcontext
.mc_rip
;
170 *bp
= ucontext
->uc_mcontext
.mc_rbp
;
171 *sp
= ucontext
->uc_mcontext
.mc_rsp
;
173 ucontext_t
*ucontext
= (ucontext_t
*)context
;
174 *pc
= ucontext
->uc_mcontext
.gregs
[REG_RIP
];
175 *bp
= ucontext
->uc_mcontext
.gregs
[REG_RBP
];
176 *sp
= ucontext
->uc_mcontext
.gregs
[REG_RSP
];
178 #elif defined(__i386__)
179 # if SANITIZER_FREEBSD
180 ucontext_t
*ucontext
= (ucontext_t
*)context
;
181 *pc
= ucontext
->uc_mcontext
.mc_eip
;
182 *bp
= ucontext
->uc_mcontext
.mc_ebp
;
183 *sp
= ucontext
->uc_mcontext
.mc_esp
;
185 ucontext_t
*ucontext
= (ucontext_t
*)context
;
186 *pc
= ucontext
->uc_mcontext
.gregs
[REG_EIP
];
187 *bp
= ucontext
->uc_mcontext
.gregs
[REG_EBP
];
188 *sp
= ucontext
->uc_mcontext
.gregs
[REG_ESP
];
190 #elif defined(__powerpc__) || defined(__powerpc64__)
191 ucontext_t
*ucontext
= (ucontext_t
*)context
;
192 *pc
= ucontext
->uc_mcontext
.regs
->nip
;
193 *sp
= ucontext
->uc_mcontext
.regs
->gpr
[PT_R1
];
194 // The powerpc{,64}-linux ABIs do not specify r31 as the frame
195 // pointer, but GCC always uses r31 when we need a frame pointer.
196 *bp
= ucontext
->uc_mcontext
.regs
->gpr
[PT_R31
];
197 #elif defined(__sparc__)
198 ucontext_t
*ucontext
= (ucontext_t
*)context
;
200 # if defined (__arch64__)
201 *pc
= ucontext
->uc_mcontext
.mc_gregs
[MC_PC
];
202 *sp
= ucontext
->uc_mcontext
.mc_gregs
[MC_O6
];
203 stk_ptr
= (uptr
*) (*sp
+ 2047);
206 *pc
= ucontext
->uc_mcontext
.gregs
[REG_PC
];
207 *sp
= ucontext
->uc_mcontext
.gregs
[REG_O6
];
208 stk_ptr
= (uptr
*) *sp
;
211 #elif defined(__mips__)
212 ucontext_t
*ucontext
= (ucontext_t
*)context
;
213 *pc
= ucontext
->uc_mcontext
.gregs
[31];
214 *bp
= ucontext
->uc_mcontext
.gregs
[30];
215 *sp
= ucontext
->uc_mcontext
.gregs
[29];
217 # error "Unsupported arch"
221 bool AsanInterceptsSignal(int signum
) {
222 return signum
== SIGSEGV
&& common_flags()->handle_segv
;
225 void AsanPlatformThreadInit() {
226 // Nothing here for now.
229 #if !SANITIZER_ANDROID
230 void ReadContextStack(void *context
, uptr
*stack
, uptr
*ssize
) {
231 ucontext_t
*ucp
= (ucontext_t
*)context
;
232 *stack
= (uptr
)ucp
->uc_stack
.ss_sp
;
233 *ssize
= ucp
->uc_stack
.ss_size
;
236 void ReadContextStack(void *context
, uptr
*stack
, uptr
*ssize
) {
241 void *AsanDlSymNext(const char *sym
) {
242 return dlsym(RTLD_NEXT
, sym
);
245 } // namespace __asan
247 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX