Loading libunwindstack/DwarfEhFrameWithHdr.cpp +13 −86 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,14 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint table_encoding_ = data[3]; table_encoding_ = data[3]; table_entry_size_ = memory_.template GetEncodedSize<AddressType>(table_encoding_); table_entry_size_ = memory_.template GetEncodedSize<AddressType>(table_encoding_); // If we can't perform a binary search on the entries, it's not worth // using this object. The calling code will fall back to the DwarfEhFrame // object in this case. if (table_entry_size_ == 0) { last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; return false; } memory_.set_pc_offset(memory_.cur_offset()); memory_.set_pc_offset(memory_.cur_offset()); if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) { if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) { last_error_.code = DWARF_ERROR_MEMORY_INVALID; last_error_.code = DWARF_ERROR_MEMORY_INVALID; Loading Loading @@ -137,13 +145,13 @@ DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) { } } template <typename AddressType> template <typename AddressType> bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { uint64_t total_entries) { if (fde_count_ == 0) { CHECK(fde_count_ > 0); return false; CHECK(total_entries <= fde_count_); } size_t first = 0; size_t first = 0; size_t last = total_entries; size_t last = fde_count_; while (first < last) { while (first < last) { size_t current = (first + last) / 2; size_t current = (first + last) / 2; const FdeInfo* info = GetFdeInfoFromIndex(current); const FdeInfo* info = GetFdeInfoFromIndex(current); Loading Loading @@ -171,87 +179,6 @@ bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* return false; return false; } } template <typename AddressType> bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { CHECK(fde_count_ != 0); last_error_.code = DWARF_ERROR_NONE; last_error_.address = 0; // We can do a binary search if the pc is in the range of the elements // that have already been cached. if (!fde_info_.empty()) { const FdeInfo* info = &fde_info_[fde_info_.size() - 1]; if (pc >= info->pc) { *fde_offset = info->offset; return true; } if (pc < info->pc) { return GetFdeOffsetBinary(pc, fde_offset, fde_info_.size()); } } if (cur_entries_offset_ == 0) { // All entries read, or error encountered. return false; } memory_.set_data_offset(entries_data_offset_); memory_.set_cur_offset(cur_entries_offset_); memory_.set_pc_offset(0); cur_entries_offset_ = 0; FdeInfo* prev_info = nullptr; for (size_t current = fde_info_.size(); current < fde_count_ && memory_.cur_offset() < entries_end_; current++) { FdeInfo* info = &fde_info_[current]; uint64_t value; if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) || !memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) { fde_info_.erase(current); last_error_.code = DWARF_ERROR_MEMORY_INVALID; last_error_.address = memory_.cur_offset(); return false; } // Relative encodings require adding in the load bias. if (IsEncodingRelative(table_encoding_)) { value += load_bias_; } info->pc = value; if (pc < info->pc) { if (prev_info == nullptr) { return false; } cur_entries_offset_ = memory_.cur_offset(); *fde_offset = prev_info->offset; return true; } prev_info = info; } if (fde_count_ == fde_info_.size() && pc >= prev_info->pc) { *fde_offset = prev_info->offset; return true; } return false; } template <typename AddressType> bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { if (fde_count_ == 0) { return false; } if (table_entry_size_ > 0) { // Do a binary search since the size of each table entry is fixed. return GetFdeOffsetBinary(pc, fde_offset, fde_count_); } else { // Do a sequential search since each table entry size is variable. return GetFdeOffsetSequential(pc, fde_offset); } } template <typename AddressType> template <typename AddressType> void DwarfEhFrameWithHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) { void DwarfEhFrameWithHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) { for (size_t i = 0; i < fde_count_; i++) { for (size_t i = 0; i < fde_count_; i++) { Loading libunwindstack/DwarfEhFrameWithHdr.h +0 −4 Original line number Original line Diff line number Diff line Loading @@ -69,10 +69,6 @@ class DwarfEhFrameWithHdr : public DwarfSectionImpl<AddressType> { const FdeInfo* GetFdeInfoFromIndex(size_t index); 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); void GetFdes(std::vector<const DwarfFde*>* fdes) override; void GetFdes(std::vector<const DwarfFde*>* fdes) override; protected: protected: Loading libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp +31 −110 Original line number Original line Diff line number Diff line Loading @@ -95,6 +95,13 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) { EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset()); EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset()); EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset()); EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset()); // Verify a zero table entry size fails to init. this->memory_.SetData8(0x1003, 0x1); ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode()); // Reset the value back to the original. this->memory_.SetData8(0x1003, DW_EH_PE_sdata4); // Verify a zero fde count fails to init. // Verify a zero fde count fails to init. this->memory_.SetData32(0x1006, 0); this->memory_.SetData32(0x1006, 0); ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); Loading Loading @@ -276,9 +283,8 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_cached) { EXPECT_EQ(0x500U, info->offset); EXPECT_EQ(0x500U, info->offset); } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_verify) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_verify) { this->eh_frame_->TestSetTableEntrySize(0x10); this->eh_frame_->TestSetTableEntrySize(0x10); this->eh_frame_->TestSetFdeCount(10); typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; for (size_t i = 0; i < 10; i++) { for (size_t i = 0; i < 10; i++) { Loading @@ -288,105 +294,42 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_verify) { } } uint64_t fde_offset; uint64_t fde_offset; EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10)); this->eh_frame_->TestSetFdeCount(10); EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); // Not an error, just not found. // Not an error, just not found. ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); // Even number of elements. // Even number of elements. for (size_t i = 0; i < 10; i++) { for (size_t i = 0; i < 10; i++) { SCOPED_TRACE(testing::Message() << "Failed at index " << i); TypeParam pc = 0x1000 * (i + 1); TypeParam pc = 0x1000 * (i + 1); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 10)) << "Failed at index " << i; EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)); EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 10)) EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)); << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset); EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 10)) EXPECT_EQ(0x5000 + i * 0x20, fde_offset); << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; } } // Odd number of elements. // Odd number of elements. this->eh_frame_->TestSetFdeCount(9); for (size_t i = 0; i < 9; i++) { for (size_t i = 0; i < 9; i++) { SCOPED_TRACE(testing::Message() << "Failed at index " << i); TypeParam pc = 0x1000 * (i + 1); TypeParam pc = 0x1000 * (i + 1); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 9)) << "Failed at index " << i; EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)); EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 9)) EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)); << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset); EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 9)) EXPECT_EQ(0x5000 + i * 0x20, fde_offset); << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; } } } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_index_fail) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_index_fail) { this->eh_frame_->TestSetTableEntrySize(0x10); this->eh_frame_->TestSetTableEntrySize(0x10); this->eh_frame_->TestSetFdeCount(10); this->eh_frame_->TestSetFdeCount(10); uint64_t fde_offset; uint64_t fde_offset; EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x1000, &fde_offset, 10)); EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset)); } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential) { this->eh_frame_->TestSetFdeCount(10); this->eh_frame_->TestSetEntriesDataOffset(0x100); this->eh_frame_->TestSetEntriesEnd(0x2000); this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); this->memory_.SetData32(0x1040, 0x340); this->memory_.SetData32(0x1044, 0x500); this->memory_.SetData32(0x1048, 0x440); this->memory_.SetData32(0x104c, 0x600); // Verify that if entries is zero, that it fails. uint64_t fde_offset; ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset)); this->eh_frame_->TestSetCurEntriesOffset(0x1040); ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset)); EXPECT_EQ(0x500U, fde_offset); ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset)); EXPECT_EQ(0x600U, fde_offset); // Expect that the data is cached so no more memory reads will occur. this->memory_.Clear(); ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset)); EXPECT_EQ(0x600U, fde_offset); } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_last_element) { this->eh_frame_->TestSetFdeCount(2); this->eh_frame_->TestSetEntriesDataOffset(0x100); this->eh_frame_->TestSetEntriesEnd(0x2000); this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); this->eh_frame_->TestSetCurEntriesOffset(0x1040); this->memory_.SetData32(0x1040, 0x340); this->memory_.SetData32(0x1044, 0x500); this->memory_.SetData32(0x1048, 0x440); this->memory_.SetData32(0x104c, 0x600); uint64_t fde_offset; ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset)); EXPECT_EQ(0x600U, fde_offset); } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_end_check) { this->eh_frame_->TestSetFdeCount(2); this->eh_frame_->TestSetEntriesDataOffset(0x100); this->eh_frame_->TestSetEntriesEnd(0x1048); this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); this->memory_.SetData32(0x1040, 0x340); this->memory_.SetData32(0x1044, 0x500); this->memory_.SetData32(0x1048, 0x440); this->memory_.SetData32(0x104c, 0x600); uint64_t fde_offset; ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset)); ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) { Loading @@ -397,7 +340,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) { ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_binary_search) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_search) { this->eh_frame_->TestSetTableEntrySize(16); this->eh_frame_->TestSetTableEntrySize(16); this->eh_frame_->TestSetFdeCount(10); this->eh_frame_->TestSetFdeCount(10); Loading @@ -417,26 +360,6 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_binary_search) { EXPECT_EQ(0x10700U, fde_offset); EXPECT_EQ(0x10700U, fde_offset); } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_sequential_search) { this->eh_frame_->TestSetFdeCount(10); this->eh_frame_->TestSetTableEntrySize(0); typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; info.pc = 0x50; info.offset = 0x10000; this->eh_frame_->TestSetFdeInfo(0, info); info.pc = 0x150; info.offset = 0x10100; this->eh_frame_->TestSetFdeInfo(1, info); info.pc = 0x250; info.offset = 0x10200; this->eh_frame_->TestSetFdeInfo(2, info); uint64_t fde_offset; ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x200, &fde_offset)); EXPECT_EQ(0x10100U, fde_offset); } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) { // CIE 32 information. // CIE 32 information. this->memory_.SetData32(0xf000, 0x100); this->memory_.SetData32(0xf000, 0x100); Loading Loading @@ -526,10 +449,8 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) { REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, GetFdes, REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, GetFdes, GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached, GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached, GetFdeOffsetBinary_verify, GetFdeOffsetBinary_index_fail, GetFdeOffsetFromPc_verify, GetFdeOffsetFromPc_index_fail, GetFdeOffsetSequential, GetFdeOffsetSequential_last_element, GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_search, GetFdeOffsetSequential_end_check, GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_binary_search, GetFdeOffsetFromPc_sequential_search, GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found); GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found); typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes; typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes; Loading Loading
libunwindstack/DwarfEhFrameWithHdr.cpp +13 −86 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,14 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint table_encoding_ = data[3]; table_encoding_ = data[3]; table_entry_size_ = memory_.template GetEncodedSize<AddressType>(table_encoding_); table_entry_size_ = memory_.template GetEncodedSize<AddressType>(table_encoding_); // If we can't perform a binary search on the entries, it's not worth // using this object. The calling code will fall back to the DwarfEhFrame // object in this case. if (table_entry_size_ == 0) { last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; return false; } memory_.set_pc_offset(memory_.cur_offset()); memory_.set_pc_offset(memory_.cur_offset()); if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) { if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) { last_error_.code = DWARF_ERROR_MEMORY_INVALID; last_error_.code = DWARF_ERROR_MEMORY_INVALID; Loading Loading @@ -137,13 +145,13 @@ DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) { } } template <typename AddressType> template <typename AddressType> bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { uint64_t total_entries) { if (fde_count_ == 0) { CHECK(fde_count_ > 0); return false; CHECK(total_entries <= fde_count_); } size_t first = 0; size_t first = 0; size_t last = total_entries; size_t last = fde_count_; while (first < last) { while (first < last) { size_t current = (first + last) / 2; size_t current = (first + last) / 2; const FdeInfo* info = GetFdeInfoFromIndex(current); const FdeInfo* info = GetFdeInfoFromIndex(current); Loading Loading @@ -171,87 +179,6 @@ bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t* return false; return false; } } template <typename AddressType> bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { CHECK(fde_count_ != 0); last_error_.code = DWARF_ERROR_NONE; last_error_.address = 0; // We can do a binary search if the pc is in the range of the elements // that have already been cached. if (!fde_info_.empty()) { const FdeInfo* info = &fde_info_[fde_info_.size() - 1]; if (pc >= info->pc) { *fde_offset = info->offset; return true; } if (pc < info->pc) { return GetFdeOffsetBinary(pc, fde_offset, fde_info_.size()); } } if (cur_entries_offset_ == 0) { // All entries read, or error encountered. return false; } memory_.set_data_offset(entries_data_offset_); memory_.set_cur_offset(cur_entries_offset_); memory_.set_pc_offset(0); cur_entries_offset_ = 0; FdeInfo* prev_info = nullptr; for (size_t current = fde_info_.size(); current < fde_count_ && memory_.cur_offset() < entries_end_; current++) { FdeInfo* info = &fde_info_[current]; uint64_t value; if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) || !memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) { fde_info_.erase(current); last_error_.code = DWARF_ERROR_MEMORY_INVALID; last_error_.address = memory_.cur_offset(); return false; } // Relative encodings require adding in the load bias. if (IsEncodingRelative(table_encoding_)) { value += load_bias_; } info->pc = value; if (pc < info->pc) { if (prev_info == nullptr) { return false; } cur_entries_offset_ = memory_.cur_offset(); *fde_offset = prev_info->offset; return true; } prev_info = info; } if (fde_count_ == fde_info_.size() && pc >= prev_info->pc) { *fde_offset = prev_info->offset; return true; } return false; } template <typename AddressType> bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { if (fde_count_ == 0) { return false; } if (table_entry_size_ > 0) { // Do a binary search since the size of each table entry is fixed. return GetFdeOffsetBinary(pc, fde_offset, fde_count_); } else { // Do a sequential search since each table entry size is variable. return GetFdeOffsetSequential(pc, fde_offset); } } template <typename AddressType> template <typename AddressType> void DwarfEhFrameWithHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) { void DwarfEhFrameWithHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) { for (size_t i = 0; i < fde_count_; i++) { for (size_t i = 0; i < fde_count_; i++) { Loading
libunwindstack/DwarfEhFrameWithHdr.h +0 −4 Original line number Original line Diff line number Diff line Loading @@ -69,10 +69,6 @@ class DwarfEhFrameWithHdr : public DwarfSectionImpl<AddressType> { const FdeInfo* GetFdeInfoFromIndex(size_t index); 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); void GetFdes(std::vector<const DwarfFde*>* fdes) override; void GetFdes(std::vector<const DwarfFde*>* fdes) override; protected: protected: Loading
libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp +31 −110 Original line number Original line Diff line number Diff line Loading @@ -95,6 +95,13 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) { EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset()); EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset()); EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset()); EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset()); // Verify a zero table entry size fails to init. this->memory_.SetData8(0x1003, 0x1); ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode()); // Reset the value back to the original. this->memory_.SetData8(0x1003, DW_EH_PE_sdata4); // Verify a zero fde count fails to init. // Verify a zero fde count fails to init. this->memory_.SetData32(0x1006, 0); this->memory_.SetData32(0x1006, 0); ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); Loading Loading @@ -276,9 +283,8 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_cached) { EXPECT_EQ(0x500U, info->offset); EXPECT_EQ(0x500U, info->offset); } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_verify) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_verify) { this->eh_frame_->TestSetTableEntrySize(0x10); this->eh_frame_->TestSetTableEntrySize(0x10); this->eh_frame_->TestSetFdeCount(10); typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; for (size_t i = 0; i < 10; i++) { for (size_t i = 0; i < 10; i++) { Loading @@ -288,105 +294,42 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_verify) { } } uint64_t fde_offset; uint64_t fde_offset; EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10)); this->eh_frame_->TestSetFdeCount(10); EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); // Not an error, just not found. // Not an error, just not found. ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); // Even number of elements. // Even number of elements. for (size_t i = 0; i < 10; i++) { for (size_t i = 0; i < 10; i++) { SCOPED_TRACE(testing::Message() << "Failed at index " << i); TypeParam pc = 0x1000 * (i + 1); TypeParam pc = 0x1000 * (i + 1); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 10)) << "Failed at index " << i; EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)); EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 10)) EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)); << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset); EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 10)) EXPECT_EQ(0x5000 + i * 0x20, fde_offset); << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; } } // Odd number of elements. // Odd number of elements. this->eh_frame_->TestSetFdeCount(9); for (size_t i = 0; i < 9; i++) { for (size_t i = 0; i < 9; i++) { SCOPED_TRACE(testing::Message() << "Failed at index " << i); TypeParam pc = 0x1000 * (i + 1); TypeParam pc = 0x1000 * (i + 1); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc, &fde_offset, 9)) << "Failed at index " << i; EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)); EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 1, &fde_offset, 9)) EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)); << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset); EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)); EXPECT_TRUE(this->eh_frame_->GetFdeOffsetBinary(pc + 0xfff, &fde_offset, 9)) EXPECT_EQ(0x5000 + i * 0x20, fde_offset); << "Failed at index " << i; EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; } } } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_index_fail) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_index_fail) { this->eh_frame_->TestSetTableEntrySize(0x10); this->eh_frame_->TestSetTableEntrySize(0x10); this->eh_frame_->TestSetFdeCount(10); this->eh_frame_->TestSetFdeCount(10); uint64_t fde_offset; uint64_t fde_offset; EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x1000, &fde_offset, 10)); EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset)); } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential) { this->eh_frame_->TestSetFdeCount(10); this->eh_frame_->TestSetEntriesDataOffset(0x100); this->eh_frame_->TestSetEntriesEnd(0x2000); this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); this->memory_.SetData32(0x1040, 0x340); this->memory_.SetData32(0x1044, 0x500); this->memory_.SetData32(0x1048, 0x440); this->memory_.SetData32(0x104c, 0x600); // Verify that if entries is zero, that it fails. uint64_t fde_offset; ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset)); this->eh_frame_->TestSetCurEntriesOffset(0x1040); ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x344, &fde_offset)); EXPECT_EQ(0x500U, fde_offset); ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset)); EXPECT_EQ(0x600U, fde_offset); // Expect that the data is cached so no more memory reads will occur. this->memory_.Clear(); ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x444, &fde_offset)); EXPECT_EQ(0x600U, fde_offset); } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_last_element) { this->eh_frame_->TestSetFdeCount(2); this->eh_frame_->TestSetEntriesDataOffset(0x100); this->eh_frame_->TestSetEntriesEnd(0x2000); this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); this->eh_frame_->TestSetCurEntriesOffset(0x1040); this->memory_.SetData32(0x1040, 0x340); this->memory_.SetData32(0x1044, 0x500); this->memory_.SetData32(0x1048, 0x440); this->memory_.SetData32(0x104c, 0x600); uint64_t fde_offset; ASSERT_TRUE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset)); EXPECT_EQ(0x600U, fde_offset); } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_end_check) { this->eh_frame_->TestSetFdeCount(2); this->eh_frame_->TestSetEntriesDataOffset(0x100); this->eh_frame_->TestSetEntriesEnd(0x1048); this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); this->memory_.SetData32(0x1040, 0x340); this->memory_.SetData32(0x1044, 0x500); this->memory_.SetData32(0x1048, 0x440); this->memory_.SetData32(0x104c, 0x600); uint64_t fde_offset; ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset)); ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) { Loading @@ -397,7 +340,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) { ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_binary_search) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_search) { this->eh_frame_->TestSetTableEntrySize(16); this->eh_frame_->TestSetTableEntrySize(16); this->eh_frame_->TestSetFdeCount(10); this->eh_frame_->TestSetFdeCount(10); Loading @@ -417,26 +360,6 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_binary_search) { EXPECT_EQ(0x10700U, fde_offset); EXPECT_EQ(0x10700U, fde_offset); } } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_sequential_search) { this->eh_frame_->TestSetFdeCount(10); this->eh_frame_->TestSetTableEntrySize(0); typename DwarfEhFrameWithHdr<TypeParam>::FdeInfo info; info.pc = 0x50; info.offset = 0x10000; this->eh_frame_->TestSetFdeInfo(0, info); info.pc = 0x150; info.offset = 0x10100; this->eh_frame_->TestSetFdeInfo(1, info); info.pc = 0x250; info.offset = 0x10200; this->eh_frame_->TestSetFdeInfo(2, info); uint64_t fde_offset; ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x200, &fde_offset)); EXPECT_EQ(0x10100U, fde_offset); } TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) { TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) { // CIE 32 information. // CIE 32 information. this->memory_.SetData32(0xf000, 0x100); this->memory_.SetData32(0xf000, 0x100); Loading Loading @@ -526,10 +449,8 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) { REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, GetFdes, REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, GetFdes, GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached, GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached, GetFdeOffsetBinary_verify, GetFdeOffsetBinary_index_fail, GetFdeOffsetFromPc_verify, GetFdeOffsetFromPc_index_fail, GetFdeOffsetSequential, GetFdeOffsetSequential_last_element, GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_search, GetFdeOffsetSequential_end_check, GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_binary_search, GetFdeOffsetFromPc_sequential_search, GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found); GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found); typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes; typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes; Loading