From dfc83a04050deffebd697122580a270393be6a7a Mon Sep 17 00:00:00 2001 From: Dmitriy Nikiforov Date: Thu, 11 May 2017 17:24:59 +0300 Subject: [PATCH] [sanitizer-coverage] Add interface for coverage symbolization libsanitizer/ * sanitizer_common/sanitizer_stacktrace_libcdep.cc: (__sanitizer_symbolize_pc): New function. (__sanitizer_get_module_and_offset_for_pc): New function. * include/sanitizer/common_interface_defs.h (__sanitizer_symbolize_pc): Likewise. (__sanitizer_get_module_and_offset_for_pc): Likewise. * sanitizer_common/sanitizer_interface_internal.h (__sanitizer_get_module_and_offset_for_pc): Likewise. Partially backported from LLVM mainline r281886, r279780, r288711, r281668, r281015, r289498. Also, fixed argument names in declarations of __sanitizer_get_module_and_offset_for_pc(). Change-Id: I3722eb8d3e1cd07b6b862f1a4421517b32b22c5a Signed-off-by: Dmitriy Nikiforov --- .../include/sanitizer/common_interface_defs.h | 13 ++++++ .../sanitizer_interface_internal.h | 6 +++ .../sanitizer_stacktrace_libcdep.cc | 47 ++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/libsanitizer/include/sanitizer/common_interface_defs.h b/libsanitizer/include/sanitizer/common_interface_defs.h index 35463e0..a6b16a6 100644 --- a/libsanitizer/include/sanitizer/common_interface_defs.h +++ b/libsanitizer/include/sanitizer/common_interface_defs.h @@ -112,6 +112,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)); @@ -126,6 +133,12 @@ extern "C" { const void *s2, size_t n); void __sanitizer_weak_hook_strncmp(void *called_pc, const char *s1, const char *s2, size_t n); + + // 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_name, + size_t module_name_len, + void **pc_offset); #ifdef __cplusplus } // extern "C" #endif diff --git a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h index 0547f99..9d2d3d0 100644 --- a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h +++ b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h @@ -54,6 +54,12 @@ extern "C" { SANITIZER_INTERFACE_ATTRIBUTE const void *__sanitizer_contiguous_container_find_bad_address( const void *beg, const void *mid, const void *end); + + SANITIZER_INTERFACE_ATTRIBUTE + int __sanitizer_get_module_and_offset_for_pc(__sanitizer::uptr pc, + char *module_name, + __sanitizer::uptr module_name_len, + __sanitizer::uptr *pc_offset); } // extern "C" #endif // SANITIZER_INTERFACE_INTERNAL_H diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc index addf44f..0bdf65f 100644 --- a/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc +++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc @@ -71,4 +71,51 @@ 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; + +extern "C" { +SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_symbolize_pc(uptr pc, const char *fmt, char *out_buf, + uptr out_buf_size) { + if (!out_buf_size) + return; + pc = StackTrace::GetPreviousInstructionPc(pc); + SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); + if (!frame) { + internal_strncpy(out_buf, "", out_buf_size); + out_buf[out_buf_size - 1] = 0; + 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); + 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" -- 2.7.4