On Mon, Nov 18, 2013 at 07:50:33PM +0400, Alexey Samsonov wrote: > On Mon, Nov 18, 2013 at 7:49 PM, Alexey Samsonov <samso...@google.com> wrote: > Unfortunately, recently there were a few enhancements to > sanitizer_symbolizer_posix_libcdep.cc (and friends), > in LLVM trunk, and now it looks different from gcc version (apparently, the > changes were committed > after the merge to gcc happened, I should have pointed this out earlier, > sorry). > > Kostya (or Jakub), is it possible to somehow pick up the changes? Otherwise > this patch can't go in ASan runtime > in gcc - the code will significantly diverge.
Here is an (untested) forward port of the patch to what is in llvm svn right now. The unpatched code always had either internal_symbolizer_ != NULL, or external_symbolizer_ != NULL, or both NULL, but not both set. The patch just adds a third variant, libbacktrace_symbolizer_, again, at most one of the 3 will be non-NULL, and the priorities are that internal_symbolizer_ has highest priority, then libbacktrace (if available/usable), then the external one. --- sanitizer_symbolizer_posix_libcdep.cc.jj 2013-11-12 19:35:30.000000000 +0100 +++ sanitizer_symbolizer_posix_libcdep.cc 2013-11-18 17:16:03.202643957 +0100 @@ -27,6 +27,16 @@ #include <sys/wait.h> #include <unistd.h> +#ifdef SANITIZER_LIBBACKTRACE +#include "backtrace-supported.h" +#if SANITIZER_LINUX && BACKTRACE_SUPPORTED \ + && !BACKTRACE_USES_MALLOC && BACKTRACE_SUPPORTS_THREADS +#include "backtrace.h" +#else +#undef SANITIZER_LIBBACKTRACE +#endif +#endif + // C++ demangling function, as required by Itanium C++ ABI. This is weak, // because we do not require a C++ ABI library to be linked to a program // using sanitizers; if it's not present, we'll just use the mangled name. @@ -364,12 +374,124 @@ class InternalSymbolizer { #endif // SANITIZER_SUPPORTS_WEAK_HOOKS +#if SANITIZER_LIBBACKTRACE +namespace { + +struct SymbolizeCodeData { + AddressInfo *frames; + uptr n_frames; + uptr max_frames; + const char *module_name; + uptr module_offset; +}; + +extern "C" { + +static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr, + const char *filename, int lineno, + const char *function) { + SymbolizeCodeData *cdata = (SymbolizeCodeData *)vdata; + if (function) { + AddressInfo *info = &cdata->frames[cdata->n_frames++]; + info->Clear(); + info->FillAddressAndModuleInfo(addr, cdata->module_name, cdata->module_offset); + info->function = internal_strdup(function); + if (filename) + info->file = internal_strdup(filename); + info->line = lineno; + } + return 0; +} + +static void SymbolizeCodeCallback(void *vdata, uintptr_t addr, + const char *symname, uintptr_t) { + SymbolizeCodeData *cdata = (SymbolizeCodeData *)vdata; + if (symname) { + AddressInfo *info = &cdata->frames[0]; + info->Clear(); + info->FillAddressAndModuleInfo(addr, cdata->module_name, cdata->module_offset); + info->function = internal_strdup(symname); + cdata->n_frames = 1; + } +} + +static void SymbolizeDataCallback(void *vdata, uintptr_t, + const char *symname, uintptr_t symval) { + DataInfo *info = (DataInfo *)vdata; + if (symname && symval) { + info->name = internal_strdup(symname); + info->start = symval; + } +} + +static void ErrorCallback(void *, const char *, int) { +} + +} + +} + +class LibbacktraceSymbolizer { + public: + static LibbacktraceSymbolizer *get(LowLevelAllocator *alloc) { + backtrace_state *state + = backtrace_create_state("/proc/self/exe", 1, ErrorCallback, NULL); + if (!state) + return 0; + return new(*alloc) LibbacktraceSymbolizer(state); + } + + uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames, + const char *module_name, uptr module_offset) { + SymbolizeCodeData data; + data.frames = frames; + data.n_frames = 0; + data.max_frames = max_frames; + data.module_name = module_name; + data.module_offset = module_offset; + backtrace_pcinfo(state_, addr, SymbolizeCodePCInfoCallback, ErrorCallback, + &data); + if (data.n_frames) + return data.n_frames; + backtrace_syminfo(state_, addr, SymbolizeCodeCallback, ErrorCallback, &data); + return data.n_frames; + } + + void SymbolizeData(DataInfo *info) { + backtrace_syminfo(state_, info->address, SymbolizeDataCallback, + ErrorCallback, info); + } + + private: + LibbacktraceSymbolizer(backtrace_state *state) : state_(state) { } + + backtrace_state *state_; // Leaked. +}; +#else +class LibbacktraceSymbolizer { + public: + static LibbacktraceSymbolizer *get(LowLevelAllocator *) { + return 0; + } + + uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames, + const char *module_name, uptr module_offset) { + return 0; + } + + void SymbolizeData(DataInfo *info) { + } +}; +#endif + class POSIXSymbolizer : public Symbolizer { public: POSIXSymbolizer(ExternalSymbolizer *external_symbolizer, + LibbacktraceSymbolizer *libbacktrace_symbolizer, InternalSymbolizer *internal_symbolizer) : Symbolizer(), external_symbolizer_(external_symbolizer), + libbacktrace_symbolizer_(libbacktrace_symbolizer), internal_symbolizer_(internal_symbolizer) {} uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) { @@ -381,7 +503,18 @@ class POSIXSymbolizer : public Symbolize return 0; const char *module_name = module->full_name(); uptr module_offset = addr - module->base_address(); - const char *str = SendCommand(false, module_name, module_offset); + const char *str = 0; + if (libbacktrace_symbolizer_) + { + uptr ret + = libbacktrace_symbolizer_->SymbolizeCode(addr, frames, max_frames, + module_name, + module_offset); + if (ret) + return ret; + } + else + str = SendCommand(false, module_name, module_offset); if (str == 0) { // External symbolizer was not initialized or failed. Fill only data // about module name and offset. @@ -444,6 +577,10 @@ class POSIXSymbolizer : public Symbolize info->address = addr; info->module = internal_strdup(module_name); info->module_offset = module_offset; + if (libbacktrace_symbolizer_) { + libbacktrace_symbolizer_->SymbolizeData(info); + return true; + } const char *str = SendCommand(true, module_name, module_offset); if (str == 0) return true; @@ -455,7 +594,9 @@ class POSIXSymbolizer : public Symbolize } bool IsAvailable() { - return internal_symbolizer_ != 0 || external_symbolizer_ != 0; + return internal_symbolizer_ != 0 || + libbacktrace_symbolizer_ != 0 || + external_symbolizer_ != 0; } bool IsExternalAvailable() { @@ -573,14 +714,19 @@ class POSIXSymbolizer : public Symbolize ExternalSymbolizer *external_symbolizer_; // Leaked. InternalSymbolizer *const internal_symbolizer_; // Leaked. + LibbacktraceSymbolizer *libbacktrace_symbolizer_; // Leaked. }; Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) { InternalSymbolizer* internal_symbolizer = InternalSymbolizer::get(&symbolizer_allocator_); + LibbacktraceSymbolizer* libbacktrace_symbolizer = 0; ExternalSymbolizer *external_symbolizer = 0; - if (!internal_symbolizer) { + if (!internal_symbolizer) + libbacktrace_symbolizer = + LibbacktraceSymbolizer::get(&symbolizer_allocator_); + if (!internal_symbolizer && !libbacktrace_symbolizer) { if (!path_to_external || path_to_external[0] == '\0') path_to_external = FindPathToBinary("llvm-symbolizer"); @@ -593,7 +739,8 @@ Symbolizer *Symbolizer::PlatformInit(con } return new(symbolizer_allocator_) - POSIXSymbolizer(external_symbolizer, internal_symbolizer); + POSIXSymbolizer(external_symbolizer, libbacktrace_symbolizer, + internal_symbolizer); } } // namespace __sanitizer Jakub