[sanitizer_common] Fuchsia-specific symbolizer

Summary:
Fuchsia doesn't support built-in symbolization per se at all.
Instead, it always emits a Fuchsia-standard "symbolizer markup"
format that makes it possible for a post-processing filter to
massage the logs into symbolized format.  Hence, it does not
support user-specified formatting options for backtraces or other
symbolization.

Reviewers: vitalybuka, alekseyshl, kcc

Subscribers: kubamracek, mgorny, phosek, filcab, llvm-commits

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D36032

llvm-svn: 309760
This commit is contained in:
Vitaly Buka 2017-08-01 22:54:51 +00:00
parent 4cad61adb3
commit f4891c2a66
4 changed files with 130 additions and 9 deletions

View File

@ -31,6 +31,7 @@ set(SANITIZER_SOURCES_NOTERMINATION
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

View File

@ -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 @@ void RenderData(InternalScopedString *buffer, const char *format,
}
}
#endif // !SANITIZER_FUCHSIA
void RenderSourceLocation(InternalScopedString *buffer, const char *file,
int line, int column, bool vs_style,
const char *strip_path_prefix) {

View File

@ -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

View File

@ -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 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
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
// <module_name> <module_offset>
@ -472,4 +475,6 @@ bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {
return true;
}
#endif // !SANITIZER_FUCHSIA
} // namespace __sanitizer