This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Use libbacktrace as libsanitizer's symbolizer
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Alexey Samsonov <samsonov at google dot com>
- Cc: Konstantin Serebryany <kcc at gcc dot gnu dot org>, Ian Lance Taylor <iant at google dot com>, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 18 Nov 2013 17:23:42 +0100
- Subject: Re: [PATCH] Use libbacktrace as libsanitizer's symbolizer
- Authentication-results: sourceware.org; auth=none
- References: <20131118133930 dot GA892 at tucnak dot redhat dot com> <CAGSYnCMV=Sa6sNq5W-WcB-+iH_f3wwcQyBZ8HMEKsEW7VamHxA at mail dot gmail dot com> <CAGSYnCOs6BHEqfhoBdpF0AEODHhbhLENyWGy_DrObVnUv+js2g at mail dot gmail dot com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Mon, Nov 18, 2013 at 07:50:33PM +0400, Alexey Samsonov wrote:
> On Mon, Nov 18, 2013 at 7:49 PM, Alexey Samsonov <samsonov@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