diff options
-rw-r--r-- | include/sanitizer/common_interface_defs.h | 7 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc | 19 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/symbolize_pc.cc | 21 |
3 files changed, 47 insertions, 0 deletions
diff --git a/include/sanitizer/common_interface_defs.h b/include/sanitizer/common_interface_defs.h index 1c90a60d7..0ed2bec2e 100644 --- a/include/sanitizer/common_interface_defs.h +++ b/include/sanitizer/common_interface_defs.h @@ -117,6 +117,13 @@ extern "C" { // Print the stack trace leading to this call. Useful for debugging user code. void __sanitizer_print_stack_trace(); + // Symbolizes the supplied 'pc' using the format string 'fmt'. + // Outputs at most 'out_buf_size' bytes into 'out_buf'. + // The format syntax is described in + // lib/sanitizer_common/sanitizer_stacktrace_printer.h. + void __sanitizer_symbolize_pc(void *pc, const char *fmt, char *out_buf, + size_t out_buf_size); + // Sets the callback to be called right before death on error. // Passing 0 will unset the callback. void __sanitizer_set_death_callback(void (*callback)(void)); diff --git a/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc index 59ca927fa..1d5af733c 100644 --- a/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc @@ -83,3 +83,22 @@ void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context, } } // namespace __sanitizer + +extern "C" { +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_symbolize_pc(uptr pc, const char *fmt, char *out_buf, + uptr out_buf_size) { + using namespace __sanitizer; + pc = StackTrace::GetPreviousInstructionPc(pc); + SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); + if (!frame) { + internal_strncpy(out_buf, "<can't symbolize>", out_buf_size); + return; + } + InternalScopedString frame_desc(GetPageSizeCached()); + RenderFrame(&frame_desc, fmt, 0, frame->info, + common_flags()->symbolize_vs_style, + common_flags()->strip_path_prefix); + internal_strncpy(out_buf, frame_desc.data(), out_buf_size); +} +} // extern "C" diff --git a/test/sanitizer_common/TestCases/symbolize_pc.cc b/test/sanitizer_common/TestCases/symbolize_pc.cc new file mode 100644 index 000000000..666f7201e --- /dev/null +++ b/test/sanitizer_common/TestCases/symbolize_pc.cc @@ -0,0 +1,21 @@ +// RUN: %clangxx -O0 %s -o %t +// RUN: %env_tool_opts=strip_path_prefix=/TestCases/ %run %t 2>&1 | FileCheck %s +// +// Tests __sanitizer_symbolize_pc. +#include <stdio.h> +#include <sanitizer/common_interface_defs.h> +void SymbolizeCaller() { + char data[1000]; + __sanitizer_symbolize_pc(__builtin_return_address(0), "%p %F %L", data, + sizeof(data)); + printf("FIRST_FORMAT %s\n", data); + __sanitizer_symbolize_pc(__builtin_return_address(0), + "FUNC:%f LINE:%l FILE:%s", data, sizeof(data)); + printf("SECOND_FORMAT %s\n", data); +} + +// CHECK: FIRST_FORMAT 0x{{.*}} in main symbolize_pc.cc:[[@LINE+3]] +// CHECK: SECOND_FORMAT FUNC:main LINE:[[@LINE+2]] FILE:symbolize_pc.cc +int main() { + SymbolizeCaller(); +} |