summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sanitizer/common_interface_defs.h7
-rw-r--r--lib/asan/asan_win_dll_thunk.cc1
-rw-r--r--lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc22
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc2
-rw-r--r--test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc63
5 files changed, 94 insertions, 1 deletions
diff --git a/include/sanitizer/common_interface_defs.h b/include/sanitizer/common_interface_defs.h
index 130f0f27a..f9f930223 100644
--- a/include/sanitizer/common_interface_defs.h
+++ b/include/sanitizer/common_interface_defs.h
@@ -182,6 +182,13 @@ extern "C" {
void __sanitizer_finish_switch_fiber(void *fake_stack_save,
const void **bottom_old,
size_t *size_old);
+
+ // Get full module name and calculate pc offset within it.
+ // Returns 1 if pc belongs to some module, 0 if module was not found.
+ int __sanitizer_get_module_and_offset_for_pc(void *pc, char *module_path,
+ size_t module_path_len,
+ void **pc_offset);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/lib/asan/asan_win_dll_thunk.cc b/lib/asan/asan_win_dll_thunk.cc
index 668b93d7f..0f629287e 100644
--- a/lib/asan/asan_win_dll_thunk.cc
+++ b/lib/asan/asan_win_dll_thunk.cc
@@ -366,6 +366,7 @@ INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
INTERFACE_FUNCTION(__sanitizer_install_malloc_and_free_hooks)
INTERFACE_FUNCTION(__sanitizer_start_switch_fiber)
INTERFACE_FUNCTION(__sanitizer_finish_switch_fiber)
+INTERFACE_FUNCTION(__sanitizer_get_module_and_offset_for_pc)
// TODO(timurrrr): Add more interface functions on the as-needed basis.
diff --git a/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
index ddf537a7e..36c98d057 100644
--- a/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
@@ -82,6 +82,21 @@ void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context,
}
}
+static int GetModuleAndOffsetForPc(uptr pc, char *module_name,
+ uptr module_name_len, uptr *pc_offset) {
+ const char *found_module_name = nullptr;
+ bool ok = Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC(
+ pc, &found_module_name, pc_offset);
+
+ if (!ok) return false;
+
+ if (module_name && module_name_len) {
+ internal_strncpy(module_name, found_module_name, module_name_len);
+ module_name[module_name_len - 1] = '\x00';
+ }
+ return true;
+}
+
} // namespace __sanitizer
using namespace __sanitizer;
@@ -117,4 +132,11 @@ void __sanitizer_symbolize_global(uptr data_addr, const char *fmt,
internal_strncpy(out_buf, data_desc.data(), out_buf_size);
out_buf[out_buf_size - 1] = 0;
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_get_module_and_offset_for_pc( // NOLINT
+ uptr pc, char *module_name, uptr module_name_len, uptr *pc_offset) {
+ return __sanitizer::GetModuleAndOffsetForPc(pc, module_name, module_name_len,
+ pc_offset);
+}
} // extern "C"
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
index dce73edc9..f50d8b184 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
@@ -55,7 +55,7 @@ const char *DemangleCXXABI(const char *name) {
// own demangler (libc++abi's implementation could be adapted so that
// it does not allocate). For now, we just call it anyway, and we leak
// the returned value.
- if (__cxxabiv1::__cxa_demangle)
+ if (&__cxxabiv1::__cxa_demangle)
if (const char *demangled_name =
__cxxabiv1::__cxa_demangle(name, 0, 0, 0))
return demangled_name;
diff --git a/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc b/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc
new file mode 100644
index 000000000..c95946e6d
--- /dev/null
+++ b/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc
@@ -0,0 +1,63 @@
+// RUN: %clangxx -DSHARED %s -shared -o %T/get_module_and_offset_for_pc.so -fPIC
+// RUN: %clangxx -DSO_DIR=\"%T\" -O0 %s -ldl -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: i386-darwin
+//
+// Tests __sanitizer_get_module_and_offset_for_pc.
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <sanitizer/common_interface_defs.h>
+#include <stdio.h>
+
+#ifdef SHARED
+extern "C" {
+int foo() { return 1; }
+}
+#else
+
+void Test(void *pc, const char *name) {
+ char module_name[1024];
+ void *offset;
+ int ok = __sanitizer_get_module_and_offset_for_pc(
+ pc, module_name, sizeof(module_name), &offset);
+ if (!ok) {
+ printf("NOT FOUND %s: %p\n", name, pc);
+ } else {
+ printf("FOUND %s: %s %p\n", name, module_name, offset);
+ }
+}
+
+void TestCallerPc() { Test(__builtin_return_address(0), "callerpc"); }
+
+void TestDlsym() {
+ void *handle = dlopen(SO_DIR "/get_module_and_offset_for_pc.so", RTLD_LAZY);
+ assert(handle);
+ void *foo = dlsym(handle, "foo");
+ assert(foo);
+ Test(foo, "foo");
+ dlclose(handle);
+}
+
+// Call __sanitizer_get_module_and_offset_for_pc lots of times
+// to make sure it is not too slow.
+void TestLoop() {
+ void *pc = __builtin_return_address(0);
+ char module_name[1024];
+ void *offset;
+ for (int i = 0; i < 1000000; ++i) {
+ __sanitizer_get_module_and_offset_for_pc(pc, module_name,
+ sizeof(module_name), &offset);
+ }
+}
+
+int main() {
+ Test(0, "null");
+ TestCallerPc();
+ TestDlsym();
+ TestLoop();
+}
+#endif
+// CHECK: NOT FOUND null: (nil)
+// CHECK-NEXT: FOUND callerpc: {{.*}}/get_module_and_offset_for_pc.cc.tmp {{.*}}
+// CHECK-NEXT: FOUND foo: {{.*}}/get_module_and_offset_for_pc.so {{.*}}