Merge "Fix potential bad info in eh_frame_hdr."
am: 2ff3c44304
Change-Id: I6aeb0de40059f630c748a09b0c37eec57cb5ebbd
diff --git a/libunwindstack/DwarfDebugFrame.h b/libunwindstack/DwarfDebugFrame.h
index 388ab0a..635cefd 100644
--- a/libunwindstack/DwarfDebugFrame.h
+++ b/libunwindstack/DwarfDebugFrame.h
@@ -26,9 +26,9 @@
namespace unwindstack {
template <typename AddressType>
-class DwarfDebugFrame : public DwarfSectionImplNoHdr<AddressType> {
+class DwarfDebugFrame : public DwarfSectionImpl<AddressType> {
public:
- DwarfDebugFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {
+ DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {
this->cie32_value_ = static_cast<uint32_t>(-1);
this->cie64_value_ = static_cast<uint64_t>(-1);
}
diff --git a/libunwindstack/DwarfEhFrame.h b/libunwindstack/DwarfEhFrame.h
index df441fb..7a41e45 100644
--- a/libunwindstack/DwarfEhFrame.h
+++ b/libunwindstack/DwarfEhFrame.h
@@ -25,9 +25,9 @@
namespace unwindstack {
template <typename AddressType>
-class DwarfEhFrame : public DwarfSectionImplNoHdr<AddressType> {
+class DwarfEhFrame : public DwarfSectionImpl<AddressType> {
public:
- DwarfEhFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {}
+ DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
virtual ~DwarfEhFrame() = default;
uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
diff --git a/libunwindstack/DwarfEhFrameWithHdr.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp
index 24b94f0..1358e51 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.cpp
+++ b/libunwindstack/DwarfEhFrameWithHdr.cpp
@@ -32,14 +32,19 @@
}
template <typename AddressType>
-bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, int64_t section_bias) {
- section_bias_ = section_bias;
+bool DwarfEhFrameWithHdr<AddressType>::EhFrameInit(uint64_t offset, uint64_t size,
+ int64_t section_bias) {
+ return DwarfSectionImpl<AddressType>::Init(offset, size, section_bias);
+}
+template <typename AddressType>
+bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t, int64_t section_bias) {
memory_.clear_func_offset();
memory_.clear_text_offset();
memory_.set_data_offset(offset);
memory_.set_cur_offset(offset);
- pc_offset_ = offset;
+
+ hdr_section_bias_ = section_bias;
// Read the first four bytes all at once.
uint8_t data[4];
@@ -56,7 +61,7 @@
return false;
}
- ptr_encoding_ = data[1];
+ uint8_t ptr_encoding = data[1];
uint8_t fde_count_encoding = data[2];
table_encoding_ = data[3];
table_entry_size_ = memory_.template GetEncodedSize<AddressType>(table_encoding_);
@@ -70,7 +75,8 @@
}
memory_.set_pc_offset(memory_.cur_offset());
- if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) {
+ uint64_t ptr_offset;
+ if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding, &ptr_offset)) {
last_error_.code = DWARF_ERROR_MEMORY_INVALID;
last_error_.address = memory_.cur_offset();
return false;
@@ -88,10 +94,8 @@
return false;
}
- entries_offset_ = memory_.cur_offset();
- entries_end_ = offset + size;
- entries_data_offset_ = offset;
- cur_entries_offset_ = entries_offset_;
+ hdr_entries_offset_ = memory_.cur_offset();
+ hdr_entries_data_offset_ = offset;
return true;
}
@@ -107,6 +111,16 @@
return nullptr;
}
+ // There is a possibility that this entry points to a zero length FDE
+ // due to a bug. If this happens, try and find the non-zero length FDE
+ // from eh_frame directly. See b/142483624.
+ if (fde->pc_start == fde->pc_end) {
+ fde = DwarfSectionImpl<AddressType>::GetFdeFromPc(pc);
+ if (fde == nullptr) {
+ return nullptr;
+ }
+ }
+
// Guaranteed pc >= pc_start, need to check pc in the fde range.
if (pc < fde->pc_end) {
return fde;
@@ -124,8 +138,8 @@
}
FdeInfo* info = &fde_info_[index];
- memory_.set_data_offset(entries_data_offset_);
- memory_.set_cur_offset(entries_offset_ + 2 * index * table_entry_size_);
+ memory_.set_data_offset(hdr_entries_data_offset_);
+ memory_.set_cur_offset(hdr_entries_offset_ + 2 * index * table_entry_size_);
memory_.set_pc_offset(0);
uint64_t value;
if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) ||
@@ -138,7 +152,7 @@
// Relative encodings require adding in the load bias.
if (IsEncodingRelative(table_encoding_)) {
- value += section_bias_;
+ value += hdr_section_bias_;
}
info->pc = value;
return info;
@@ -190,6 +204,16 @@
if (fde == nullptr) {
break;
}
+
+ // There is a possibility that this entry points to a zero length FDE
+ // due to a bug. If this happens, try and find the non-zero length FDE
+ // from eh_frame directly. See b/142483624.
+ if (fde->pc_start == fde->pc_end) {
+ const DwarfFde* fde_real = DwarfSectionImpl<AddressType>::GetFdeFromPc(fde->pc_start);
+ if (fde_real != nullptr) {
+ fde = fde_real;
+ }
+ }
fdes->push_back(fde);
}
}
diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h
index b8dd3dd..f7c010c 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.h
+++ b/libunwindstack/DwarfEhFrameWithHdr.h
@@ -34,11 +34,7 @@
// Add these so that the protected members of DwarfSectionImpl
// can be accessed without needing a this->.
using DwarfSectionImpl<AddressType>::memory_;
- using DwarfSectionImpl<AddressType>::pc_offset_;
- using DwarfSectionImpl<AddressType>::entries_offset_;
- using DwarfSectionImpl<AddressType>::entries_end_;
using DwarfSectionImpl<AddressType>::last_error_;
- using DwarfSectionImpl<AddressType>::section_bias_;
struct FdeInfo {
AddressType pc;
@@ -49,18 +45,19 @@
virtual ~DwarfEhFrameWithHdr() = default;
uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
- return this->memory_.cur_offset() - pointer - 4;
+ return memory_.cur_offset() - pointer - 4;
}
uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
- return this->memory_.cur_offset() - pointer - 8;
+ return memory_.cur_offset() - pointer - 8;
}
uint64_t AdjustPcFromFde(uint64_t pc) override {
// The eh_frame uses relative pcs.
- return pc + this->memory_.cur_offset() - 4;
+ return pc + memory_.cur_offset() - 4;
}
+ bool EhFrameInit(uint64_t offset, uint64_t size, int64_t section_bias);
bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
const DwarfFde* GetFdeFromPc(uint64_t pc) override;
@@ -72,17 +69,15 @@
void GetFdes(std::vector<const DwarfFde*>* fdes) override;
protected:
- uint8_t version_;
- uint8_t ptr_encoding_;
- uint8_t table_encoding_;
- size_t table_entry_size_;
+ uint8_t version_ = 0;
+ uint8_t table_encoding_ = 0;
+ size_t table_entry_size_ = 0;
- uint64_t ptr_offset_;
+ uint64_t hdr_entries_offset_ = 0;
+ uint64_t hdr_entries_data_offset_ = 0;
+ uint64_t hdr_section_bias_ = 0;
- uint64_t entries_data_offset_;
- uint64_t cur_entries_offset_ = 0;
-
- uint64_t fde_count_;
+ uint64_t fde_count_ = 0;
std::unordered_map<uint64_t, FdeInfo> fde_info_;
};
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index cdb6141..e6263f8 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -69,6 +69,7 @@
return &cie_entry->second;
}
DwarfCie* cie = &cie_entries_[offset];
+ memory_.set_data_offset(entries_offset_);
memory_.set_cur_offset(offset);
if (!FillInCieHeader(cie) || !FillInCie(cie)) {
// Erase the cached entry.
@@ -251,6 +252,7 @@
return &fde_entry->second;
}
DwarfFde* fde = &fde_entries_[offset];
+ memory_.set_data_offset(entries_offset_);
memory_.set_cur_offset(offset);
if (!FillInFdeHeader(fde) || !FillInFde(fde)) {
fde_entries_.erase(offset);
@@ -591,8 +593,7 @@
}
template <typename AddressType>
-bool DwarfSectionImplNoHdr<AddressType>::Init(uint64_t offset, uint64_t size,
- int64_t section_bias) {
+bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size, int64_t section_bias) {
section_bias_ = section_bias;
entries_offset_ = offset;
next_entries_offset_ = offset;
@@ -601,7 +602,6 @@
memory_.clear_func_offset();
memory_.clear_text_offset();
memory_.set_cur_offset(offset);
- memory_.set_data_offset(offset);
pc_offset_ = offset;
return true;
@@ -617,7 +617,7 @@
// and an fde has a start pc of 0x100 and end pc of 0x500, two new entries
// will be added: 0x200, 0x100 and 0x500, 0x400.
template <typename AddressType>
-void DwarfSectionImplNoHdr<AddressType>::InsertFde(const DwarfFde* fde) {
+void DwarfSectionImpl<AddressType>::InsertFde(const DwarfFde* fde) {
uint64_t start = fde->pc_start;
uint64_t end = fde->pc_end;
auto it = fdes_.upper_bound(start);
@@ -654,9 +654,10 @@
}
template <typename AddressType>
-bool DwarfSectionImplNoHdr<AddressType>::GetNextCieOrFde(DwarfFde** fde_entry) {
+bool DwarfSectionImpl<AddressType>::GetNextCieOrFde(const DwarfFde** fde_entry) {
uint64_t start_offset = next_entries_offset_;
+ memory_.set_data_offset(entries_offset_);
memory_.set_cur_offset(next_entries_offset_);
uint32_t value32;
if (!memory_.ReadBytes(&value32, sizeof(value32))) {
@@ -689,7 +690,7 @@
entry_is_cie = true;
cie_fde_encoding = DW_EH_PE_sdata8;
} else {
- cie_offset = this->GetCieOffsetFromFde64(value64);
+ cie_offset = GetCieOffsetFromFde64(value64);
}
} else {
next_entries_offset_ = memory_.cur_offset() + value32;
@@ -705,37 +706,45 @@
entry_is_cie = true;
cie_fde_encoding = DW_EH_PE_sdata4;
} else {
- cie_offset = this->GetCieOffsetFromFde32(value32);
+ cie_offset = GetCieOffsetFromFde32(value32);
}
}
if (entry_is_cie) {
- DwarfCie* cie = &cie_entries_[start_offset];
- cie->lsda_encoding = DW_EH_PE_omit;
- cie->cfa_instructions_end = next_entries_offset_;
- cie->fde_address_encoding = cie_fde_encoding;
+ auto entry = cie_entries_.find(start_offset);
+ if (entry == cie_entries_.end()) {
+ DwarfCie* cie = &cie_entries_[start_offset];
+ cie->lsda_encoding = DW_EH_PE_omit;
+ cie->cfa_instructions_end = next_entries_offset_;
+ cie->fde_address_encoding = cie_fde_encoding;
- if (!this->FillInCie(cie)) {
- cie_entries_.erase(start_offset);
- return false;
+ if (!FillInCie(cie)) {
+ cie_entries_.erase(start_offset);
+ return false;
+ }
}
*fde_entry = nullptr;
} else {
- DwarfFde* fde = &fde_entries_[start_offset];
- fde->cfa_instructions_end = next_entries_offset_;
- fde->cie_offset = cie_offset;
+ auto entry = fde_entries_.find(start_offset);
+ if (entry != fde_entries_.end()) {
+ *fde_entry = &entry->second;
+ } else {
+ DwarfFde* fde = &fde_entries_[start_offset];
+ fde->cfa_instructions_end = next_entries_offset_;
+ fde->cie_offset = cie_offset;
- if (!this->FillInFde(fde)) {
- fde_entries_.erase(start_offset);
- return false;
+ if (!FillInFde(fde)) {
+ fde_entries_.erase(start_offset);
+ return false;
+ }
+ *fde_entry = fde;
}
- *fde_entry = fde;
}
return true;
}
template <typename AddressType>
-void DwarfSectionImplNoHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
+void DwarfSectionImpl<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
// Loop through the already cached entries.
uint64_t entry_offset = entries_offset_;
while (entry_offset < next_entries_offset_) {
@@ -754,7 +763,7 @@
}
while (next_entries_offset_ < entries_end_) {
- DwarfFde* fde;
+ const DwarfFde* fde;
if (!GetNextCieOrFde(&fde)) {
break;
}
@@ -771,7 +780,7 @@
}
template <typename AddressType>
-const DwarfFde* DwarfSectionImplNoHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
+const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromPc(uint64_t pc) {
// Search in the list of fdes we already have.
auto it = fdes_.upper_bound(pc);
if (it != fdes_.end()) {
@@ -784,7 +793,7 @@
// to do a linear search of the fdes by pc. As fdes are read, a cached
// search map is created.
while (next_entries_offset_ < entries_end_) {
- DwarfFde* fde;
+ const DwarfFde* fde;
if (!GetNextCieOrFde(&fde)) {
return nullptr;
}
@@ -807,10 +816,6 @@
template class DwarfSectionImpl<uint32_t>;
template class DwarfSectionImpl<uint64_t>;
-// Explicitly instantiate DwarfSectionImplNoHdr
-template class DwarfSectionImplNoHdr<uint32_t>;
-template class DwarfSectionImplNoHdr<uint64_t>;
-
// Explicitly instantiate DwarfDebugFrame
template class DwarfDebugFrame<uint32_t>;
template class DwarfDebugFrame<uint64_t>;
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index e863f22..5f95fa8 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -126,8 +126,10 @@
template <typename AddressType>
void ElfInterface::InitHeadersWithTemplate() {
if (eh_frame_hdr_offset_ != 0) {
- eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
- if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, eh_frame_hdr_section_bias_)) {
+ DwarfEhFrameWithHdr<AddressType>* eh_frame_hdr = new DwarfEhFrameWithHdr<AddressType>(memory_);
+ eh_frame_.reset(eh_frame_hdr);
+ if (!eh_frame_hdr->EhFrameInit(eh_frame_offset_, eh_frame_size_, eh_frame_section_bias_) ||
+ !eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, eh_frame_hdr_section_bias_)) {
eh_frame_.reset(nullptr);
}
}
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index 0b3f6d4..c244749 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -125,10 +125,16 @@
DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
virtual ~DwarfSectionImpl() = default;
+ bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
+
const DwarfCie* GetCieFromOffset(uint64_t offset);
const DwarfFde* GetFdeFromOffset(uint64_t offset);
+ const DwarfFde* GetFdeFromPc(uint64_t pc) override;
+
+ void GetFdes(std::vector<const DwarfFde*>* fdes) override;
+
bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info);
bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
@@ -139,6 +145,8 @@
bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) override;
protected:
+ bool GetNextCieOrFde(const DwarfFde** fde_entry);
+
bool FillInCieHeader(DwarfCie* cie);
bool FillInCie(DwarfCie* cie);
@@ -150,43 +158,13 @@
bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
+ void InsertFde(const DwarfFde* fde);
+
int64_t section_bias_ = 0;
uint64_t entries_offset_ = 0;
uint64_t entries_end_ = 0;
- uint64_t pc_offset_ = 0;
-};
-
-template <typename AddressType>
-class DwarfSectionImplNoHdr : 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>::pc_offset_;
- using DwarfSectionImpl<AddressType>::entries_offset_;
- using DwarfSectionImpl<AddressType>::entries_end_;
- using DwarfSectionImpl<AddressType>::last_error_;
- using DwarfSectionImpl<AddressType>::section_bias_;
- using DwarfSectionImpl<AddressType>::cie_entries_;
- using DwarfSectionImpl<AddressType>::fde_entries_;
- using DwarfSectionImpl<AddressType>::cie32_value_;
- using DwarfSectionImpl<AddressType>::cie64_value_;
-
- DwarfSectionImplNoHdr(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
- virtual ~DwarfSectionImplNoHdr() = default;
-
- bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
-
- const DwarfFde* GetFdeFromPc(uint64_t pc) override;
-
- void GetFdes(std::vector<const DwarfFde*>* fdes) override;
-
- protected:
- bool GetNextCieOrFde(DwarfFde** fde_entry);
-
- void InsertFde(const DwarfFde* fde);
-
uint64_t next_entries_offset_ = 0;
+ uint64_t pc_offset_ = 0;
std::map<uint64_t, std::pair<uint64_t, const DwarfFde*>> fdes_;
};
diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
index 78608e3..768a808 100644
--- a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
@@ -36,10 +36,8 @@
~TestDwarfEhFrameWithHdr() = default;
void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; }
- void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; }
- void TestSetEntriesEnd(uint64_t end) { this->entries_end_ = end; }
- void TestSetEntriesDataOffset(uint64_t offset) { this->entries_data_offset_ = offset; }
- void TestSetCurEntriesOffset(uint64_t offset) { this->cur_entries_offset_ = offset; }
+ void TestSetHdrEntriesOffset(uint64_t offset) { this->hdr_entries_offset_ = offset; }
+ void TestSetHdrEntriesDataOffset(uint64_t offset) { this->hdr_entries_data_offset_ = offset; }
void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; }
void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
@@ -48,15 +46,11 @@
}
uint8_t TestGetVersion() { return this->version_; }
- uint8_t TestGetPtrEncoding() { return this->ptr_encoding_; }
- uint64_t TestGetPtrOffset() { return this->ptr_offset_; }
uint8_t TestGetTableEncoding() { return this->table_encoding_; }
uint64_t TestGetTableEntrySize() { return this->table_entry_size_; }
uint64_t TestGetFdeCount() { return this->fde_count_; }
- uint64_t TestGetEntriesOffset() { return this->entries_offset_; }
- uint64_t TestGetEntriesEnd() { return this->entries_end_; }
- uint64_t TestGetEntriesDataOffset() { return this->entries_data_offset_; }
- uint64_t TestGetCurEntriesOffset() { return this->cur_entries_offset_; }
+ uint64_t TestGetHdrEntriesOffset() { return this->hdr_entries_offset_; }
+ uint64_t TestGetHdrEntriesDataOffset() { return this->hdr_entries_data_offset_; }
};
template <typename TypeParam>
@@ -85,15 +79,11 @@
ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
- EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding());
EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding());
EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount());
- EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset());
- EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset());
- EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd());
- EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset());
- EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset());
+ EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
+ EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
// Verify a zero table entry size fails to init.
this->memory_.SetData8(0x1003, 0x1);
@@ -137,17 +127,14 @@
this->memory_.SetData32(0x140c, 0x200);
this->memory_.SetData16(0x1410, 0);
+ ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x200, 0x2000));
ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000));
EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
- EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding());
EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding());
EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount());
- EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset());
- EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset());
- EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd());
- EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset());
- EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset());
+ EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
+ EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
ASSERT_TRUE(fde != nullptr);
@@ -155,6 +142,115 @@
EXPECT_EQ(0x4700U, fde->pc_end);
}
+TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias_different_from_eh_frame_bias) {
+ this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
+ DW_EH_PE_pcrel | DW_EH_PE_sdata4});
+ this->memory_.SetData16(0x1004, 0x500);
+ this->memory_.SetData32(0x1006, 1);
+ this->memory_.SetData32(0x100a, 0x2500);
+ this->memory_.SetData32(0x100e, 0x1400);
+
+ // CIE 32 information.
+ this->memory_.SetData32(0x1300, 0xfc);
+ this->memory_.SetData32(0x1304, 0);
+ this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
+
+ // FDE 32 information.
+ this->memory_.SetData32(0x1400, 0xfc);
+ this->memory_.SetData32(0x1404, 0x104);
+ this->memory_.SetData32(0x1408, 0x20f8);
+ this->memory_.SetData32(0x140c, 0x200);
+ this->memory_.SetData16(0x1410, 0);
+
+ ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x200, 0x1000));
+ ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000));
+ EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
+ EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding());
+ EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
+ EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount());
+ EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
+ EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
+
+ const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
+ ASSERT_TRUE(fde != nullptr);
+ EXPECT_EQ(0x4500U, fde->pc_start);
+ EXPECT_EQ(0x4700U, fde->pc_end);
+}
+
+TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_wtih_empty_fde) {
+ this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
+ DW_EH_PE_pcrel | DW_EH_PE_sdata4});
+ this->memory_.SetData16(0x1004, 0x500);
+ this->memory_.SetData32(0x1006, 1);
+ this->memory_.SetData32(0x100a, 0x2500);
+ this->memory_.SetData32(0x100e, 0x1400);
+
+ // CIE 32 information.
+ this->memory_.SetData32(0x1300, 0xfc);
+ this->memory_.SetData32(0x1304, 0);
+ this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
+
+ // FDE 32 information.
+ this->memory_.SetData32(0x1400, 0xfc);
+ this->memory_.SetData32(0x1404, 0x104);
+ this->memory_.SetData32(0x1408, 0x30f8);
+ this->memory_.SetData32(0x140c, 0);
+ this->memory_.SetData16(0x1410, 0);
+
+ // FDE 32 information.
+ this->memory_.SetData32(0x1500, 0xfc);
+ this->memory_.SetData32(0x1504, 0x204);
+ this->memory_.SetData32(0x1508, 0x2ff8);
+ this->memory_.SetData32(0x150c, 0x200);
+ this->memory_.SetData16(0x1510, 0);
+
+ ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x300, 0));
+ ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
+
+ const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
+ ASSERT_TRUE(fde != nullptr);
+ EXPECT_EQ(0x4500U, fde->pc_start);
+ EXPECT_EQ(0x4700U, fde->pc_end);
+}
+
+TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes_with_empty_fde) {
+ this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
+ DW_EH_PE_pcrel | DW_EH_PE_sdata4});
+ this->memory_.SetData16(0x1004, 0x500);
+ this->memory_.SetData32(0x1006, 1);
+ this->memory_.SetData32(0x100a, 0x2500);
+ this->memory_.SetData32(0x100e, 0x1400);
+
+ // CIE 32 information.
+ this->memory_.SetData32(0x1300, 0xfc);
+ this->memory_.SetData32(0x1304, 0);
+ this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
+
+ // FDE 32 information.
+ this->memory_.SetData32(0x1400, 0xfc);
+ this->memory_.SetData32(0x1404, 0x104);
+ this->memory_.SetData32(0x1408, 0x30f8);
+ this->memory_.SetData32(0x140c, 0);
+ this->memory_.SetData16(0x1410, 0);
+
+ // FDE 32 information.
+ this->memory_.SetData32(0x1500, 0xfc);
+ this->memory_.SetData32(0x1504, 0x204);
+ this->memory_.SetData32(0x1508, 0x2ff8);
+ this->memory_.SetData32(0x150c, 0x200);
+ this->memory_.SetData16(0x1510, 0);
+
+ ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x300, 0));
+ ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
+
+ std::vector<const DwarfFde*> fdes;
+ this->eh_frame_->GetFdes(&fdes);
+ ASSERT_FALSE(fdes.empty());
+ ASSERT_EQ(1U, fdes.size());
+ EXPECT_EQ(0x4500U, fdes[0]->pc_start);
+ EXPECT_EQ(0x4700U, fdes[0]->pc_end);
+}
+
TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes) {
this->memory_.SetMemory(
0x1000, std::vector<uint8_t>{1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4});
@@ -220,7 +316,7 @@
TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
this->eh_frame_->TestSetTableEntrySize(0x10);
this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
- this->eh_frame_->TestSetEntriesOffset(0x1000);
+ this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode());
@@ -233,8 +329,8 @@
// We are assuming that pc rel, is really relative to the load_bias.
TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) {
this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4);
- this->eh_frame_->TestSetEntriesOffset(0x1000);
- this->eh_frame_->TestSetEntriesDataOffset(0x3000);
+ this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
+ this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000);
this->eh_frame_->TestSetTableEntrySize(0x10);
this->memory_.SetData32(0x1040, 0x340);
@@ -248,8 +344,8 @@
TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) {
this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4);
- this->eh_frame_->TestSetEntriesOffset(0x1000);
- this->eh_frame_->TestSetEntriesDataOffset(0x3000);
+ this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
+ this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000);
this->eh_frame_->TestSetTableEntrySize(0x10);
this->memory_.SetData32(0x1040, 0x340);
@@ -263,7 +359,7 @@
TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_cached) {
this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
- this->eh_frame_->TestSetEntriesOffset(0x1000);
+ this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
this->eh_frame_->TestSetTableEntrySize(0x10);
this->memory_.SetData32(0x1040, 0x340);
@@ -446,7 +542,9 @@
ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
}
-REGISTER_TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, GetFdes,
+REGISTER_TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias,
+ Init_non_zero_load_bias_different_from_eh_frame_bias,
+ GetFdeFromPc_wtih_empty_fde, GetFdes_with_empty_fde, GetFdes,
GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel,
GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached,
GetFdeOffsetFromPc_verify, GetFdeOffsetFromPc_index_fail,