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

Reply via email to