On Tue, Nov 19, 2013 at 8:42 PM, Jakub Jelinek <ja...@redhat.com> wrote: > > 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).
Do you have an idea of how the libbacktrace symbolizer should look to the end user (if the static runtime was built with -DSANITIZER_LIBBACKTRACE)? I see the following options, none of which looks nice: 1) Force the user to provide -L/path/to/libbacktrace -lbacktrace at link time (otherwise one will see link errors like "undefined symbol: backtrace_create_state"). Certainly this is a bad user experience. 2) Make -fsanitize=address link flag imply "-lbacktrace" as we do for libpthread, librt etc. But libbacktrace may not be installed in the system. 3) Pull libbacktrace.a inside libasan.a. This means we should teach the build system to merge two archives (or have access to backtrace sources at build time and recompile them ourselves). This is doable, but kind of ugly and leads to funny consequences - we'll fail to build libbacktrace itself with ASan (or, arguably, any program which uses it). I ask this because I'm slightly afraid libbacktrace symbolizer will be pretty undertested in the llvm tree and we may break it without noticing. Building it is not a problem, but making all the tests "just work" with it is harder. > > > --- 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 -- Alexey Samsonov, MSK