From d338ae0144c1727f22e818200ea68dbf311595de Mon Sep 17 00:00:00 2001 From: Alex Light Date: Wed, 13 Aug 2014 17:15:38 -0700 Subject: [PATCH] Make gdb fixup work with multiple DWARF Compilation Units Change-Id: I83042362fc199ca48c8452230709a377e52a2cf5 --- runtime/elf_file.cc | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc index 6179b5e8d..35294d4da 100644 --- a/runtime/elf_file.cc +++ b/runtime/elf_file.cc @@ -1189,18 +1189,27 @@ class DebugAbbrev { public: ~DebugAbbrev() {} static DebugAbbrev* Create(const byte* dbg_abbrev, size_t dbg_abbrev_size) { - std::unique_ptr abbrev(new DebugAbbrev); - const byte* last = dbg_abbrev + dbg_abbrev_size; - while (dbg_abbrev < last) { + std::unique_ptr abbrev(new DebugAbbrev(dbg_abbrev, dbg_abbrev + dbg_abbrev_size)); + if (!abbrev->ReadAtOffset(0)) { + return nullptr; + } + return abbrev.release(); + } + + bool ReadAtOffset(uint32_t abbrev_offset) { + tags_.clear(); + tag_list_.clear(); + const byte* dbg_abbrev = begin_ + abbrev_offset; + while (dbg_abbrev < end_ && *dbg_abbrev != 0) { std::unique_ptr tag(DebugTag::Create(&dbg_abbrev)); if (tag.get() == nullptr) { - return nullptr; + return false; } else { - abbrev->tags_.insert(std::pair(tag->index_, abbrev->tag_list_.size())); - abbrev->tag_list_.push_back(std::move(tag)); + tags_.insert(std::pair(tag->index_, tag_list_.size())); + tag_list_.push_back(std::move(tag)); } } - return abbrev.release(); + return true; } DebugTag* ReadTag(const byte* entry) { @@ -1215,7 +1224,9 @@ class DebugAbbrev { } private: - DebugAbbrev() {} + DebugAbbrev(const byte* begin, const byte* end) : begin_(begin), end_(end) {} + const byte* begin_; + const byte* end_; std::map tags_; std::vector> tag_list_; }; @@ -1239,11 +1250,21 @@ class DebugInfoIterator { if (current_entry_ == nullptr || current_tag_ == nullptr) { return false; } + bool reread_abbrev = false; current_entry_ += current_tag_->GetSize(); + if (reinterpret_cast(current_entry_) >= next_cu_) { + current_cu_ = next_cu_; + next_cu_ = GetNextCu(current_cu_); + current_entry_ = reinterpret_cast(current_cu_) + sizeof(DebugInfoHeader); + reread_abbrev = true; + } if (current_entry_ >= last_entry_) { current_entry_ = nullptr; return false; } + if (reread_abbrev) { + abbrev_->ReadAtOffset(current_cu_->debug_abbrev_offset); + } current_tag_ = abbrev_->ReadTag(current_entry_); if (current_tag_ == nullptr) { current_entry_ = nullptr; @@ -1271,12 +1292,21 @@ class DebugInfoIterator { } private: + static DebugInfoHeader* GetNextCu(DebugInfoHeader* hdr) { + byte* hdr_byte = reinterpret_cast(hdr); + return reinterpret_cast(hdr_byte + sizeof(uint32_t) + hdr->unit_length); + } + DebugInfoIterator(DebugInfoHeader* header, size_t frame_size, DebugAbbrev* abbrev) : abbrev_(abbrev), + current_cu_(header), + next_cu_(GetNextCu(header)), last_entry_(reinterpret_cast(header) + frame_size), current_entry_(reinterpret_cast(header) + sizeof(DebugInfoHeader)), current_tag_(abbrev_->ReadTag(current_entry_)) {} DebugAbbrev* abbrev_; + DebugInfoHeader* current_cu_; + DebugInfoHeader* next_cu_; byte* last_entry_; byte* current_entry_; DebugTag* current_tag_; -- 2.11.0