1 //===-- sanitizer_linux_libcdep.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 shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries and implements linux-specific functions from
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_platform.h"
14 #if SANITIZER_FREEBSD || SANITIZER_LINUX
16 #include "sanitizer_common.h"
17 #include "sanitizer_flags.h"
18 #include "sanitizer_linux.h"
19 #include "sanitizer_placement_new.h"
20 #include "sanitizer_procmaps.h"
21 #include "sanitizer_stacktrace.h"
22 #include "sanitizer_atomic.h"
27 #include <sys/resource.h>
29 #define _GNU_SOURCE // to declare _Unwind_Backtrace() from <unwind.h>
34 #include <pthread_np.h>
35 #define pthread_getattr_np pthread_attr_get_np
39 #include <sys/prctl.h>
42 #if !SANITIZER_ANDROID
48 namespace __sanitizer
{
50 // This function is defined elsewhere if we intercepted pthread_attr_getstack.
52 SANITIZER_WEAK_ATTRIBUTE
int
53 real_pthread_attr_getstack(void *attr
, void **addr
, size_t *size
);
56 static int my_pthread_attr_getstack(void *attr
, void **addr
, size_t *size
) {
57 if (real_pthread_attr_getstack
)
58 return real_pthread_attr_getstack((pthread_attr_t
*)attr
, addr
, size
);
59 return pthread_attr_getstack((pthread_attr_t
*)attr
, addr
, size
);
62 SANITIZER_WEAK_ATTRIBUTE
int
63 real_sigaction(int signum
, const void *act
, void *oldact
);
65 int internal_sigaction(int signum
, const void *act
, void *oldact
) {
67 return real_sigaction(signum
, act
, oldact
);
68 return sigaction(signum
, (struct sigaction
*)act
, (struct sigaction
*)oldact
);
71 void GetThreadStackTopAndBottom(bool at_initialization
, uptr
*stack_top
,
75 if (at_initialization
) {
76 // This is the main thread. Libpthread may not be initialized yet.
78 CHECK_EQ(getrlimit(RLIMIT_STACK
, &rl
), 0);
80 // Find the mapping that contains a stack variable.
81 MemoryMappingLayout
proc_maps(/*cache_enabled*/true);
82 uptr start
, end
, offset
;
84 while (proc_maps
.Next(&start
, &end
, &offset
, 0, 0, /* protection */0)) {
89 CHECK((uptr
)&rl
>= start
&& (uptr
)&rl
< end
);
91 // Get stacksize from rlimit, but clip it so that it does not overlap
92 // with other mappings.
93 uptr stacksize
= rl
.rlim_cur
;
94 if (stacksize
> end
- prev_end
)
95 stacksize
= end
- prev_end
;
96 // When running with unlimited stack size, we still want to set some limit.
97 // The unlimited stack size is caused by 'ulimit -s unlimited'.
98 // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
99 if (stacksize
> kMaxThreadStackSize
)
100 stacksize
= kMaxThreadStackSize
;
102 *stack_bottom
= end
- stacksize
;
106 pthread_attr_init(&attr
);
107 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr
), 0);
110 my_pthread_attr_getstack(&attr
, &stackaddr
, (size_t*)&stacksize
);
111 pthread_attr_destroy(&attr
);
113 CHECK_LE(stacksize
, kMaxThreadStackSize
); // Sanity check.
114 *stack_top
= (uptr
)stackaddr
+ stacksize
;
115 *stack_bottom
= (uptr
)stackaddr
;
118 bool SetEnv(const char *name
, const char *value
) {
119 void *f
= dlsym(RTLD_NEXT
, "setenv");
122 typedef int(*setenv_ft
)(const char *name
, const char *value
, int overwrite
);
124 CHECK_EQ(sizeof(setenv_f
), sizeof(f
));
125 internal_memcpy(&setenv_f
, &f
, sizeof(f
));
126 return IndirectExternCall(setenv_f
)(name
, value
, 1) == 0;
129 bool SanitizerSetThreadName(const char *name
) {
131 return 0 == prctl(PR_SET_NAME
, (unsigned long)name
, 0, 0, 0); // NOLINT
137 bool SanitizerGetThreadName(char *name
, int max_len
) {
140 if (prctl(PR_GET_NAME
, (unsigned long)buff
, 0, 0, 0)) // NOLINT
142 internal_strncpy(name
, buff
, max_len
);
150 //------------------------- SlowUnwindStack -----------------------------------
159 typedef void *(*acquire_my_map_info_list_func
)();
160 typedef void (*release_my_map_info_list_func
)(void *map
);
161 typedef sptr (*unwind_backtrace_signal_arch_func
)(
162 void *siginfo
, void *sigcontext
, void *map_info_list
,
163 backtrace_frame_t
*backtrace
, uptr ignore_depth
, uptr max_depth
);
164 acquire_my_map_info_list_func acquire_my_map_info_list
;
165 release_my_map_info_list_func release_my_map_info_list
;
166 unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch
;
169 #if SANITIZER_ANDROID
170 void SanitizerInitializeUnwinder() {
171 void *p
= dlopen("libcorkscrew.so", RTLD_LAZY
);
174 "Failed to open libcorkscrew.so. You may see broken stack traces "
178 acquire_my_map_info_list
=
179 (acquire_my_map_info_list_func
)(uptr
)dlsym(p
, "acquire_my_map_info_list");
180 release_my_map_info_list
=
181 (release_my_map_info_list_func
)(uptr
)dlsym(p
, "release_my_map_info_list");
182 unwind_backtrace_signal_arch
= (unwind_backtrace_signal_arch_func
)(uptr
)dlsym(
183 p
, "unwind_backtrace_signal_arch");
184 if (!acquire_my_map_info_list
|| !release_my_map_info_list
||
185 !unwind_backtrace_signal_arch
) {
187 "Failed to find one of the required symbols in libcorkscrew.so. "
188 "You may see broken stack traces in SEGV reports.");
189 acquire_my_map_info_list
= NULL
;
190 unwind_backtrace_signal_arch
= NULL
;
191 release_my_map_info_list
= NULL
;
197 #define UNWIND_STOP _URC_END_OF_STACK
198 #define UNWIND_CONTINUE _URC_NO_REASON
200 #define UNWIND_STOP _URC_NORMAL_STOP
201 #define UNWIND_CONTINUE _URC_NO_REASON
204 uptr
Unwind_GetIP(struct _Unwind_Context
*ctx
) {
207 _Unwind_VRS_Result res
= _Unwind_VRS_Get(ctx
, _UVRSC_CORE
,
208 15 /* r15 = PC */, _UVRSD_UINT32
, &val
);
209 CHECK(res
== _UVRSR_OK
&& "_Unwind_VRS_Get failed");
210 // Clear the Thumb bit.
211 return val
& ~(uptr
)1;
213 return _Unwind_GetIP(ctx
);
217 struct UnwindTraceArg
{
222 _Unwind_Reason_Code
Unwind_Trace(struct _Unwind_Context
*ctx
, void *param
) {
223 UnwindTraceArg
*arg
= (UnwindTraceArg
*)param
;
224 CHECK_LT(arg
->stack
->size
, arg
->max_depth
);
225 uptr pc
= Unwind_GetIP(ctx
);
226 arg
->stack
->trace
[arg
->stack
->size
++] = pc
;
227 if (arg
->stack
->size
== arg
->max_depth
) return UNWIND_STOP
;
228 return UNWIND_CONTINUE
;
231 void StackTrace::SlowUnwindStack(uptr pc
, uptr max_depth
) {
232 CHECK_GE(max_depth
, 2);
234 UnwindTraceArg arg
= {this, Min(max_depth
+ 1, kStackTraceMax
)};
235 _Unwind_Backtrace(Unwind_Trace
, &arg
);
236 // We need to pop a few frames so that pc is on top.
237 uptr to_pop
= LocatePcInTrace(pc
);
238 // trace[0] belongs to the current function so we always pop it.
241 PopStackFrames(to_pop
);
245 void StackTrace::SlowUnwindStackWithContext(uptr pc
, void *context
,
247 CHECK_GE(max_depth
, 2);
248 if (!unwind_backtrace_signal_arch
) {
249 SlowUnwindStack(pc
, max_depth
);
253 void *map
= acquire_my_map_info_list();
255 InternalScopedBuffer
<backtrace_frame_t
> frames(kStackTraceMax
);
256 // siginfo argument appears to be unused.
257 sptr res
= unwind_backtrace_signal_arch(/* siginfo */ NULL
, context
, map
,
259 /* ignore_depth */ 0, max_depth
);
260 release_my_map_info_list(map
);
262 CHECK_LE((uptr
)res
, kStackTraceMax
);
265 // +2 compensate for libcorkscrew unwinder returning addresses of call
266 // instructions instead of raw return addresses.
267 for (sptr i
= 0; i
< res
; ++i
)
268 trace
[size
++] = frames
[i
].absolute_pc
+ 2;
271 #if !SANITIZER_FREEBSD
272 static uptr g_tls_size
;
276 # define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
278 # define DL_INTERNAL_FUNCTION
282 #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID
283 typedef void (*get_tls_func
)(size_t*, size_t*) DL_INTERNAL_FUNCTION
;
284 get_tls_func get_tls
;
285 void *get_tls_static_info_ptr
= dlsym(RTLD_NEXT
, "_dl_get_tls_static_info");
286 CHECK_EQ(sizeof(get_tls
), sizeof(get_tls_static_info_ptr
));
287 internal_memcpy(&get_tls
, &get_tls_static_info_ptr
,
288 sizeof(get_tls_static_info_ptr
));
289 CHECK_NE(get_tls
, 0);
291 size_t tls_align
= 0;
292 IndirectExternCall(get_tls
)(&tls_size
, &tls_align
);
293 g_tls_size
= tls_size
;
294 #endif // !SANITIZER_FREEBSD && !SANITIZER_ANDROID
297 #if (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX
298 // sizeof(struct thread) from glibc.
299 static atomic_uintptr_t kThreadDescriptorSize
;
301 uptr
ThreadDescriptorSize() {
303 uptr val
= atomic_load(&kThreadDescriptorSize
, memory_order_relaxed
);
306 #ifdef _CS_GNU_LIBC_VERSION
307 uptr len
= confstr(_CS_GNU_LIBC_VERSION
, buf
, sizeof(buf
));
308 if (len
< sizeof(buf
) && internal_strncmp(buf
, "glibc 2.", 8) == 0) {
310 int minor
= internal_simple_strtoll(buf
+ 8, &end
, 10);
311 if (end
!= buf
+ 8 && (*end
== '\0' || *end
== '.')) {
312 /* sizeof(struct thread) values from various glibc versions. */
314 val
= 1728; // Assume only one particular version for x32.
316 val
= FIRST_32_SECOND_64(1104, 1696);
318 val
= FIRST_32_SECOND_64(1120, 1728);
320 val
= FIRST_32_SECOND_64(1136, 1728);
322 val
= FIRST_32_SECOND_64(1136, 1712);
323 else if (minor
== 10)
324 val
= FIRST_32_SECOND_64(1168, 1776);
325 else if (minor
<= 12)
326 val
= FIRST_32_SECOND_64(1168, 2288);
328 val
= FIRST_32_SECOND_64(1216, 2304);
331 atomic_store(&kThreadDescriptorSize
, val
, memory_order_relaxed
);
338 // The offset at which pointer to self is located in the thread descriptor.
339 const uptr kThreadSelfOffset
= FIRST_32_SECOND_64(8, 16);
341 uptr
ThreadSelfOffset() {
342 return kThreadSelfOffset
;
347 # if defined(__i386__)
348 asm("mov %%gs:%c1,%0" : "=r"(descr_addr
) : "i"(kThreadSelfOffset
));
349 # elif defined(__x86_64__)
350 asm("mov %%fs:%c1,%0" : "=r"(descr_addr
) : "i"(kThreadSelfOffset
));
352 # error "unsupported CPU arch"
356 #endif // (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX
358 #if SANITIZER_FREEBSD
359 static void **ThreadSelfSegbase() {
361 # if defined(__i386__)
362 // sysarch(I386_GET_GSBASE, segbase);
363 __asm
__volatile("mov %%gs:0, %0" : "=r" (segbase
));
364 # elif defined(__x86_64__)
365 // sysarch(AMD64_GET_FSBASE, segbase);
366 __asm
__volatile("movq %%fs:0, %0" : "=r" (segbase
));
368 # error "unsupported CPU arch for FreeBSD platform"
374 return (uptr
)ThreadSelfSegbase()[2];
376 #endif // SANITIZER_FREEBSD
378 static void GetTls(uptr
*addr
, uptr
*size
) {
380 # if defined(__x86_64__) || defined(__i386__)
381 *addr
= ThreadSelf();
382 *size
= GetTlsSize();
384 *addr
+= ThreadDescriptorSize();
389 #elif SANITIZER_FREEBSD
390 void** segbase
= ThreadSelfSegbase();
395 // tls_size = round(tls_static_space, tcbalign);
397 // dtv[2] = segbase - tls_static_space;
398 void **dtv
= (void**) segbase
[1];
399 *addr
= (uptr
) dtv
[2];
400 *size
= (*addr
== 0) ? 0 : ((uptr
) segbase
[0] - (uptr
) dtv
[2]);
408 #if SANITIZER_FREEBSD
410 GetTls(&addr
, &size
);
417 void GetThreadStackAndTls(bool main
, uptr
*stk_addr
, uptr
*stk_size
,
418 uptr
*tls_addr
, uptr
*tls_size
) {
419 GetTls(tls_addr
, tls_size
);
421 uptr stack_top
, stack_bottom
;
422 GetThreadStackTopAndBottom(main
, &stack_top
, &stack_bottom
);
423 *stk_addr
= stack_bottom
;
424 *stk_size
= stack_top
- stack_bottom
;
427 // If stack and tls intersect, make them non-intersecting.
428 if (*tls_addr
> *stk_addr
&& *tls_addr
< *stk_addr
+ *stk_size
) {
429 CHECK_GT(*tls_addr
+ *tls_size
, *stk_addr
);
430 CHECK_LE(*tls_addr
+ *tls_size
, *stk_addr
+ *stk_size
);
431 *stk_size
-= *tls_size
;
432 *tls_addr
= *stk_addr
+ *stk_size
;
437 void AdjustStackSize(void *attr_
) {
438 pthread_attr_t
*attr
= (pthread_attr_t
*)attr_
;
440 size_t stacksize
= 0;
441 my_pthread_attr_getstack(attr
, (void**)&stackaddr
, &stacksize
);
442 // GLibC will return (0 - stacksize) as the stack address in the case when
443 // stacksize is set, but stackaddr is not.
444 bool stack_set
= (stackaddr
!= 0) && (stackaddr
+ stacksize
!= 0);
445 // We place a lot of tool data into TLS, account for that.
446 const uptr minstacksize
= GetTlsSize() + 128*1024;
447 if (stacksize
< minstacksize
) {
449 if (stacksize
!= 0) {
450 VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize
,
452 pthread_attr_setstacksize(attr
, minstacksize
);
455 Printf("Sanitizer: pre-allocated stack size is insufficient: "
456 "%zu < %zu\n", stacksize
, minstacksize
);
457 Printf("Sanitizer: pthread_create is likely to fail.\n");
462 #if SANITIZER_ANDROID
463 uptr
GetListOfModules(LoadedModule
*modules
, uptr max_modules
,
464 string_predicate_t filter
) {
465 MemoryMappingLayout
memory_mapping(false);
466 return memory_mapping
.DumpListOfModules(modules
, max_modules
, filter
);
468 #else // SANITIZER_ANDROID
469 # if !SANITIZER_FREEBSD
470 typedef ElfW(Phdr
) Elf_Phdr
;
473 struct DlIteratePhdrData
{
474 LoadedModule
*modules
;
478 string_predicate_t filter
;
481 static int dl_iterate_phdr_cb(dl_phdr_info
*info
, size_t size
, void *arg
) {
482 DlIteratePhdrData
*data
= (DlIteratePhdrData
*)arg
;
483 if (data
->current_n
== data
->max_n
)
485 InternalScopedBuffer
<char> module_name(kMaxPathLength
);
486 module_name
.data()[0] = '\0';
489 // First module is the binary itself.
490 ReadBinaryName(module_name
.data(), module_name
.size());
491 } else if (info
->dlpi_name
) {
492 internal_strncpy(module_name
.data(), info
->dlpi_name
, module_name
.size());
494 if (module_name
.data()[0] == '\0')
496 if (data
->filter
&& !data
->filter(module_name
.data()))
498 void *mem
= &data
->modules
[data
->current_n
];
499 LoadedModule
*cur_module
= new(mem
) LoadedModule(module_name
.data(),
502 for (int i
= 0; i
< info
->dlpi_phnum
; i
++) {
503 const Elf_Phdr
*phdr
= &info
->dlpi_phdr
[i
];
504 if (phdr
->p_type
== PT_LOAD
) {
505 uptr cur_beg
= info
->dlpi_addr
+ phdr
->p_vaddr
;
506 uptr cur_end
= cur_beg
+ phdr
->p_memsz
;
507 cur_module
->addAddressRange(cur_beg
, cur_end
);
513 uptr
GetListOfModules(LoadedModule
*modules
, uptr max_modules
,
514 string_predicate_t filter
) {
516 DlIteratePhdrData data
= {modules
, 0, true, max_modules
, filter
};
517 dl_iterate_phdr(dl_iterate_phdr_cb
, &data
);
518 return data
.current_n
;
520 #endif // SANITIZER_ANDROID
522 uptr indirect_call_wrapper
;
524 void SetIndirectCallWrapper(uptr wrapper
) {
525 CHECK(!indirect_call_wrapper
);
527 indirect_call_wrapper
= wrapper
;
530 } // namespace __sanitizer
532 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX