[Sanitizer] Add rudimentary support for using libbacktrace in symbolizer.
Jakub Jelinek
jakub at redhat.com
Fri Jan 10 02:15:13 PST 2014
On Thu, Jan 09, 2014 at 03:11:16PM -0800, Chandler Carruth wrote:
> I've mailed out a patch to the LLVM developer's policy which should clarify
> this. The only thing that would help is for the authors of these three
> patches (and the fourth patch I found later) to just email a copy of the
> patch to llvm-commits, or if any of you have commit access to directly
> commit the patch.
Here I'm submitting my contribution to the libbacktrace sanitization patch,
which has been posted in
http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02338.html
Note that Alexey has made quite a few changes to the patch that has been
eventually committed as r196875, so is this post sufficient for Alexey
to commit again his r196875 change?
--- lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc.jj 2013-11-12 19:35:30.000000000 +0100
+++ lib/sanitizer_common/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
--- lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc.jj 2013-11-19 16:41:37.811809494 +0100
+++ lib/sanitizer_common/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
--- lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h.jj 2013-11-19 16:41:32.286843717 +0100
+++ lib/sanitizer_common/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.
+};
+
+}
Jakub
More information about the llvm-commits
mailing list