aboutsummaryrefslogtreecommitdiff
path: root/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2014-09-23 17:59:53 +0000
committerKostya Serebryany <kcc@google.com>2014-09-23 17:59:53 +0000
commit7bfc3daf734dbb13192b8ad6f0a8faf958d647f4 (patch)
treedfe8acd36f160811afc54c8eaf16e8160ba8bd70 /libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
parent22069056fd359931cae41e243b05a6c95470ce6d (diff)
[libsanitizer merge from upstream r218156]
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@215527 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc')
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc155
1 files changed, 27 insertions, 128 deletions
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
index e754b26e693..36aaafdcc4b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -15,23 +15,25 @@
#include "sanitizer_common.h"
#include "sanitizer_flags.h"
+#include "sanitizer_freebsd.h"
#include "sanitizer_linux.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
#include "sanitizer_stacktrace.h"
#include "sanitizer_atomic.h"
+#include "sanitizer_symbolizer.h"
+
+#if SANITIZER_ANDROID || SANITIZER_FREEBSD
+#include <dlfcn.h> // for dlsym()
+#endif
-#include <dlfcn.h>
#include <pthread.h>
#include <signal.h>
#include <sys/resource.h>
-#if SANITIZER_FREEBSD
-#define _GNU_SOURCE // to declare _Unwind_Backtrace() from <unwind.h>
-#endif
-#include <unwind.h>
#if SANITIZER_FREEBSD
#include <pthread_np.h>
+#include <osreldate.h>
#define pthread_getattr_np pthread_attr_get_np
#endif
@@ -147,127 +149,6 @@ bool SanitizerGetThreadName(char *name, int max_len) {
#endif
}
-//------------------------- SlowUnwindStack -----------------------------------
-
-typedef struct {
- uptr absolute_pc;
- uptr stack_top;
- uptr stack_size;
-} backtrace_frame_t;
-
-extern "C" {
-typedef void *(*acquire_my_map_info_list_func)();
-typedef void (*release_my_map_info_list_func)(void *map);
-typedef sptr (*unwind_backtrace_signal_arch_func)(
- void *siginfo, void *sigcontext, void *map_info_list,
- backtrace_frame_t *backtrace, uptr ignore_depth, uptr max_depth);
-acquire_my_map_info_list_func acquire_my_map_info_list;
-release_my_map_info_list_func release_my_map_info_list;
-unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch;
-} // extern "C"
-
-#if SANITIZER_ANDROID
-void SanitizerInitializeUnwinder() {
- void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
- if (!p) {
- VReport(1,
- "Failed to open libcorkscrew.so. You may see broken stack traces "
- "in SEGV reports.");
- return;
- }
- acquire_my_map_info_list =
- (acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
- release_my_map_info_list =
- (release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
- unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
- p, "unwind_backtrace_signal_arch");
- if (!acquire_my_map_info_list || !release_my_map_info_list ||
- !unwind_backtrace_signal_arch) {
- VReport(1,
- "Failed to find one of the required symbols in libcorkscrew.so. "
- "You may see broken stack traces in SEGV reports.");
- acquire_my_map_info_list = NULL;
- unwind_backtrace_signal_arch = NULL;
- release_my_map_info_list = NULL;
- }
-}
-#endif
-
-#ifdef __arm__
-#define UNWIND_STOP _URC_END_OF_STACK
-#define UNWIND_CONTINUE _URC_NO_REASON
-#else
-#define UNWIND_STOP _URC_NORMAL_STOP
-#define UNWIND_CONTINUE _URC_NO_REASON
-#endif
-
-uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
-#ifdef __arm__
- uptr val;
- _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
- 15 /* r15 = PC */, _UVRSD_UINT32, &val);
- CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
- // Clear the Thumb bit.
- return val & ~(uptr)1;
-#else
- return _Unwind_GetIP(ctx);
-#endif
-}
-
-struct UnwindTraceArg {
- StackTrace *stack;
- uptr max_depth;
-};
-
-_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
- UnwindTraceArg *arg = (UnwindTraceArg*)param;
- CHECK_LT(arg->stack->size, arg->max_depth);
- uptr pc = Unwind_GetIP(ctx);
- arg->stack->trace[arg->stack->size++] = pc;
- if (arg->stack->size == arg->max_depth) return UNWIND_STOP;
- return UNWIND_CONTINUE;
-}
-
-void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
- CHECK_GE(max_depth, 2);
- size = 0;
- UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
- _Unwind_Backtrace(Unwind_Trace, &arg);
- // We need to pop a few frames so that pc is on top.
- uptr to_pop = LocatePcInTrace(pc);
- // trace[0] belongs to the current function so we always pop it.
- if (to_pop == 0)
- to_pop = 1;
- PopStackFrames(to_pop);
- trace[0] = pc;
-}
-
-void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
- uptr max_depth) {
- CHECK_GE(max_depth, 2);
- if (!unwind_backtrace_signal_arch) {
- SlowUnwindStack(pc, max_depth);
- return;
- }
-
- void *map = acquire_my_map_info_list();
- CHECK(map);
- InternalScopedBuffer<backtrace_frame_t> frames(kStackTraceMax);
- // siginfo argument appears to be unused.
- sptr res = unwind_backtrace_signal_arch(/* siginfo */ NULL, context, map,
- frames.data(),
- /* ignore_depth */ 0, max_depth);
- release_my_map_info_list(map);
- if (res < 0) return;
- CHECK_LE((uptr)res, kStackTraceMax);
-
- size = 0;
- // +2 compensate for libcorkscrew unwinder returning addresses of call
- // instructions instead of raw return addresses.
- for (sptr i = 0; i < res; ++i)
- trace[size++] = frames[i].absolute_pc + 2;
-}
-
#if !SANITIZER_FREEBSD
static uptr g_tls_size;
#endif
@@ -299,11 +180,11 @@ void InitTlsSize() {
static atomic_uintptr_t kThreadDescriptorSize;
uptr ThreadDescriptorSize() {
- char buf[64];
uptr val = atomic_load(&kThreadDescriptorSize, memory_order_relaxed);
if (val)
return val;
#ifdef _CS_GNU_LIBC_VERSION
+ char buf[64];
uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
if (len < sizeof(buf) && internal_strncmp(buf, "glibc 2.", 8) == 0) {
char *end;
@@ -468,6 +349,10 @@ uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
#else // SANITIZER_ANDROID
# if !SANITIZER_FREEBSD
typedef ElfW(Phdr) Elf_Phdr;
+# elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2
+# define Elf_Phdr XElf32_Phdr
+# define dl_phdr_info xdl_phdr_info
+# define dl_iterate_phdr(c, b) xdl_iterate_phdr((c), (b))
# endif
struct DlIteratePhdrData {
@@ -504,7 +389,8 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
if (phdr->p_type == PT_LOAD) {
uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
uptr cur_end = cur_beg + phdr->p_memsz;
- cur_module->addAddressRange(cur_beg, cur_end);
+ bool executable = phdr->p_flags & PF_X;
+ cur_module->addAddressRange(cur_beg, cur_end, executable);
}
}
return 0;
@@ -527,6 +413,19 @@ void SetIndirectCallWrapper(uptr wrapper) {
indirect_call_wrapper = wrapper;
}
+void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
+ // Some kinds of sandboxes may forbid filesystem access, so we won't be able
+ // to read the file mappings from /proc/self/maps. Luckily, neither the
+ // process will be able to load additional libraries, so it's fine to use the
+ // cached mappings.
+ MemoryMappingLayout::CacheMemoryMappings();
+ // Same for /proc/self/exe in the symbolizer.
+#if !SANITIZER_GO
+ Symbolizer::GetOrInit()->PrepareForSandboxing();
+ CovPrepareForSandboxing(args);
+#endif
+}
+
} // namespace __sanitizer
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX