1088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne//===-- sanitizer_linux_libcdep.cc ----------------------------------------===// 2088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// 3088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// The LLVM Compiler Infrastructure 4088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// 5088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// This file is distributed under the University of Illinois Open Source 6088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// License. See LICENSE.TXT for details. 7088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// 8088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne//===----------------------------------------------------------------------===// 9088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// 10088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// This file is shared between AddressSanitizer and ThreadSanitizer 11088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// run-time libraries and implements linux-specific functions from 12088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// sanitizer_libc.h. 13088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne//===----------------------------------------------------------------------===// 14088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 15088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include "sanitizer_platform.h" 162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD || SANITIZER_LINUX 17088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 18088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include "sanitizer_common.h" 1906cbed8b8ae64b7ace50c1b4e4eed97a2a8b9965Dmitry Vyukov#include "sanitizer_flags.h" 207847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#include "sanitizer_linux.h" 217847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#include "sanitizer_placement_new.h" 22088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include "sanitizer_procmaps.h" 23088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include "sanitizer_stacktrace.h" 242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_atomic.h" 252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_symbolizer.h" 26088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 27088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include <dlfcn.h> 28088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include <pthread.h> 292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <signal.h> 30088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include <sys/resource.h> 312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define _GNU_SOURCE // to declare _Unwind_Backtrace() from <unwind.h> 332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 34088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#include <unwind.h> 35088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <pthread_np.h> 382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define pthread_getattr_np pthread_attr_get_np 392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX 422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <sys/prctl.h> 432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 457847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#if !SANITIZER_ANDROID 467847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#include <elf.h> 477847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#include <link.h> 482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <unistd.h> 497847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#endif 507847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 51088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbournenamespace __sanitizer { 52088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This function is defined elsewhere if we intercepted pthread_attr_getstack. 542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" { 552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesSANITIZER_WEAK_ATTRIBUTE int 562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesreal_pthread_attr_getstack(void *attr, void **addr, size_t *size); 572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // extern "C" 582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) { 602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (real_pthread_attr_getstack) 612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, size); 622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return pthread_attr_getstack((pthread_attr_t *)attr, addr, size); 632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesSANITIZER_WEAK_ATTRIBUTE int 662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesreal_sigaction(int signum, const void *act, void *oldact); 672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint internal_sigaction(int signum, const void *act, void *oldact) { 692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (real_sigaction) 702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return real_sigaction(signum, act, oldact); 712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return sigaction(signum, (struct sigaction *)act, (struct sigaction *)oldact); 722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 74088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbournevoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 75088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne uptr *stack_bottom) { 76088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK(stack_top); 77088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK(stack_bottom); 78088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if (at_initialization) { 79088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // This is the main thread. Libpthread may not be initialized yet. 80088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne struct rlimit rl; 81088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0); 82088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 83088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // Find the mapping that contains a stack variable. 84088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne MemoryMappingLayout proc_maps(/*cache_enabled*/true); 85088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne uptr start, end, offset; 86088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne uptr prev_end = 0; 87088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) { 88088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if ((uptr)&rl < end) 89088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne break; 90088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne prev_end = end; 91088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne } 92088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK((uptr)&rl >= start && (uptr)&rl < end); 93088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 94088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // Get stacksize from rlimit, but clip it so that it does not overlap 95088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // with other mappings. 96088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne uptr stacksize = rl.rlim_cur; 97088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if (stacksize > end - prev_end) 98088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne stacksize = end - prev_end; 99088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // When running with unlimited stack size, we still want to set some limit. 100088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // The unlimited stack size is caused by 'ulimit -s unlimited'. 101088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // Also, for some reason, GNU make spawns subprocesses with unlimited stack. 102088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if (stacksize > kMaxThreadStackSize) 103088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne stacksize = kMaxThreadStackSize; 104088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne *stack_top = end; 105088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne *stack_bottom = end - stacksize; 106088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return; 107088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne } 108088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne pthread_attr_t attr; 1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines pthread_attr_init(&attr); 110088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0); 111088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne uptr stacksize = 0; 112088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne void *stackaddr = 0; 1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines my_pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize); 114088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne pthread_attr_destroy(&attr); 115088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 116933a5d2fd96e8758dd12890ed263def8e80f6f02Evgeniy Stepanov CHECK_LE(stacksize, kMaxThreadStackSize); // Sanity check. 117088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne *stack_top = (uptr)stackaddr + stacksize; 118088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne *stack_bottom = (uptr)stackaddr; 119088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 120088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 121088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbournebool SetEnv(const char *name, const char *value) { 122088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne void *f = dlsym(RTLD_NEXT, "setenv"); 123088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if (f == 0) 124088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return false; 125088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne typedef int(*setenv_ft)(const char *name, const char *value, int overwrite); 126088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne setenv_ft setenv_f; 127088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK_EQ(sizeof(setenv_f), sizeof(f)); 128088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne internal_memcpy(&setenv_f, &f, sizeof(f)); 1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return IndirectExternCall(setenv_f)(name, value, 1) == 0; 130088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 131088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 132088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbournebool SanitizerSetThreadName(const char *name) { 133088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#ifdef PR_SET_NAME 134088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); // NOLINT 135088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#else 136088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return false; 137088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#endif 138088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 139088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 140088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbournebool SanitizerGetThreadName(char *name, int max_len) { 141088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#ifdef PR_GET_NAME 142088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne char buff[17]; 143088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0)) // NOLINT 144088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return false; 145088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne internal_strncpy(name, buff, max_len); 146088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne name[max_len] = 0; 147088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return true; 148088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#else 149088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return false; 150088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#endif 151088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 152088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 153088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne//------------------------- SlowUnwindStack ----------------------------------- 1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestypedef struct { 1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr absolute_pc; 1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr stack_top; 1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr stack_size; 1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} backtrace_frame_t; 1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" { 1622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestypedef void *(*acquire_my_map_info_list_func)(); 1632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestypedef void (*release_my_map_info_list_func)(void *map); 1642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestypedef sptr (*unwind_backtrace_signal_arch_func)( 1652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *siginfo, void *sigcontext, void *map_info_list, 1662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines backtrace_frame_t *backtrace, uptr ignore_depth, uptr max_depth); 1672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesacquire_my_map_info_list_func acquire_my_map_info_list; 1682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesrelease_my_map_info_list_func release_my_map_info_list; 1692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesunwind_backtrace_signal_arch_func unwind_backtrace_signal_arch; 1702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // extern "C" 1712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_ANDROID 1732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid SanitizerInitializeUnwinder() { 1742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *p = dlopen("libcorkscrew.so", RTLD_LAZY); 1752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!p) { 1762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VReport(1, 1772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines "Failed to open libcorkscrew.so. You may see broken stack traces " 1782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines "in SEGV reports."); 1792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines acquire_my_map_info_list = 1822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list"); 1832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines release_my_map_info_list = 1842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list"); 1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym( 1862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines p, "unwind_backtrace_signal_arch"); 1872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!acquire_my_map_info_list || !release_my_map_info_list || 1882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines !unwind_backtrace_signal_arch) { 1892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VReport(1, 1902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines "Failed to find one of the required symbols in libcorkscrew.so. " 1912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines "You may see broken stack traces in SEGV reports."); 1922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines acquire_my_map_info_list = NULL; 1932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines unwind_backtrace_signal_arch = NULL; 1942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines release_my_map_info_list = NULL; 1952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 1982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 199088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#ifdef __arm__ 200088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#define UNWIND_STOP _URC_END_OF_STACK 201088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#define UNWIND_CONTINUE _URC_NO_REASON 202088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#else 203088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#define UNWIND_STOP _URC_NORMAL_STOP 204088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#define UNWIND_CONTINUE _URC_NO_REASON 205088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#endif 206088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 207088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourneuptr Unwind_GetIP(struct _Unwind_Context *ctx) { 208088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#ifdef __arm__ 209088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne uptr val; 210088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE, 211088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 15 /* r15 = PC */, _UVRSD_UINT32, &val); 212088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed"); 213088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // Clear the Thumb bit. 214088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return val & ~(uptr)1; 215088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#else 216088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return _Unwind_GetIP(ctx); 217088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#endif 218088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 219088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 2203e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonovstruct UnwindTraceArg { 2213e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov StackTrace *stack; 2223e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov uptr max_depth; 2233e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov}; 2243e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov 225088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { 2263e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov UnwindTraceArg *arg = (UnwindTraceArg*)param; 2273e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov CHECK_LT(arg->stack->size, arg->max_depth); 228088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne uptr pc = Unwind_GetIP(ctx); 2293e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov arg->stack->trace[arg->stack->size++] = pc; 2303e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov if (arg->stack->size == arg->max_depth) return UNWIND_STOP; 231088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne return UNWIND_CONTINUE; 232088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 233088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 234088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbournevoid StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) { 2352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_GE(max_depth, 2); 2363e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov size = 0; 2374b9f050c2acab536356342ab96e6cc76c281ac24Alexey Samsonov UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)}; 2384b9f050c2acab536356342ab96e6cc76c281ac24Alexey Samsonov _Unwind_Backtrace(Unwind_Trace, &arg); 2394b9f050c2acab536356342ab96e6cc76c281ac24Alexey Samsonov // We need to pop a few frames so that pc is on top. 2406a58b0078a94195f963fede873068d7a0982c509Alexey Samsonov uptr to_pop = LocatePcInTrace(pc); 2414b9f050c2acab536356342ab96e6cc76c281ac24Alexey Samsonov // trace[0] belongs to the current function so we always pop it. 2427177d2bbb5850fb499d3e8910b2e05f5c6b025b0Timur Iskhodzhanov if (to_pop == 0) 2437177d2bbb5850fb499d3e8910b2e05f5c6b025b0Timur Iskhodzhanov to_pop = 1; 2444b9f050c2acab536356342ab96e6cc76c281ac24Alexey Samsonov PopStackFrames(to_pop); 2453e0b8ff07e86e0858e016d187d842e97aea2255dAlexey Samsonov trace[0] = pc; 246088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 247088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 2482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid StackTrace::SlowUnwindStackWithContext(uptr pc, void *context, 2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr max_depth) { 2502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_GE(max_depth, 2); 2512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!unwind_backtrace_signal_arch) { 2522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SlowUnwindStack(pc, max_depth); 2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 2552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *map = acquire_my_map_info_list(); 2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK(map); 2582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines InternalScopedBuffer<backtrace_frame_t> frames(kStackTraceMax); 2592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // siginfo argument appears to be unused. 2602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines sptr res = unwind_backtrace_signal_arch(/* siginfo */ NULL, context, map, 2612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines frames.data(), 2622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines /* ignore_depth */ 0, max_depth); 2632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines release_my_map_info_list(map); 2642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (res < 0) return; 2652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_LE((uptr)res, kStackTraceMax); 2662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines size = 0; 2682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // +2 compensate for libcorkscrew unwinder returning addresses of call 2692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // instructions instead of raw return addresses. 2702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (sptr i = 0; i < res; ++i) 2712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines trace[size++] = frames[i].absolute_pc + 2; 2722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 273088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 2742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD 275088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbournestatic uptr g_tls_size; 2762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 277088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 278088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#ifdef __i386__ 279088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall)) 280088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#else 281088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne# define DL_INTERNAL_FUNCTION 282088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#endif 283088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 284088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbournevoid InitTlsSize() { 2852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID 286088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION; 287088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne get_tls_func get_tls; 288088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); 289088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr)); 290088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne internal_memcpy(&get_tls, &get_tls_static_info_ptr, 291088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne sizeof(get_tls_static_info_ptr)); 292088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK_NE(get_tls, 0); 293088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne size_t tls_size = 0; 294088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne size_t tls_align = 0; 2952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines IndirectExternCall(get_tls)(&tls_size, &tls_align); 296088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne g_tls_size = tls_size; 2972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // !SANITIZER_FREEBSD && !SANITIZER_ANDROID 298088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 299088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 3002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX 301088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne// sizeof(struct thread) from glibc. 3022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic atomic_uintptr_t kThreadDescriptorSize; 303088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 304088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourneuptr ThreadDescriptorSize() { 3052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr val = atomic_load(&kThreadDescriptorSize, memory_order_relaxed); 3062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (val) 3072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return val; 3082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#ifdef _CS_GNU_LIBC_VERSION 3095d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines char buf[64]; 3102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf)); 3112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (len < sizeof(buf) && internal_strncmp(buf, "glibc 2.", 8) == 0) { 3122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines char *end; 3132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int minor = internal_simple_strtoll(buf + 8, &end, 10); 3142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (end != buf + 8 && (*end == '\0' || *end == '.')) { 3152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines /* sizeof(struct thread) values from various glibc versions. */ 3162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (SANITIZER_X32) 3172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines val = 1728; // Assume only one particular version for x32. 3182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines else if (minor <= 3) 3192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines val = FIRST_32_SECOND_64(1104, 1696); 3202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines else if (minor == 4) 3212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines val = FIRST_32_SECOND_64(1120, 1728); 3222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines else if (minor == 5) 3232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines val = FIRST_32_SECOND_64(1136, 1728); 3242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines else if (minor <= 9) 3252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines val = FIRST_32_SECOND_64(1136, 1712); 3262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines else if (minor == 10) 3272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines val = FIRST_32_SECOND_64(1168, 1776); 3282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines else if (minor <= 12) 3292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines val = FIRST_32_SECOND_64(1168, 2288); 3302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines else 3312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines val = FIRST_32_SECOND_64(1216, 2304); 3322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 3332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (val) 3342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed); 3352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return val; 3362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 3372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 3382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return 0; 339088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 3404c086441ff9d06e53fa941671781008d453dba49Sergey Matveev 3414c086441ff9d06e53fa941671781008d453dba49Sergey Matveev// The offset at which pointer to self is located in the thread descriptor. 3424c086441ff9d06e53fa941671781008d453dba49Sergey Matveevconst uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16); 3434c086441ff9d06e53fa941671781008d453dba49Sergey Matveev 3444c086441ff9d06e53fa941671781008d453dba49Sergey Matveevuptr ThreadSelfOffset() { 3454c086441ff9d06e53fa941671781008d453dba49Sergey Matveev return kThreadSelfOffset; 3464c086441ff9d06e53fa941671781008d453dba49Sergey Matveev} 3474c086441ff9d06e53fa941671781008d453dba49Sergey Matveev 3484c086441ff9d06e53fa941671781008d453dba49Sergey Matveevuptr ThreadSelf() { 3494c086441ff9d06e53fa941671781008d453dba49Sergey Matveev uptr descr_addr; 3502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# if defined(__i386__) 3514c086441ff9d06e53fa941671781008d453dba49Sergey Matveev asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); 3522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# elif defined(__x86_64__) 3534c086441ff9d06e53fa941671781008d453dba49Sergey Matveev asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); 3542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# else 3552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# error "unsupported CPU arch" 3562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# endif 3574c086441ff9d06e53fa941671781008d453dba49Sergey Matveev return descr_addr; 3584c086441ff9d06e53fa941671781008d453dba49Sergey Matveev} 3592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX 3602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 3612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 3622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void **ThreadSelfSegbase() { 3632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void **segbase = 0; 3642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# if defined(__i386__) 3652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // sysarch(I386_GET_GSBASE, segbase); 3662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __asm __volatile("mov %%gs:0, %0" : "=r" (segbase)); 3672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# elif defined(__x86_64__) 3682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // sysarch(AMD64_GET_FSBASE, segbase); 3692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __asm __volatile("movq %%fs:0, %0" : "=r" (segbase)); 3702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# else 3712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# error "unsupported CPU arch for FreeBSD platform" 3722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# endif 3732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return segbase; 3742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 375088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 3762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr ThreadSelf() { 3772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return (uptr)ThreadSelfSegbase()[2]; 3782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 3792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // SANITIZER_FREEBSD 3802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 3812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void GetTls(uptr *addr, uptr *size) { 3822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LINUX 3832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# if defined(__x86_64__) || defined(__i386__) 3842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *addr = ThreadSelf(); 3852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *size = GetTlsSize(); 3862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *addr -= *size; 3872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *addr += ThreadDescriptorSize(); 3882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# else 3892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *addr = 0; 3902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *size = 0; 3912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# endif 3922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#elif SANITIZER_FREEBSD 3932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void** segbase = ThreadSelfSegbase(); 3942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *addr = 0; 3952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *size = 0; 3962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (segbase != 0) { 3972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // tcbalign = 16 3982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // tls_size = round(tls_static_space, tcbalign); 3992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // dtv = segbase[1]; 4002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // dtv[2] = segbase - tls_static_space; 4012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void **dtv = (void**) segbase[1]; 4022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *addr = (uptr) dtv[2]; 4032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines *size = (*addr == 0) ? 0 : ((uptr) segbase[0] - (uptr) dtv[2]); 4042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 405088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#else 4062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# error "Unknown OS" 407088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne#endif 4082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 4092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 4102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr GetTlsSize() { 4112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_FREEBSD 4122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr addr, size; 4132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines GetTls(&addr, &size); 4142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return size; 4152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else 4162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return g_tls_size; 4172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 4182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 4192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 4202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, 4212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr *tls_addr, uptr *tls_size) { 4222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines GetTls(tls_addr, tls_size); 423088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 424088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne uptr stack_top, stack_bottom; 425088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); 426088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne *stk_addr = stack_bottom; 427088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne *stk_size = stack_top - stack_bottom; 428088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 429088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if (!main) { 430088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // If stack and tls intersect, make them non-intersecting. 431088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) { 432088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK_GT(*tls_addr + *tls_size, *stk_addr); 433088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size); 434088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne *stk_size -= *tls_size; 435088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne *tls_addr = *stk_addr + *stk_size; 436088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne } 437088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne } 438088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 439088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 4402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AdjustStackSize(void *attr_) { 441088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne pthread_attr_t *attr = (pthread_attr_t *)attr_; 442088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne uptr stackaddr = 0; 443088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne size_t stacksize = 0; 4442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize); 445088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // GLibC will return (0 - stacksize) as the stack address in the case when 446088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // stacksize is set, but stackaddr is not. 447088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0); 448088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne // We place a lot of tool data into TLS, account for that. 449088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne const uptr minstacksize = GetTlsSize() + 128*1024; 450088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if (stacksize < minstacksize) { 451088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne if (!stack_set) { 4522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (stacksize != 0) { 4532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize, 4542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines minstacksize); 4552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines pthread_attr_setstacksize(attr, minstacksize); 4562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 457088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne } else { 458088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne Printf("Sanitizer: pre-allocated stack size is insufficient: " 459088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne "%zu < %zu\n", stacksize, minstacksize); 460088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne Printf("Sanitizer: pthread_create is likely to fail.\n"); 461088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne } 462088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne } 463088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} 464088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 4657847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#if SANITIZER_ANDROID 4667847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovuptr GetListOfModules(LoadedModule *modules, uptr max_modules, 4677847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov string_predicate_t filter) { 4682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryMappingLayout memory_mapping(false); 4692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return memory_mapping.DumpListOfModules(modules, max_modules, filter); 4707847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 4717847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#else // SANITIZER_ANDROID 4722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# if !SANITIZER_FREEBSD 4737847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovtypedef ElfW(Phdr) Elf_Phdr; 4742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# endif 4757847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 4767847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstruct DlIteratePhdrData { 4777847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov LoadedModule *modules; 4787847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov uptr current_n; 4797847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov bool first; 4807847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov uptr max_n; 4817847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov string_predicate_t filter; 4827847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov}; 4837847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 4847847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovstatic int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { 4857847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov DlIteratePhdrData *data = (DlIteratePhdrData*)arg; 4867847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov if (data->current_n == data->max_n) 4877847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov return 0; 4887847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov InternalScopedBuffer<char> module_name(kMaxPathLength); 4897847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov module_name.data()[0] = '\0'; 4907847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov if (data->first) { 4917847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov data->first = false; 4927847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov // First module is the binary itself. 4937847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov ReadBinaryName(module_name.data(), module_name.size()); 4947847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } else if (info->dlpi_name) { 4957847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov internal_strncpy(module_name.data(), info->dlpi_name, module_name.size()); 4967847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 4977847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov if (module_name.data()[0] == '\0') 4987847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov return 0; 4997847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov if (data->filter && !data->filter(module_name.data())) 5007847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov return 0; 5017847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov void *mem = &data->modules[data->current_n]; 5027847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov LoadedModule *cur_module = new(mem) LoadedModule(module_name.data(), 5037847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov info->dlpi_addr); 5047847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov data->current_n++; 5057847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov for (int i = 0; i < info->dlpi_phnum; i++) { 5067847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov const Elf_Phdr *phdr = &info->dlpi_phdr[i]; 5077847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov if (phdr->p_type == PT_LOAD) { 5087847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov uptr cur_beg = info->dlpi_addr + phdr->p_vaddr; 5097847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov uptr cur_end = cur_beg + phdr->p_memsz; 5105d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines bool executable = phdr->p_flags & PF_X; 5115d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines cur_module->addAddressRange(cur_beg, cur_end, executable); 5127847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 5137847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov } 5147847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov return 0; 5157847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 5167847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 5177847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonovuptr GetListOfModules(LoadedModule *modules, uptr max_modules, 5187847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov string_predicate_t filter) { 5197847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov CHECK(modules); 5207847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov DlIteratePhdrData data = {modules, 0, true, max_modules, filter}; 5217847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov dl_iterate_phdr(dl_iterate_phdr_cb, &data); 5227847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov return data.current_n; 5237847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov} 5247847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov#endif // SANITIZER_ANDROID 5257847d77b246635211c3bf465421d49d7af5226c1Alexey Samsonov 5262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr indirect_call_wrapper; 5272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 5282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid SetIndirectCallWrapper(uptr wrapper) { 5292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK(!indirect_call_wrapper); 5302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK(wrapper); 5312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines indirect_call_wrapper = wrapper; 5322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 5332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 5342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { 5352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Some kinds of sandboxes may forbid filesystem access, so we won't be able 5362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // to read the file mappings from /proc/self/maps. Luckily, neither the 5372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // process will be able to load additional libraries, so it's fine to use the 5382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // cached mappings. 5392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryMappingLayout::CacheMemoryMappings(); 5402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Same for /proc/self/exe in the symbolizer. 5412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !SANITIZER_GO 5422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (Symbolizer *sym = Symbolizer::GetOrNull()) 5432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines sym->PrepareForSandboxing(); 5442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CovPrepareForSandboxing(args); 5452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif 5462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 5472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 548088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne} // namespace __sanitizer 549088ea2b46f97172bd0b0663a629e11cf826b84f7Peter Collingbourne 5502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // SANITIZER_FREEBSD || SANITIZER_LINUX 551