[compiler-rt] r199384 - [Sanitizer] Add basic support for using libbacktrace in symbolizer.

Alexey Samsonov samsonov at google.com
Thu Jan 16 05:48:16 PST 2014


Author: samsonov
Date: Thu Jan 16 07:48:15 2014
New Revision: 199384

URL: http://llvm.org/viewvc/llvm-project?rev=199384&view=rev
Log:
[Sanitizer] Add basic support for using libbacktrace in symbolizer.

This change allows to compile sanitizer sources so that *san runtime
will attempt to use libbacktrace and/or libiberty for symbolization
(instead of communicating with llvm-symbolizer).

I've tested this patch by manually defining SANITIZER_LIBBACKTRACE and/or
SANITIZER_CP_DEMANGLE, linking with necessary libraries and verifying that
all tests from ASan test suite work.

Based on patches by Jakub Jelinek!

Added:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
Modified:
    compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=199384&r1=199383&r2=199384&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Thu Jan 16 07:48:15 2014
@@ -20,6 +20,7 @@ set(SANITIZER_SOURCES
   sanitizer_stacktrace.cc
   sanitizer_suppressions.cc
   sanitizer_symbolizer.cc
+  sanitizer_symbolizer_libbacktrace.cc
   sanitizer_symbolizer_win.cc
   sanitizer_thread_registry.cc
   sanitizer_win.cc)
@@ -67,6 +68,7 @@ set(SANITIZER_HEADERS
   sanitizer_stoptheworld.h
   sanitizer_suppressions.h
   sanitizer_symbolizer.h
+  sanitizer_symbolizer_libbacktrace.h
   sanitizer_syscall_generic.inc
   sanitizer_syscall_linux_x86_64.inc
   sanitizer_thread_registry.h)

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc?rev=199384&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc Thu Jan 16 07:48:15 2014
@@ -0,0 +1,206 @@
+//===-- 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"
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_libbacktrace.h"
+
+#if SANITIZER_LIBBACKTRACE
+# include "backtrace-supported.h"
+# if SANITIZER_POSIX && BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC
+#  include "backtrace.h"
+#  if SANITIZER_CP_DEMANGLE
+#   undef ARRAY_SIZE
+#   include "demangle.h"
+#  endif
+# else
+#  define SANITIZER_LIBBACKTRACE 0
+# endif
+#endif
+
+namespace __sanitizer {
+
+#if SANITIZER_LIBBACKTRACE
+
+namespace {
+
+# if SANITIZER_CP_DEMANGLE
+struct CplusV3DemangleData {
+  char *buf;
+  uptr size, allocated;
+};
+
+extern "C" {
+static void CplusV3DemangleCallback(const char *s, size_t l, void *vdata) {
+  CplusV3DemangleData *data = (CplusV3DemangleData *)vdata;
+  uptr needed = data->size + l + 1;
+  if (needed > data->allocated) {
+    data->allocated *= 2;
+    if (needed > data->allocated)
+      data->allocated = needed;
+    char *buf = (char *)InternalAlloc(data->allocated);
+    if (data->buf) {
+      internal_memcpy(buf, data->buf, data->size);
+      InternalFree(data->buf);
+    }
+    data->buf = buf;
+  }
+  internal_memcpy(data->buf + data->size, s, l);
+  data->buf[data->size + l] = '\0';
+  data->size += l;
+}
+}  // extern "C"
+
+char *CplusV3Demangle(const char *name) {
+  CplusV3DemangleData data;
+  data.buf = 0;
+  data.size = 0;
+  data.allocated = 0;
+  if (cplus_demangle_v3_callback(name, DMGL_PARAMS | DMGL_ANSI,
+                                 CplusV3DemangleCallback, &data)) {
+    if (data.size + 64 > data.allocated)
+      return data.buf;
+    char *buf = internal_strdup(data.buf);
+    InternalFree(data.buf);
+    return buf;
+  }
+  if (data.buf)
+    InternalFree(data.buf);
+  return 0;
+}
+# endif  // SANITIZER_CP_DEMANGLE
+
+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 = LibbacktraceSymbolizer::Demangle(function, true);
+    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 = LibbacktraceSymbolizer::Demangle(symname, true);
+    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 = LibbacktraceSymbolizer::Demangle(symname, true);
+    info->start = symval;
+    info->size = symsize;
+  }
+}
+
+static void ErrorCallback(void *, const char *, int) {}
+}  // extern "C"
+
+}  // namespace
+
+LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
+  // State created in backtrace_create_state is leaked.
+  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;
+}
+
+bool LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) {
+  backtrace_syminfo((backtrace_state *)state_, info->address,
+                    SymbolizeDataCallback, ErrorCallback, info);
+  return true;
+}
+
+#else  // SANITIZER_LIBBACKTRACE
+
+LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
+  return 0;
+}
+
+uptr LibbacktraceSymbolizer::SymbolizeCode(uptr addr, AddressInfo *frames,
+                                           uptr max_frames,
+                                           const char *module_name,
+                                           uptr module_offset) {
+  (void)state_;
+  return 0;
+}
+
+bool LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) {
+  return false;
+}
+
+#endif  // SANITIZER_LIBBACKTRACE
+
+char *LibbacktraceSymbolizer::Demangle(const char *name, bool always_alloc) {
+#if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE
+  if (char *demangled = CplusV3Demangle(name))
+    return demangled;
+#endif
+  if (always_alloc)
+    return internal_strdup(name);
+  return 0;
+}
+
+}  // namespace __sanitizer

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h?rev=199384&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h Thu Jan 16 07:48:15 2014
@@ -0,0 +1,47 @@
+//===-- sanitizer_symbolizer_libbacktrace.h ---------------------*- C++ -*-===//
+//
+//                     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.
+// Header for libbacktrace symbolizer.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#include "sanitizer_common.h"
+#include "sanitizer_symbolizer.h"
+
+#ifndef SANITIZER_LIBBACKTRACE
+# define SANITIZER_LIBBACKTRACE 0
+#endif
+
+#ifndef SANITIZER_CP_DEMANGLE
+# define SANITIZER_CP_DEMANGLE 0
+#endif
+
+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);
+
+  bool SymbolizeData(DataInfo *info);
+
+  // May return NULL if demangling failed.
+  static char *Demangle(const char *name, bool always_alloc = false);
+
+ private:
+  explicit LibbacktraceSymbolizer(void *state) : state_(state) {}
+
+  void *state_;  // Leaked.
+};
+
+}  // namespace __sanitizer

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc?rev=199384&r1=199383&r2=199384&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc Thu Jan 16 07:48:15 2014
@@ -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>
@@ -386,10 +387,12 @@ class InternalSymbolizer {
 class POSIXSymbolizer : public Symbolizer {
  public:
   POSIXSymbolizer(ExternalSymbolizer *external_symbolizer,
-                  InternalSymbolizer *internal_symbolizer)
+                  InternalSymbolizer *internal_symbolizer,
+                  LibbacktraceSymbolizer *libbacktrace_symbolizer)
       : Symbolizer(),
         external_symbolizer_(external_symbolizer),
-        internal_symbolizer_(internal_symbolizer) {}
+        internal_symbolizer_(internal_symbolizer),
+        libbacktrace_symbolizer_(libbacktrace_symbolizer) {}
 
   uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames) {
     BlockingMutexLock l(&mu_);
@@ -399,9 +402,17 @@ class POSIXSymbolizer : public Symbolize
     uptr module_offset;
     if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
       return 0;
+    // First, try to use libbacktrace symbolizer (if it's available).
+    if (libbacktrace_symbolizer_ != 0) {
+      mu_.CheckLocked();
+      uptr res = libbacktrace_symbolizer_->SymbolizeCode(
+          addr, frames, max_frames, module_name, module_offset);
+      if (res > 0)
+        return res;
+    }
     const char *str = SendCommand(false, module_name, module_offset);
     if (str == 0) {
-      // External symbolizer was not initialized or failed. Fill only data
+      // Symbolizer was not initialized or failed. Fill only data
       // about module name and offset.
       AddressInfo *info = &frames[0];
       info->Clear();
@@ -462,6 +473,12 @@ class POSIXSymbolizer : public Symbolize
     info->address = addr;
     info->module = internal_strdup(module_name);
     info->module_offset = module_offset;
+    // First, try to use libbacktrace symbolizer (if it's available).
+    if (libbacktrace_symbolizer_ != 0) {
+      mu_.CheckLocked();
+      if (libbacktrace_symbolizer_->SymbolizeData(info))
+        return true;
+    }
     const char *str = SendCommand(true, module_name, module_offset);
     if (str == 0)
       return true;
@@ -479,7 +496,8 @@ class POSIXSymbolizer : public Symbolize
   }
 
   bool CanReturnFileLineInfo() {
-    return internal_symbolizer_ != 0 || external_symbolizer_ != 0;
+    return internal_symbolizer_ != 0 || external_symbolizer_ != 0 ||
+           libbacktrace_symbolizer_ != 0;
   }
 
   void Flush() {
@@ -497,6 +515,11 @@ class POSIXSymbolizer : public Symbolize
     // Run hooks even if we don't use internal symbolizer, as cxxabi
     // demangle may call system functions.
     SymbolizerScope sym_scope(this);
+    // Try to use libbacktrace demangler (if available).
+    if (libbacktrace_symbolizer_ != 0) {
+      if (const char *demangled = libbacktrace_symbolizer_->Demangle(name))
+        return demangled;
+    }
     if (internal_symbolizer_ != 0)
       return internal_symbolizer_->Demangle(name);
     return DemangleCXXABI(name);
@@ -578,24 +601,30 @@ 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_);
   ExternalSymbolizer *external_symbolizer = 0;
+  LibbacktraceSymbolizer *libbacktrace_symbolizer = 0;
 
   if (!internal_symbolizer) {
-    // Find path to llvm-symbolizer if it's not provided.
-    if (!path_to_external)
-      path_to_external = FindPathToBinary("llvm-symbolizer");
-    if (path_to_external && path_to_external[0] != '\0')
-      external_symbolizer = new(symbolizer_allocator_)
-          ExternalSymbolizer(path_to_external);
+    libbacktrace_symbolizer =
+        LibbacktraceSymbolizer::get(&symbolizer_allocator_);
+    if (!libbacktrace_symbolizer) {
+      // Find path to llvm-symbolizer if it's not provided.
+      if (!path_to_external)
+        path_to_external = FindPathToBinary("llvm-symbolizer");
+      if (path_to_external && path_to_external[0] != '\0')
+        external_symbolizer = new(symbolizer_allocator_)
+            ExternalSymbolizer(path_to_external);
+    }
   }
 
-  return new(symbolizer_allocator_)
-      POSIXSymbolizer(external_symbolizer, internal_symbolizer);
+  return new(symbolizer_allocator_) POSIXSymbolizer(
+      external_symbolizer, internal_symbolizer, libbacktrace_symbolizer);
 }
 
 }  // namespace __sanitizer





More information about the llvm-commits mailing list