diff options
Diffstat (limited to 'src/common/dwarf/dwarf2reader.cc')
-rw-r--r-- | src/common/dwarf/dwarf2reader.cc | 150 |
1 files changed, 89 insertions, 61 deletions
diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc index b191d78c..8a8bf6f8 100644 --- a/src/common/dwarf/dwarf2reader.cc +++ b/src/common/dwarf/dwarf2reader.cc @@ -31,6 +31,10 @@ // Implementation of LineInfo, CompilationUnit, // and CallFrameInfo. See dwarf2reader.h for details. +#ifdef HAVE_CONFIG_H +#include <config.h> // Must come first +#endif + #include "common/dwarf/dwarf2reader.h" #include <stdint.h> @@ -76,9 +80,10 @@ CompilationUnit::CompilationUnit(const string& path, str_offsets_buffer_(NULL), str_offsets_buffer_length_(0), addr_buffer_(NULL), addr_buffer_length_(0), is_split_dwarf_(false), is_type_unit_(false), dwo_id_(0), dwo_name_(), - skeleton_dwo_id_(0), ranges_base_(0), addr_base_(0), - str_offsets_base_(0), have_checked_for_dwp_(false), dwp_path_(), - dwp_byte_reader_(), dwp_reader_() {} + skeleton_dwo_id_(0), addr_base_(0), + str_offsets_base_(0), have_checked_for_dwp_(false), + should_process_split_dwarf_(false), low_pc_(0), + has_source_line_info_(false), source_line_offset_(0) {} // Initialize a compilation unit from a .dwo or .dwp file. // In this case, we need the .debug_addr section from the @@ -87,16 +92,10 @@ CompilationUnit::CompilationUnit(const string& path, // the executable file, and call it as if we were still // processing the original compilation unit. -void CompilationUnit::SetSplitDwarf(const uint8_t* addr_buffer, - uint64_t addr_buffer_length, - uint64_t addr_base, - uint64_t ranges_base, +void CompilationUnit::SetSplitDwarf(uint64_t addr_base, uint64_t dwo_id) { is_split_dwarf_ = true; - addr_buffer_ = addr_buffer; - addr_buffer_length_ = addr_buffer_length; addr_base_ = addr_base; - ranges_base_ = ranges_base; skeleton_dwo_id_ = dwo_id; } @@ -396,7 +395,13 @@ uint64_t CompilationUnit::Start() { // Set up our buffer buffer_ = iter->second.first + offset_from_section_start_; - buffer_length_ = iter->second.second - offset_from_section_start_; + if (is_split_dwarf_) { + iter = GetSectionByName(sections_, ".debug_info_offset"); + assert(iter != sections_.end()); + buffer_length_ = iter->second.second; + } else { + buffer_length_ = iter->second.second - offset_from_section_start_; + } // Read the header ReadHeader(); @@ -430,6 +435,12 @@ uint64_t CompilationUnit::Start() { string_buffer_length_ = iter->second.second; } + iter = GetSectionByName(sections_, ".debug_line"); + if (iter != sections_.end()) { + line_buffer_ = iter->second.first; + line_buffer_length_ = iter->second.second; + } + // Set the line string section if we have one. iter = GetSectionByName(sections_, ".debug_line_str"); if (iter != sections_.end()) { @@ -457,10 +468,8 @@ uint64_t CompilationUnit::Start() { // If this is a skeleton compilation unit generated with split DWARF, // and the client needs the full debug info, we need to find the full // compilation unit in a .dwo or .dwp file. - if (!is_split_dwarf_ - && dwo_name_ != NULL - && handler_->NeedSplitDebugInfo()) - ProcessSplitDwarf(); + should_process_split_dwarf_ = + !is_split_dwarf_ && dwo_name_ != NULL && handler_->NeedSplitDebugInfo(); return ourlength; } @@ -881,7 +890,9 @@ const uint8_t* CompilationUnit::ProcessDIE(uint64_t dieoffset, // DW_AT_str_offsets_base or DW_AT_addr_base. If it does, that attribute must // be found and processed before trying to process the other attributes; // otherwise the string or address values will all come out incorrect. - if (abbrev.tag == DW_TAG_compile_unit && header_.version == 5) { + if ((abbrev.tag == DW_TAG_compile_unit || + abbrev.tag == DW_TAG_skeleton_unit) && + header_.version == 5) { uint64_t dieoffset_copy = dieoffset; const uint8_t* start_copy = start; for (AttributeList::const_iterator i = abbrev.attributes.begin(); @@ -990,66 +1001,69 @@ inline int GetElfWidth(const ElfReader& elf) { return 0; } -void CompilationUnit::ProcessSplitDwarf() { +bool CompilationUnit::ProcessSplitDwarf(std::string& split_file, + SectionMap& sections, + ByteReader& split_byte_reader, + uint64_t& cu_offset) { + if (!should_process_split_dwarf_) + return false; struct stat statbuf; + bool found_in_dwp = false; if (!have_checked_for_dwp_) { // Look for a .dwp file in the same directory as the executable. have_checked_for_dwp_ = true; string dwp_suffix(".dwp"); - dwp_path_ = path_ + dwp_suffix; - if (stat(dwp_path_.c_str(), &statbuf) != 0) { + std::string dwp_path = path_ + dwp_suffix; + if (stat(dwp_path.c_str(), &statbuf) != 0) { // Fall back to a split .debug file in the same directory. string debug_suffix(".debug"); - dwp_path_ = path_; + dwp_path = path_; size_t found = path_.rfind(debug_suffix); - if (found + debug_suffix.length() == path_.length()) - dwp_path_ = dwp_path_.replace(found, debug_suffix.length(), dwp_suffix); + if (found != string::npos && + found + debug_suffix.length() == path_.length()) + dwp_path = dwp_path.replace(found, debug_suffix.length(), dwp_suffix); } - if (stat(dwp_path_.c_str(), &statbuf) == 0) { - ElfReader* elf = new ElfReader(dwp_path_); - int width = GetElfWidth(*elf); + if (stat(dwp_path.c_str(), &statbuf) == 0) { + split_elf_reader_ = std::make_unique<ElfReader>(dwp_path); + int width = GetElfWidth(*split_elf_reader_.get()); if (width != 0) { - dwp_byte_reader_.reset(new ByteReader(reader_->GetEndianness())); - dwp_byte_reader_->SetAddressSize(width); - dwp_reader_.reset(new DwpReader(*dwp_byte_reader_, elf)); + split_byte_reader = ByteReader(reader_->GetEndianness()); + split_byte_reader.SetAddressSize(width); + dwp_reader_ = std::make_unique<DwpReader>(split_byte_reader, + split_elf_reader_.get()); dwp_reader_->Initialize(); - } else { - delete elf; + // If we have a .dwp file, read the debug sections for the requested CU. + dwp_reader_->ReadDebugSectionsForCU(dwo_id_, §ions); + if (!sections.empty()) { + SectionMap::const_iterator cu_iter = + GetSectionByName(sections, ".debug_info_offset"); + SectionMap::const_iterator debug_info_iter = + GetSectionByName(sections, ".debug_info"); + assert(cu_iter != sections.end()); + assert(debug_info_iter != sections.end()); + cu_offset = cu_iter->second.first - debug_info_iter->second.first; + found_in_dwp = true; + split_file = dwp_path; + } } } } - bool found_in_dwp = false; - if (dwp_reader_) { - // If we have a .dwp file, read the debug sections for the requested CU. - SectionMap sections; - dwp_reader_->ReadDebugSectionsForCU(dwo_id_, §ions); - if (!sections.empty()) { - found_in_dwp = true; - CompilationUnit dwp_comp_unit(dwp_path_, sections, 0, - dwp_byte_reader_.get(), handler_); - dwp_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, addr_base_, - ranges_base_, dwo_id_); - dwp_comp_unit.Start(); - } - } if (!found_in_dwp) { // If no .dwp file, try to open the .dwo file. if (stat(dwo_name_, &statbuf) == 0) { - ElfReader elf(dwo_name_); - int width = GetElfWidth(elf); + split_elf_reader_ = std::make_unique<ElfReader>(dwo_name_); + int width = GetElfWidth(*split_elf_reader_.get()); if (width != 0) { - ByteReader reader(ENDIANNESS_LITTLE); - reader.SetAddressSize(width); - SectionMap sections; - ReadDebugSectionsFromDwo(&elf, §ions); - CompilationUnit dwo_comp_unit(dwo_name_, sections, 0, &reader, - handler_); - dwo_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, - addr_base_, ranges_base_, dwo_id_); - dwo_comp_unit.Start(); + split_byte_reader = ByteReader(ENDIANNESS_LITTLE); + split_byte_reader.SetAddressSize(width); + ReadDebugSectionsFromDwo(split_elf_reader_.get(), §ions); + if (!sections.empty()) { + split_file = dwo_name_; + } } } } + return !split_file.empty(); } void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader, @@ -1084,10 +1098,6 @@ DwpReader::DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader) abbrev_size_(0), info_data_(NULL), info_size_(0), str_offsets_data_(NULL), str_offsets_size_(0) {} -DwpReader::~DwpReader() { - if (elf_reader_) delete elf_reader_; -} - void DwpReader::Initialize() { cu_index_ = elf_reader_->GetSectionByName(".debug_cu_index", &cu_index_size_); @@ -1127,6 +1137,8 @@ void DwpReader::Initialize() { info_data_ = elf_reader_->GetSectionByName(".debug_info.dwo", &info_size_); str_offsets_data_ = elf_reader_->GetSectionByName(".debug_str_offsets.dwo", &str_offsets_size_); + rnglist_data_ = + elf_reader_->GetSectionByName(".debug_rnglists.dwo", &rnglist_size_); if (size_table_ >= cu_index_ + cu_index_size_) { version_ = 0; } @@ -1227,13 +1239,24 @@ void DwpReader::ReadDebugSectionsForCU(uint64_t dwo_id, } else if (section_id == DW_SECT_INFO) { sections->insert(std::make_pair( ".debug_info", - std::make_pair(reinterpret_cast<const uint8_t*> (info_data_) - + offset, size))); + std::make_pair(reinterpret_cast<const uint8_t*>(info_data_), 0))); + // .debug_info_offset will points the buffer for the CU with given + // dwo_id. + sections->insert(std::make_pair( + ".debug_info_offset", + std::make_pair( + reinterpret_cast<const uint8_t*>(info_data_) + offset, size))); } else if (section_id == DW_SECT_STR_OFFSETS) { sections->insert(std::make_pair( ".debug_str_offsets", std::make_pair(reinterpret_cast<const uint8_t*> (str_offsets_data_) + offset, size))); + } else if (section_id == DW_SECT_RNGLISTS) { + sections->insert(std::make_pair( + ".debug_rnglists", + std::make_pair( + reinterpret_cast<const uint8_t*>(rnglist_data_) + offset, + size))); } } sections->insert(std::make_pair( @@ -1819,6 +1842,11 @@ bool RangeListReader::ReadRanges(enum DwarfForm form, uint64_t data) { return ReadDebugRngList(data); } } else if (form == DW_FORM_rnglistx) { + if (cu_info_->ranges_base_ == 0) { + // In split dwarf, there's no DW_AT_rnglists_base attribute, range_base + // will just be the first byte after the header. + cu_info_->ranges_base_ = reader_->OffsetSize() == 4? 12: 20; + } offset_array_ = cu_info_->ranges_base_; uint64_t index_offset = reader_->OffsetSize() * data; uint64_t range_list_offset = |