summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sanitizer/common_interface_defs.h7
-rw-r--r--lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc19
-rw-r--r--test/sanitizer_common/TestCases/symbolize_pc.cc21
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();
+}