aboutsummaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_symbolizer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sanitizer_common/sanitizer_symbolizer.cc')
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer.cc144
1 files changed, 144 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_symbolizer.cc b/lib/sanitizer_common/sanitizer_symbolizer.cc
new file mode 100644
index 000000000000..85eb0764f19c
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer.cc
@@ -0,0 +1,144 @@
+//===-- sanitizer_symbolizer.cc -------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a stub for LLVM-based symbolizer.
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries. See sanitizer.h for details.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+#include "sanitizer_symbolizer.h"
+
+namespace __sanitizer {
+
+bool IsFullNameOfDWARFSection(const char *full_name, const char *short_name) {
+ // Skip "__DWARF," prefix.
+ if (0 == internal_strncmp(full_name, "__DWARF,", 8)) {
+ full_name += 8;
+ }
+ // Skip . and _ prefices.
+ while (*full_name == '.' || *full_name == '_') {
+ full_name++;
+ }
+ return 0 == internal_strcmp(full_name, short_name);
+}
+
+void AddressInfo::Clear() {
+ InternalFree(module);
+ InternalFree(function);
+ InternalFree(file);
+ internal_memset(this, 0, sizeof(AddressInfo));
+}
+
+ModuleDIContext::ModuleDIContext(const char *module_name, uptr base_address) {
+ full_name_ = internal_strdup(module_name);
+ short_name_ = internal_strrchr(module_name, '/');
+ if (short_name_ == 0) {
+ short_name_ = full_name_;
+ } else {
+ short_name_++;
+ }
+ base_address_ = base_address;
+ n_ranges_ = 0;
+ mapped_addr_ = 0;
+ mapped_size_ = 0;
+}
+
+void ModuleDIContext::addAddressRange(uptr beg, uptr end) {
+ CHECK_LT(n_ranges_, kMaxNumberOfAddressRanges);
+ ranges_[n_ranges_].beg = beg;
+ ranges_[n_ranges_].end = end;
+ n_ranges_++;
+}
+
+bool ModuleDIContext::containsAddress(uptr address) const {
+ for (uptr i = 0; i < n_ranges_; i++) {
+ if (ranges_[i].beg <= address && address < ranges_[i].end)
+ return true;
+ }
+ return false;
+}
+
+void ModuleDIContext::getAddressInfo(AddressInfo *info) {
+ info->module = internal_strdup(full_name_);
+ info->module_offset = info->address - base_address_;
+ if (mapped_addr_ == 0)
+ CreateDIContext();
+ // FIXME: Use the actual debug info context here.
+ info->function = 0;
+ info->file = 0;
+ info->line = 0;
+ info->column = 0;
+}
+
+void ModuleDIContext::CreateDIContext() {
+ mapped_addr_ = (uptr)MapFileToMemory(full_name_, &mapped_size_);
+ CHECK(mapped_addr_);
+ DWARFSection debug_info;
+ DWARFSection debug_abbrev;
+ DWARFSection debug_line;
+ DWARFSection debug_aranges;
+ DWARFSection debug_str;
+ FindDWARFSection(mapped_addr_, "debug_info", &debug_info);
+ FindDWARFSection(mapped_addr_, "debug_abbrev", &debug_abbrev);
+ FindDWARFSection(mapped_addr_, "debug_line", &debug_line);
+ FindDWARFSection(mapped_addr_, "debug_aranges", &debug_aranges);
+ FindDWARFSection(mapped_addr_, "debug_str", &debug_str);
+ // FIXME: Construct actual debug info context using mapped_addr,
+ // mapped_size and pointers to DWARF sections in memory.
+}
+
+class Symbolizer {
+ public:
+ uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) {
+ if (max_frames == 0)
+ return 0;
+ AddressInfo *info = &frames[0];
+ info->Clear();
+ info->address = addr;
+ ModuleDIContext *module = FindModuleForAddress(addr);
+ if (module) {
+ module->getAddressInfo(info);
+ return 1;
+ }
+ return 0;
+ }
+
+ private:
+ ModuleDIContext *FindModuleForAddress(uptr address) {
+ if (modules_ == 0) {
+ modules_ = (ModuleDIContext*)InternalAlloc(
+ kMaxNumberOfModuleContexts * sizeof(ModuleDIContext));
+ CHECK(modules_);
+ n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts);
+ CHECK_GT(n_modules_, 0);
+ CHECK_LT(n_modules_, kMaxNumberOfModuleContexts);
+ }
+ for (uptr i = 0; i < n_modules_; i++) {
+ if (modules_[i].containsAddress(address)) {
+ return &modules_[i];
+ }
+ }
+ return 0;
+ }
+ static const uptr kMaxNumberOfModuleContexts = 4096;
+ // Array of module debug info contexts is leaked.
+ ModuleDIContext *modules_;
+ uptr n_modules_;
+};
+
+static Symbolizer symbolizer; // Linker initialized.
+
+uptr SymbolizeCode(uptr address, AddressInfo *frames, uptr max_frames) {
+ return symbolizer.SymbolizeCode(address, frames, max_frames);
+}
+
+} // namespace __sanitizer