On Tue, Nov 19, 2013 at 04:33:50PM +0100, Jakub Jelinek wrote: > I will try.
Ok, here it is (untested though, because libsanitizer in gcc is older and I don't have spare cycles to play with llvm). Guess you need to write it up into compiler-rt buildsystem somehow, and for testing add -DSANITIZER_LIBBACKTRACE -I..../srcdir_of_libbacktrace -I..../builddir_of_libbacktrace -L..../builddir_of_libbacktrace/.libs -lbacktrace This is against current libbacktrace (r205028 or later, before that the syminfo callbacks had one less argument). --- sanitizer_symbolizer_libbacktrace.cc.jj 2013-11-19 16:41:37.811809494 +0100 +++ sanitizer_symbolizer_libbacktrace.cc 2013-11-19 16:56:34.111233379 +0100 @@ -0,0 +1,151 @@ +//===-- sanitizer_symbolizer_libbacktrace.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 AddressSanitizer and ThreadSanitizer +// run-time libraries. +// Libbacktrace implementation of symbolizer parts. +//===----------------------------------------------------------------------===// + +#include "sanitizer_platform.h" +#if SANITIZER_POSIX +#include "sanitizer_allocator_internal.h" +#include "sanitizer_common.h" +#include "sanitizer_internal_defs.h" +#include "sanitizer_linux.h" +#include "sanitizer_placement_new.h" +#include "sanitizer_procmaps.h" +#include "sanitizer_symbolizer.h" +#include "sanitizer_symbolizer_libbacktrace.h" + +#include <stdlib.h> +#include <unistd.h> + +#ifdef SANITIZER_LIBBACKTRACE +#include "backtrace-supported.h" +#if SANITIZER_POSIX && BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC +#include "backtrace.h" +#else +#undef SANITIZER_LIBBACKTRACE +#endif +#endif + +namespace __sanitizer { + +#ifdef 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; + if (cdata->n_frames == cdata->max_frames) + return 1; + } + return 0; +} + +static void SymbolizeCodeCallback(void *vdata, uintptr_t addr, + const char *symname, uintptr_t, 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, uintptr_t symsize) { + DataInfo *info = (DataInfo *)vdata; + if (symname && symval) { + info->name = internal_strdup(symname); + info->start = symval; + info->size = symsize; + } +} + +static void ErrorCallback(void *, const char *, int) { +} + +} + +} + +LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) { + void *state + = (void *) backtrace_create_state("/proc/self/exe", 0, ErrorCallback, NULL); + if (!state) + return 0; + return new(*alloc) LibbacktraceSymbolizer(state); +} + +uptr LibbacktraceSymbolizer::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((backtrace_state) state_, addr, SymbolizeCodePCInfoCallback, + ErrorCallback, &data); + if (data.n_frames) + return data.n_frames; + backtrace_syminfo((backtrace_state) state_, addr, SymbolizeCodeCallback, + ErrorCallback, &data); + return data.n_frames; +} + +void LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) { + backtrace_syminfo((backtrace_state) state_, info->address, + SymbolizeDataCallback, ErrorCallback, info); +} + +#else + +LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *) { + return 0; +} + +uptr LibbacktraceSymbolizer::SymbolizeCode(uptr, AddressInfo *, uptr, + const char *, uptr) { + return 0; +} + +void LibbacktraceSymbolizer::SymbolizeData(DataInfo *) { +} + +#endif + +} // namespace __sanitizer + +#endif // SANITIZER_POSIX --- sanitizer_symbolizer_libbacktrace.h.jj 2013-11-19 16:41:32.286843717 +0100 +++ sanitizer_symbolizer_libbacktrace.h 2013-11-19 16:52:16.448544275 +0100 @@ -0,0 +1,36 @@ +//===-- sanitizer_symbolizer_libbacktrace.h -------------------------------===// +// +// 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 AddressSanitizer and ThreadSanitizer +// run-time libraries. +// POSIX-specific implementation of symbolizer parts. +//===----------------------------------------------------------------------===// + +#include "sanitizer_platform.h" +#include "sanitizer_common.h" +#include "sanitizer_symbolizer.h" + +namespace __sanitizer { + +class LibbacktraceSymbolizer { + public: + static LibbacktraceSymbolizer *get(LowLevelAllocator *alloc); + + uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames, + const char *module_name, uptr module_offset); + + void SymbolizeData(DataInfo *info); + + private: + LibbacktraceSymbolizer(void *state) : state_(state) { } + + void *state_; // Leaked. +}; + +} --- sanitizer_symbolizer_posix_libcdep.cc.jj 2013-11-12 19:35:30.000000000 +0100 +++ sanitizer_symbolizer_posix_libcdep.cc 2013-11-19 16:54:56.831724908 +0100 @@ -21,6 +21,7 @@ #include "sanitizer_placement_new.h" #include "sanitizer_procmaps.h" #include "sanitizer_symbolizer.h" +#include "sanitizer_symbolizer_libbacktrace.h" #include <errno.h> #include <stdlib.h> @@ -367,9 +368,11 @@ class InternalSymbolizer { 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 +384,19 @@ 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 = NULL; + if (libbacktrace_symbolizer_) + { + mu_.CheckLocked(); + 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 +459,11 @@ class POSIXSymbolizer : public Symbolize info->address = addr; info->module = internal_strdup(module_name); info->module_offset = module_offset; + if (libbacktrace_symbolizer_) { + mu_.CheckLocked(); + libbacktrace_symbolizer_->SymbolizeData(info); + return true; + } const char *str = SendCommand(true, module_name, module_offset); if (str == 0) return true; @@ -455,7 +477,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 +597,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 +622,8 @@ Symbolizer *Symbolizer::PlatformInit(con } return new(symbolizer_allocator_) - POSIXSymbolizer(external_symbolizer, internal_symbolizer); + POSIXSymbolizer(external_symbolizer, libbacktrace_symbolizer, + internal_symbolizer); } } // namespace __sanitizer Jakub