Index: include/sanitizer/common_interface_defs.h =================================================================== --- include/sanitizer/common_interface_defs.h +++ include/sanitizer/common_interface_defs.h @@ -182,6 +182,13 @@ 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 Index: lib/asan/asan_win_dll_thunk.cc =================================================================== --- lib/asan/asan_win_dll_thunk.cc +++ lib/asan/asan_win_dll_thunk.cc @@ -366,6 +366,7 @@ 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. Index: lib/sanitizer_common/sanitizer_common_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_common_libcdep.cc +++ lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -169,6 +169,21 @@ #endif } +static int GetModuleAndOffsetForPc(uptr pc, char *module_name, + uptr module_name_len, uptr *pc_offset) { + ListOfModules modules; + modules.init(); + + const char *found_module_name = nullptr; + bool ok = Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC( + pc, &found_module_name, pc_offset); + + if (!ok) return false; + + internal_strncpy(module_name, found_module_name, module_name_len); + return true; +} + } // namespace __sanitizer void NOINLINE @@ -177,3 +192,13 @@ if (__sanitizer::sandboxing_callback) __sanitizer::sandboxing_callback(); } + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE int +__sanitizer_get_module_and_offset_for_pc(void *pc, // NOLINT + char *module_name, + uptr module_name_len, + void **pc_offset) { + return __sanitizer::GetModuleAndOffsetForPc( + reinterpret_cast(pc), module_name, module_name_len, + reinterpret_cast(pc_offset)); +} Index: test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc =================================================================== --- /dev/null +++ test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc @@ -0,0 +1,28 @@ +// RUN: %clangxx -v -O0 %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: i386-darwin +// +// Tests __sanitizer_get_module_and_offset_for_pc. +#include +#include + +void Test(void *pc) { + 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: %p\n", pc); + } else { + printf("FOUND: %s %p\n", module_name, offset); + } +} + +void TestCallerPc() { Test(__builtin_return_address(0)); } + +int main() { + Test(0); + TestCallerPc(); +} +// CHECK: NOT FOUND: (nil) +// CHECK-NEXT: FOUND: {{.*}}/get_module_and_offset_for_pc.cc.tmp