| //===-- 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 file is shared between AddressSanitizer and ThreadSanitizer |
| // run-time libraries. See sanitizer_symbolizer.h for details. |
| //===----------------------------------------------------------------------===// |
| |
| #include "sanitizer_common.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; |
| dwarf_context_ = 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) |
| CreateDWARFContext(); |
| getLineInfoFromContext(dwarf_context_, info); |
| } |
| |
| void ModuleDIContext::CreateDWARFContext() { |
| mapped_addr_ = (uptr)MapFileToMemory(full_name_, &mapped_size_); |
| CHECK(mapped_addr_); |
| DWARFSection debug_info; |
| DWARFSection debug_abbrev; |
| DWARFSection debug_aranges; |
| DWARFSection debug_line; |
| DWARFSection debug_str; |
| FindDWARFSection(mapped_addr_, "debug_info", &debug_info); |
| FindDWARFSection(mapped_addr_, "debug_abbrev", &debug_abbrev); |
| FindDWARFSection(mapped_addr_, "debug_aranges", &debug_aranges); |
| FindDWARFSection(mapped_addr_, "debug_line", &debug_line); |
| FindDWARFSection(mapped_addr_, "debug_str", &debug_str); |
| dwarf_context_ = getDWARFContext(debug_info, debug_abbrev, debug_aranges, |
| debug_line, debug_str); |
| } |
| |
| 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 |