Loading libunwindstack/Android.bp +2 −2 Original line number Diff line number Diff line Loading @@ -48,8 +48,7 @@ cc_library { srcs: [ "ArmExidx.cpp", "DwarfCfa.cpp", "DwarfDebugFrame.cpp", "DwarfEhFrame.cpp", "DwarfEhFrameWithHdr.cpp", "DwarfMemory.cpp", "DwarfOp.cpp", "DwarfSection.cpp", Loading Loading @@ -106,6 +105,7 @@ cc_test { "tests/DwarfCfaTest.cpp", "tests/DwarfDebugFrameTest.cpp", "tests/DwarfEhFrameTest.cpp", "tests/DwarfEhFrameWithHdrTest.cpp", "tests/DwarfMemoryTest.cpp", "tests/DwarfOpLogTest.cpp", "tests/DwarfOpTest.cpp", Loading libunwindstack/DwarfDebugFrame.cppdeleted 100644 → 0 +0 −316 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdint.h> #include <stdlib.h> #include <algorithm> #include <unwindstack/DwarfStructs.h> #include <unwindstack/Memory.h> #include "DwarfDebugFrame.h" #include "DwarfEncoding.h" #include "DwarfError.h" namespace unwindstack { template <typename AddressType> bool DwarfDebugFrame<AddressType>::Init(uint64_t offset, uint64_t size) { offset_ = offset; end_offset_ = offset + size; memory_.clear_func_offset(); memory_.clear_text_offset(); memory_.set_data_offset(offset); memory_.set_cur_offset(offset); return CreateSortedFdeList(); } template <typename AddressType> bool DwarfDebugFrame<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) { uint8_t version; if (!memory_.ReadBytes(&version, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } // Read the augmentation string. std::vector<char> aug_string; char aug_value; bool get_encoding = false; do { if (!memory_.ReadBytes(&aug_value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } if (aug_value == 'R') { get_encoding = true; } aug_string.push_back(aug_value); } while (aug_value != '\0'); if (version == 4) { // Skip the Address Size field. memory_.set_cur_offset(memory_.cur_offset() + 1); // Read the segment size. if (!memory_.ReadBytes(segment_size, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } else { *segment_size = 0; } if (aug_string[0] != 'z' || !get_encoding) { // No encoding return true; } // Skip code alignment factor uint8_t value; do { if (!memory_.ReadBytes(&value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } while (value & 0x80); // Skip data alignment factor do { if (!memory_.ReadBytes(&value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } while (value & 0x80); if (version == 1) { // Skip return address register. memory_.set_cur_offset(memory_.cur_offset() + 1); } else { // Skip return address register. do { if (!memory_.ReadBytes(&value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } while (value & 0x80); } // Skip the augmentation length. do { if (!memory_.ReadBytes(&value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } while (value & 0x80); for (size_t i = 1; i < aug_string.size(); i++) { if (aug_string[i] == 'R') { if (!memory_.ReadBytes(encoding, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } // Got the encoding, that's all we are looking for. return true; } else if (aug_string[i] == 'L') { memory_.set_cur_offset(memory_.cur_offset() + 1); } else if (aug_string[i] == 'P') { uint8_t encoding; if (!memory_.ReadBytes(&encoding, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } uint64_t value; if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } } // It should be impossible to get here. abort(); } template <typename AddressType> bool DwarfDebugFrame<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding) { if (segment_size != 0) { memory_.set_cur_offset(memory_.cur_offset() + 1); } uint64_t start; if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } uint64_t length; if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } if (length != 0) { fdes_.emplace_back(entry_offset, start, length); } return true; } template <typename AddressType> bool DwarfDebugFrame<AddressType>::CreateSortedFdeList() { memory_.set_cur_offset(offset_); // Loop through all of the entries and read just enough to create // a sorted list of pcs. // This code assumes that first comes the cie, then the fdes that // it applies to. uint64_t cie_offset = 0; uint8_t address_encoding; uint8_t segment_size; while (memory_.cur_offset() < end_offset_) { uint64_t cur_entry_offset = memory_.cur_offset(); // Figure out the entry length and type. uint32_t value32; if (!memory_.ReadBytes(&value32, sizeof(value32))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } uint64_t next_entry_offset; if (value32 == static_cast<uint32_t>(-1)) { uint64_t value64; if (!memory_.ReadBytes(&value64, sizeof(value64))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } next_entry_offset = memory_.cur_offset() + value64; // Read the Cie Id of a Cie or the pointer of the Fde. if (!memory_.ReadBytes(&value64, sizeof(value64))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } if (value64 == static_cast<uint64_t>(-1)) { // Cie 64 bit address_encoding = DW_EH_PE_sdata8; if (!GetCieInfo(&segment_size, &address_encoding)) { return false; } cie_offset = cur_entry_offset; } else { if (offset_ + value64 != cie_offset) { // This means that this Fde is not following the Cie. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } // Fde 64 bit if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) { return false; } } } else { next_entry_offset = memory_.cur_offset() + value32; // Read the Cie Id of a Cie or the pointer of the Fde. if (!memory_.ReadBytes(&value32, sizeof(value32))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } if (value32 == static_cast<uint32_t>(-1)) { // Cie 32 bit address_encoding = DW_EH_PE_sdata4; if (!GetCieInfo(&segment_size, &address_encoding)) { return false; } cie_offset = cur_entry_offset; } else { if (offset_ + value32 != cie_offset) { // This means that this Fde is not following the Cie. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } // Fde 32 bit if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) { return false; } } } if (next_entry_offset < memory_.cur_offset()) { // This indicates some kind of corruption, or malformed section data. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } memory_.set_cur_offset(next_entry_offset); } // Sort the entries. std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) { if (a.start == b.start) return a.end < b.end; return a.start < b.start; }); fde_count_ = fdes_.size(); return true; } template <typename AddressType> bool DwarfDebugFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { if (fde_count_ == 0) { return false; } size_t first = 0; size_t last = fde_count_; while (first < last) { size_t current = (first + last) / 2; const FdeInfo* info = &fdes_[current]; if (pc >= info->start && pc <= info->end) { *fde_offset = info->offset; return true; } if (pc < info->start) { last = current; } else { first = current + 1; } } return false; } template <typename AddressType> const DwarfFde* DwarfDebugFrame<AddressType>::GetFdeFromIndex(size_t index) { if (index >= fdes_.size()) { return nullptr; } return this->GetFdeFromOffset(fdes_[index].offset); } // Explicitly instantiate DwarfDebugFrame. template class DwarfDebugFrame<uint32_t>; template class DwarfDebugFrame<uint64_t>; } // namespace unwindstack libunwindstack/DwarfDebugFrame.h +10 −40 Original line number Diff line number Diff line Loading @@ -28,51 +28,21 @@ namespace unwindstack { template <typename AddressType> class DwarfDebugFrame : public DwarfSectionImpl<AddressType> { public: // Add these so that the protected members of DwarfSectionImpl // can be accessed without needing a this->. using DwarfSectionImpl<AddressType>::memory_; using DwarfSectionImpl<AddressType>::fde_count_; using DwarfSectionImpl<AddressType>::last_error_; struct FdeInfo { FdeInfo(uint64_t offset, uint64_t start, uint64_t length) : offset(offset), start(start), end(start + length) {} uint64_t offset; AddressType start; AddressType end; }; DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {} DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) { this->cie32_value_ = static_cast<uint32_t>(-1); this->cie64_value_ = static_cast<uint64_t>(-1); } virtual ~DwarfDebugFrame() = default; bool Init(uint64_t offset, uint64_t size) override; bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; const DwarfFde* GetFdeFromIndex(size_t index) override; bool IsCie32(uint32_t value32) override { return value32 == static_cast<uint32_t>(-1); } uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { return this->entries_offset_ + pointer; } bool IsCie64(uint64_t value64) override { return value64 == static_cast<uint64_t>(-1); } uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { return offset_ + pointer; } uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { return offset_ + pointer; } uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { return this->entries_offset_ + pointer; } uint64_t AdjustPcFromFde(uint64_t pc) override { return pc; } bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding); bool AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding); bool CreateSortedFdeList(); protected: uint64_t offset_; uint64_t end_offset_; std::vector<FdeInfo> fdes_; }; } // namespace unwindstack Loading libunwindstack/DwarfEhFrame.h +5 −49 Original line number Diff line number Diff line Loading @@ -20,74 +20,30 @@ #include <stdint.h> #include <unwindstack/DwarfSection.h> #include <unwindstack/Memory.h> namespace unwindstack { // Forward declarations. class Memory; template <typename AddressType> class DwarfEhFrame : public DwarfSectionImpl<AddressType> { public: // Add these so that the protected members of DwarfSectionImpl // can be accessed without needing a this->. using DwarfSectionImpl<AddressType>::memory_; using DwarfSectionImpl<AddressType>::fde_count_; using DwarfSectionImpl<AddressType>::last_error_; struct FdeInfo { AddressType pc; uint64_t offset; }; DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {} virtual ~DwarfEhFrame() = default; bool Init(uint64_t offset, uint64_t size) override; bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; const DwarfFde* GetFdeFromIndex(size_t index) override; bool IsCie32(uint32_t value32) override { return value32 == 0; } bool IsCie64(uint64_t value64) override { return value64 == 0; } uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { return memory_.cur_offset() - pointer - 4; return this->memory_.cur_offset() - pointer - 4; } uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { return memory_.cur_offset() - pointer - 8; return this->memory_.cur_offset() - pointer - 8; } uint64_t AdjustPcFromFde(uint64_t pc) override { // The eh_frame uses relative pcs. return pc + memory_.cur_offset(); return pc + this->memory_.cur_offset(); } const FdeInfo* GetFdeInfoFromIndex(size_t index); bool GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset); bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries); protected: uint8_t version_; uint8_t ptr_encoding_; uint8_t table_encoding_; size_t table_entry_size_; uint64_t ptr_offset_; uint64_t entries_offset_; uint64_t entries_end_; uint64_t entries_data_offset_; uint64_t cur_entries_offset_ = 0; std::unordered_map<uint64_t, FdeInfo> fde_info_; }; } // namespace unwindstack #endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_H #endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H libunwindstack/DwarfEhFrame.cpp→libunwindstack/DwarfEhFrameWithHdr.cpp +12 −12 Original line number Diff line number Diff line Loading @@ -20,13 +20,13 @@ #include <unwindstack/Memory.h> #include "Check.h" #include "DwarfEhFrame.h" #include "DwarfEhFrameWithHdr.h" #include "DwarfError.h" namespace unwindstack { template <typename AddressType> bool DwarfEhFrame<AddressType>::Init(uint64_t offset, uint64_t size) { bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size) { uint8_t data[4]; memory_.clear_func_offset(); Loading Loading @@ -73,7 +73,7 @@ bool DwarfEhFrame<AddressType>::Init(uint64_t offset, uint64_t size) { } template <typename AddressType> const DwarfFde* DwarfEhFrame<AddressType>::GetFdeFromIndex(size_t index) { const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromIndex(size_t index) { const FdeInfo* info = GetFdeInfoFromIndex(index); if (info == nullptr) { return nullptr; Loading @@ -82,8 +82,8 @@ const DwarfFde* DwarfEhFrame<AddressType>::GetFdeFromIndex(size_t index) { } template <typename AddressType> const typename DwarfEhFrame<AddressType>::FdeInfo* DwarfEhFrame<AddressType>::GetFdeInfoFromIndex( size_t index) { const typename DwarfEhFrameWithHdr<AddressType>::FdeInfo* DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) { auto entry = fde_info_.find(index); if (entry != fde_info_.end()) { return &fde_info_[index]; Loading @@ -105,7 +105,7 @@ const typename DwarfEhFrame<AddressType>::FdeInfo* DwarfEhFrame<AddressType>::Ge } template <typename AddressType> bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries) { CHECK(fde_count_ > 0); CHECK(total_entries <= fde_count_); Loading Loading @@ -134,7 +134,7 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_of } template <typename AddressType> bool DwarfEhFrame<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { CHECK(fde_count_ != 0); last_error_ = DWARF_ERROR_NONE; // We can do a binary search if the pc is in the range of the elements Loading Loading @@ -196,7 +196,7 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fd } template <typename AddressType> bool DwarfEhFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { if (fde_count_ == 0) { return false; } Loading @@ -210,8 +210,8 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_of } } // Explicitly instantiate DwarfEhFrame. template class DwarfEhFrame<uint32_t>; template class DwarfEhFrame<uint64_t>; // Explicitly instantiate DwarfEhFrameWithHdr template class DwarfEhFrameWithHdr<uint32_t>; template class DwarfEhFrameWithHdr<uint64_t>; } // namespace unwindstack Loading
libunwindstack/Android.bp +2 −2 Original line number Diff line number Diff line Loading @@ -48,8 +48,7 @@ cc_library { srcs: [ "ArmExidx.cpp", "DwarfCfa.cpp", "DwarfDebugFrame.cpp", "DwarfEhFrame.cpp", "DwarfEhFrameWithHdr.cpp", "DwarfMemory.cpp", "DwarfOp.cpp", "DwarfSection.cpp", Loading Loading @@ -106,6 +105,7 @@ cc_test { "tests/DwarfCfaTest.cpp", "tests/DwarfDebugFrameTest.cpp", "tests/DwarfEhFrameTest.cpp", "tests/DwarfEhFrameWithHdrTest.cpp", "tests/DwarfMemoryTest.cpp", "tests/DwarfOpLogTest.cpp", "tests/DwarfOpTest.cpp", Loading
libunwindstack/DwarfDebugFrame.cppdeleted 100644 → 0 +0 −316 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdint.h> #include <stdlib.h> #include <algorithm> #include <unwindstack/DwarfStructs.h> #include <unwindstack/Memory.h> #include "DwarfDebugFrame.h" #include "DwarfEncoding.h" #include "DwarfError.h" namespace unwindstack { template <typename AddressType> bool DwarfDebugFrame<AddressType>::Init(uint64_t offset, uint64_t size) { offset_ = offset; end_offset_ = offset + size; memory_.clear_func_offset(); memory_.clear_text_offset(); memory_.set_data_offset(offset); memory_.set_cur_offset(offset); return CreateSortedFdeList(); } template <typename AddressType> bool DwarfDebugFrame<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) { uint8_t version; if (!memory_.ReadBytes(&version, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } // Read the augmentation string. std::vector<char> aug_string; char aug_value; bool get_encoding = false; do { if (!memory_.ReadBytes(&aug_value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } if (aug_value == 'R') { get_encoding = true; } aug_string.push_back(aug_value); } while (aug_value != '\0'); if (version == 4) { // Skip the Address Size field. memory_.set_cur_offset(memory_.cur_offset() + 1); // Read the segment size. if (!memory_.ReadBytes(segment_size, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } else { *segment_size = 0; } if (aug_string[0] != 'z' || !get_encoding) { // No encoding return true; } // Skip code alignment factor uint8_t value; do { if (!memory_.ReadBytes(&value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } while (value & 0x80); // Skip data alignment factor do { if (!memory_.ReadBytes(&value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } while (value & 0x80); if (version == 1) { // Skip return address register. memory_.set_cur_offset(memory_.cur_offset() + 1); } else { // Skip return address register. do { if (!memory_.ReadBytes(&value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } while (value & 0x80); } // Skip the augmentation length. do { if (!memory_.ReadBytes(&value, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } while (value & 0x80); for (size_t i = 1; i < aug_string.size(); i++) { if (aug_string[i] == 'R') { if (!memory_.ReadBytes(encoding, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } // Got the encoding, that's all we are looking for. return true; } else if (aug_string[i] == 'L') { memory_.set_cur_offset(memory_.cur_offset() + 1); } else if (aug_string[i] == 'P') { uint8_t encoding; if (!memory_.ReadBytes(&encoding, 1)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } uint64_t value; if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } } // It should be impossible to get here. abort(); } template <typename AddressType> bool DwarfDebugFrame<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding) { if (segment_size != 0) { memory_.set_cur_offset(memory_.cur_offset() + 1); } uint64_t start; if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } uint64_t length; if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } if (length != 0) { fdes_.emplace_back(entry_offset, start, length); } return true; } template <typename AddressType> bool DwarfDebugFrame<AddressType>::CreateSortedFdeList() { memory_.set_cur_offset(offset_); // Loop through all of the entries and read just enough to create // a sorted list of pcs. // This code assumes that first comes the cie, then the fdes that // it applies to. uint64_t cie_offset = 0; uint8_t address_encoding; uint8_t segment_size; while (memory_.cur_offset() < end_offset_) { uint64_t cur_entry_offset = memory_.cur_offset(); // Figure out the entry length and type. uint32_t value32; if (!memory_.ReadBytes(&value32, sizeof(value32))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } uint64_t next_entry_offset; if (value32 == static_cast<uint32_t>(-1)) { uint64_t value64; if (!memory_.ReadBytes(&value64, sizeof(value64))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } next_entry_offset = memory_.cur_offset() + value64; // Read the Cie Id of a Cie or the pointer of the Fde. if (!memory_.ReadBytes(&value64, sizeof(value64))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } if (value64 == static_cast<uint64_t>(-1)) { // Cie 64 bit address_encoding = DW_EH_PE_sdata8; if (!GetCieInfo(&segment_size, &address_encoding)) { return false; } cie_offset = cur_entry_offset; } else { if (offset_ + value64 != cie_offset) { // This means that this Fde is not following the Cie. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } // Fde 64 bit if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) { return false; } } } else { next_entry_offset = memory_.cur_offset() + value32; // Read the Cie Id of a Cie or the pointer of the Fde. if (!memory_.ReadBytes(&value32, sizeof(value32))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } if (value32 == static_cast<uint32_t>(-1)) { // Cie 32 bit address_encoding = DW_EH_PE_sdata4; if (!GetCieInfo(&segment_size, &address_encoding)) { return false; } cie_offset = cur_entry_offset; } else { if (offset_ + value32 != cie_offset) { // This means that this Fde is not following the Cie. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } // Fde 32 bit if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) { return false; } } } if (next_entry_offset < memory_.cur_offset()) { // This indicates some kind of corruption, or malformed section data. last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } memory_.set_cur_offset(next_entry_offset); } // Sort the entries. std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) { if (a.start == b.start) return a.end < b.end; return a.start < b.start; }); fde_count_ = fdes_.size(); return true; } template <typename AddressType> bool DwarfDebugFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { if (fde_count_ == 0) { return false; } size_t first = 0; size_t last = fde_count_; while (first < last) { size_t current = (first + last) / 2; const FdeInfo* info = &fdes_[current]; if (pc >= info->start && pc <= info->end) { *fde_offset = info->offset; return true; } if (pc < info->start) { last = current; } else { first = current + 1; } } return false; } template <typename AddressType> const DwarfFde* DwarfDebugFrame<AddressType>::GetFdeFromIndex(size_t index) { if (index >= fdes_.size()) { return nullptr; } return this->GetFdeFromOffset(fdes_[index].offset); } // Explicitly instantiate DwarfDebugFrame. template class DwarfDebugFrame<uint32_t>; template class DwarfDebugFrame<uint64_t>; } // namespace unwindstack
libunwindstack/DwarfDebugFrame.h +10 −40 Original line number Diff line number Diff line Loading @@ -28,51 +28,21 @@ namespace unwindstack { template <typename AddressType> class DwarfDebugFrame : public DwarfSectionImpl<AddressType> { public: // Add these so that the protected members of DwarfSectionImpl // can be accessed without needing a this->. using DwarfSectionImpl<AddressType>::memory_; using DwarfSectionImpl<AddressType>::fde_count_; using DwarfSectionImpl<AddressType>::last_error_; struct FdeInfo { FdeInfo(uint64_t offset, uint64_t start, uint64_t length) : offset(offset), start(start), end(start + length) {} uint64_t offset; AddressType start; AddressType end; }; DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {} DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) { this->cie32_value_ = static_cast<uint32_t>(-1); this->cie64_value_ = static_cast<uint64_t>(-1); } virtual ~DwarfDebugFrame() = default; bool Init(uint64_t offset, uint64_t size) override; bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; const DwarfFde* GetFdeFromIndex(size_t index) override; bool IsCie32(uint32_t value32) override { return value32 == static_cast<uint32_t>(-1); } uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { return this->entries_offset_ + pointer; } bool IsCie64(uint64_t value64) override { return value64 == static_cast<uint64_t>(-1); } uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { return offset_ + pointer; } uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { return offset_ + pointer; } uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { return this->entries_offset_ + pointer; } uint64_t AdjustPcFromFde(uint64_t pc) override { return pc; } bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding); bool AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding); bool CreateSortedFdeList(); protected: uint64_t offset_; uint64_t end_offset_; std::vector<FdeInfo> fdes_; }; } // namespace unwindstack Loading
libunwindstack/DwarfEhFrame.h +5 −49 Original line number Diff line number Diff line Loading @@ -20,74 +20,30 @@ #include <stdint.h> #include <unwindstack/DwarfSection.h> #include <unwindstack/Memory.h> namespace unwindstack { // Forward declarations. class Memory; template <typename AddressType> class DwarfEhFrame : public DwarfSectionImpl<AddressType> { public: // Add these so that the protected members of DwarfSectionImpl // can be accessed without needing a this->. using DwarfSectionImpl<AddressType>::memory_; using DwarfSectionImpl<AddressType>::fde_count_; using DwarfSectionImpl<AddressType>::last_error_; struct FdeInfo { AddressType pc; uint64_t offset; }; DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {} virtual ~DwarfEhFrame() = default; bool Init(uint64_t offset, uint64_t size) override; bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; const DwarfFde* GetFdeFromIndex(size_t index) override; bool IsCie32(uint32_t value32) override { return value32 == 0; } bool IsCie64(uint64_t value64) override { return value64 == 0; } uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { return memory_.cur_offset() - pointer - 4; return this->memory_.cur_offset() - pointer - 4; } uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { return memory_.cur_offset() - pointer - 8; return this->memory_.cur_offset() - pointer - 8; } uint64_t AdjustPcFromFde(uint64_t pc) override { // The eh_frame uses relative pcs. return pc + memory_.cur_offset(); return pc + this->memory_.cur_offset(); } const FdeInfo* GetFdeInfoFromIndex(size_t index); bool GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset); bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries); protected: uint8_t version_; uint8_t ptr_encoding_; uint8_t table_encoding_; size_t table_entry_size_; uint64_t ptr_offset_; uint64_t entries_offset_; uint64_t entries_end_; uint64_t entries_data_offset_; uint64_t cur_entries_offset_ = 0; std::unordered_map<uint64_t, FdeInfo> fde_info_; }; } // namespace unwindstack #endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_H #endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
libunwindstack/DwarfEhFrame.cpp→libunwindstack/DwarfEhFrameWithHdr.cpp +12 −12 Original line number Diff line number Diff line Loading @@ -20,13 +20,13 @@ #include <unwindstack/Memory.h> #include "Check.h" #include "DwarfEhFrame.h" #include "DwarfEhFrameWithHdr.h" #include "DwarfError.h" namespace unwindstack { template <typename AddressType> bool DwarfEhFrame<AddressType>::Init(uint64_t offset, uint64_t size) { bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size) { uint8_t data[4]; memory_.clear_func_offset(); Loading Loading @@ -73,7 +73,7 @@ bool DwarfEhFrame<AddressType>::Init(uint64_t offset, uint64_t size) { } template <typename AddressType> const DwarfFde* DwarfEhFrame<AddressType>::GetFdeFromIndex(size_t index) { const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromIndex(size_t index) { const FdeInfo* info = GetFdeInfoFromIndex(index); if (info == nullptr) { return nullptr; Loading @@ -82,8 +82,8 @@ const DwarfFde* DwarfEhFrame<AddressType>::GetFdeFromIndex(size_t index) { } template <typename AddressType> const typename DwarfEhFrame<AddressType>::FdeInfo* DwarfEhFrame<AddressType>::GetFdeInfoFromIndex( size_t index) { const typename DwarfEhFrameWithHdr<AddressType>::FdeInfo* DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) { auto entry = fde_info_.find(index); if (entry != fde_info_.end()) { return &fde_info_[index]; Loading @@ -105,7 +105,7 @@ const typename DwarfEhFrame<AddressType>::FdeInfo* DwarfEhFrame<AddressType>::Ge } template <typename AddressType> bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries) { CHECK(fde_count_ > 0); CHECK(total_entries <= fde_count_); Loading Loading @@ -134,7 +134,7 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_of } template <typename AddressType> bool DwarfEhFrame<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { CHECK(fde_count_ != 0); last_error_ = DWARF_ERROR_NONE; // We can do a binary search if the pc is in the range of the elements Loading Loading @@ -196,7 +196,7 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fd } template <typename AddressType> bool DwarfEhFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { if (fde_count_ == 0) { return false; } Loading @@ -210,8 +210,8 @@ bool DwarfEhFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_of } } // Explicitly instantiate DwarfEhFrame. template class DwarfEhFrame<uint32_t>; template class DwarfEhFrame<uint64_t>; // Explicitly instantiate DwarfEhFrameWithHdr template class DwarfEhFrameWithHdr<uint32_t>; template class DwarfEhFrameWithHdr<uint64_t>; } // namespace unwindstack