Index: lib/sanitizer_common/CMakeLists.txt =================================================================== --- lib/sanitizer_common/CMakeLists.txt +++ lib/sanitizer_common/CMakeLists.txt @@ -31,6 +31,7 @@ sanitizer_stoptheworld_mac.cc sanitizer_suppressions.cc sanitizer_symbolizer.cc + sanitizer_symbolizer_fuchsia.cc sanitizer_symbolizer_libbacktrace.cc sanitizer_symbolizer_mac.cc sanitizer_symbolizer_win.cc Index: lib/sanitizer_common/sanitizer_stacktrace_printer.cc =================================================================== --- lib/sanitizer_common/sanitizer_stacktrace_printer.cc +++ lib/sanitizer_common/sanitizer_stacktrace_printer.cc @@ -13,9 +13,13 @@ #include "sanitizer_stacktrace_printer.h" #include "sanitizer_file.h" +#include "sanitizer_fuchsia.h" namespace __sanitizer { +// sanitizer_symbolizer_fuchsia.cc implements these differently for Fuchsia. +#if !SANITIZER_FUCHSIA + static const char *StripFunctionName(const char *function, const char *prefix) { if (!function) return nullptr; if (!prefix) return function; @@ -147,6 +151,8 @@ } } +#endif // !SANITIZER_FUCHSIA + void RenderSourceLocation(InternalScopedString *buffer, const char *file, int line, int column, bool vs_style, const char *strip_path_prefix) { Index: lib/sanitizer_common/sanitizer_symbolizer_fuchsia.cc =================================================================== --- /dev/null +++ lib/sanitizer_common/sanitizer_symbolizer_fuchsia.cc @@ -0,0 +1,109 @@ +//===-- sanitizer_symbolizer_fuchsia.cc -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is shared between various sanitizers' runtime libraries. +// +// Implementation of Fuchsia-specific symbolizer. +//===----------------------------------------------------------------------===// + +#include "sanitizer_platform.h" +#if SANITIZER_FUCHSIA + +#include "sanitizer_fuchsia.h" +#include "sanitizer_symbolizer.h" + +namespace __sanitizer { + +// For Fuchsia we don't do any actual symbolization per se. +// Instead, we emit text containing raw addresses and raw linkage +// symbol names, embedded in Fuchsia's symbolization markup format. +// Fuchsia's logging infrastructure emits enough information about +// process memory layout that a post-processing filter can do the +// symbolization and pretty-print the markup. +// TODO(mcgrathr): URL to markup format document + +// This is used by UBSan for type names, and by ASan for global variable names. +constexpr const char *kFormatDemangle = "{{{symbol:%s}}}"; +constexpr uptr kFormatDemangleMax = 1024; // Arbitrary. + +// Function name or equivalent from PC location. +constexpr const char *kFormatFunction = "{{{pc:%p}}}"; +constexpr uptr kFormatFunctionMax = 64; // More than big enough for 64-bit hex. + +// Global variable name or equivalent from data memory address. +constexpr const char *kFormatData = "{{{data:%p}}}"; + +// One frame in a backtrace (printed on a line by itself). +constexpr const char *kFormatFrame = "{{{bt:%u:%p}}}"; + +// This is used by UBSan for type names, and by ASan for global variable names. +// It's expected to return a static buffer that will be reused on each call. +const char *Symbolizer::Demangle(const char *name) { + static char buffer[kFormatDemangleMax]; + internal_snprintf(buffer, sizeof(buffer), kFormatDemangle, name); + return buffer; +} + +// This is used mostly for suppression matching. Making it work +// would enable "interceptor_via_lib" suppressions. It's also used +// once in UBSan to say "in module ..." in a message that also +// includes an address in the module, so post-processing can already +// pretty-print that so as to indicate the module. +bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, + uptr *module_address) { + return false; +} + +// This is used in some places for suppression checking, which we +// don't really support for Fuchsia. It's also used in UBSan to +// identify a PC location to a function name, so we always fill in +// the function member with a string containing markup around the PC +// value. +// TODO(mcgrathr): Under SANITIZER_GO, it's currently used by TSan +// to render stack frames, but that should be changed to use +// RenderStackFrame. +SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) { + SymbolizedStack *s = SymbolizedStack::New(addr); + char buffer[kFormatFunctionMax]; + internal_snprintf(buffer, sizeof(buffer), kFormatFunction, addr); + s->info.function = internal_strdup(buffer); + return s; +} + +// Always claim we succeeded, so that RenderDataInfo will be called. +bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) { + info->Clear(); + info->start = addr; + return true; +} + +// We ignore the format argument to __sanitizer_symbolize_global. +void RenderData(InternalScopedString *buffer, const char *format, + const DataInfo *DI, const char *strip_path_prefix) { + buffer->append(kFormatData, DI->start); +} + +// We don't support the stack_trace_format flag at all. +void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, + const AddressInfo &info, bool vs_style, + const char *strip_path_prefix, const char *strip_func_prefix) { + buffer->append(kFormatFrame, frame_no, info.address); +} + +Symbolizer *Symbolizer::PlatformInit() { + return new(symbolizer_allocator_) Symbolizer({}); +} + +void Symbolizer::LateInitialize() { + Symbolizer::GetOrInit(); +} + +} // namespace __sanitizer + +#endif // SANITIZER_FUCHSIA Index: lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc @@ -17,6 +17,18 @@ namespace __sanitizer { +Symbolizer *Symbolizer::GetOrInit() { + SpinMutexLock l(&init_mu_); + if (symbolizer_) + return symbolizer_; + symbolizer_ = PlatformInit(); + CHECK(symbolizer_); + return symbolizer_; +} + +// See sanitizer_symbolizer_fuchsia.cc. +#if !SANITIZER_FUCHSIA + const char *ExtractToken(const char *str, const char *delims, char **result) { uptr prefix_len = internal_strcspn(str, delims); *result = (char*)InternalAlloc(prefix_len + 1); @@ -175,15 +187,6 @@ return 0; } -Symbolizer *Symbolizer::GetOrInit() { - SpinMutexLock l(&init_mu_); - if (symbolizer_) - return symbolizer_; - symbolizer_ = PlatformInit(); - CHECK(symbolizer_); - return symbolizer_; -} - // For now we assume the following protocol: // For each request of the form // @@ -472,4 +475,6 @@ return true; } +#endif // !SANITIZER_FUCHSIA + } // namespace __sanitizer