Merge "Refactor the DwarfSection classes."
am: f9b879fd05
Change-Id: I9b8bac71b3e85a7b49fe207a12fac55e0ee76c1c
This commit is contained in:
commit
26128c09b5
12 changed files with 1473 additions and 2050 deletions
|
|
@ -26,9 +26,9 @@
|
|||
namespace unwindstack {
|
||||
|
||||
template <typename AddressType>
|
||||
class DwarfDebugFrame : public DwarfSectionImpl<AddressType> {
|
||||
class DwarfDebugFrame : public DwarfSectionImplNoHdr<AddressType> {
|
||||
public:
|
||||
DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {
|
||||
DwarfDebugFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {
|
||||
this->cie32_value_ = static_cast<uint32_t>(-1);
|
||||
this->cie64_value_ = static_cast<uint64_t>(-1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@
|
|||
namespace unwindstack {
|
||||
|
||||
template <typename AddressType>
|
||||
class DwarfEhFrame : public DwarfSectionImpl<AddressType> {
|
||||
class DwarfEhFrame : public DwarfSectionImplNoHdr<AddressType> {
|
||||
public:
|
||||
DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
|
||||
DwarfEhFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {}
|
||||
virtual ~DwarfEhFrame() = default;
|
||||
|
||||
uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint
|
|||
memory_.clear_text_offset();
|
||||
memory_.set_data_offset(offset);
|
||||
memory_.set_cur_offset(offset);
|
||||
pc_offset_ = offset;
|
||||
|
||||
// Read the first four bytes all at once.
|
||||
uint8_t data[4];
|
||||
|
|
@ -88,12 +89,22 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint
|
|||
}
|
||||
|
||||
template <typename AddressType>
|
||||
const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromIndex(size_t index) {
|
||||
const FdeInfo* info = GetFdeInfoFromIndex(index);
|
||||
if (info == nullptr) {
|
||||
const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
|
||||
uint64_t fde_offset;
|
||||
if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->GetFdeFromOffset(info->offset);
|
||||
const DwarfFde* fde = this->GetFdeFromOffset(fde_offset);
|
||||
if (fde == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Guaranteed pc >= pc_start, need to check pc in the fde range.
|
||||
if (pc < fde->pc_end) {
|
||||
return fde;
|
||||
}
|
||||
last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
|
|
@ -241,6 +252,21 @@ bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t*
|
|||
}
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
void DwarfEhFrameWithHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
|
||||
for (size_t i = 0; i < fde_count_; i++) {
|
||||
const FdeInfo* info = GetFdeInfoFromIndex(i);
|
||||
if (info == nullptr) {
|
||||
break;
|
||||
}
|
||||
const DwarfFde* fde = this->GetFdeFromOffset(info->offset);
|
||||
if (fde == nullptr) {
|
||||
break;
|
||||
}
|
||||
fdes->push_back(fde);
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly instantiate DwarfEhFrameWithHdr
|
||||
template class DwarfEhFrameWithHdr<uint32_t>;
|
||||
template class DwarfEhFrameWithHdr<uint64_t>;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "DwarfEhFrame.h"
|
||||
#include <unwindstack/DwarfSection.h>
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
|
|
@ -29,12 +29,12 @@ namespace unwindstack {
|
|||
class Memory;
|
||||
|
||||
template <typename AddressType>
|
||||
class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
|
||||
class DwarfEhFrameWithHdr : 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>::pc_offset_;
|
||||
using DwarfSectionImpl<AddressType>::entries_offset_;
|
||||
using DwarfSectionImpl<AddressType>::entries_end_;
|
||||
using DwarfSectionImpl<AddressType>::last_error_;
|
||||
|
|
@ -45,14 +45,27 @@ class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
|
|||
uint64_t offset;
|
||||
};
|
||||
|
||||
DwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrame<AddressType>(memory) {}
|
||||
DwarfEhFrameWithHdr(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
|
||||
virtual ~DwarfEhFrameWithHdr() = default;
|
||||
|
||||
uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
|
||||
return this->memory_.cur_offset() - pointer - 4;
|
||||
}
|
||||
|
||||
uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
|
||||
return this->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;
|
||||
}
|
||||
|
||||
bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
|
||||
|
||||
bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override;
|
||||
const DwarfFde* GetFdeFromPc(uint64_t pc) override;
|
||||
|
||||
const DwarfFde* GetFdeFromIndex(size_t index) override;
|
||||
bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset);
|
||||
|
||||
const FdeInfo* GetFdeInfoFromIndex(size_t index);
|
||||
|
||||
|
|
@ -60,6 +73,8 @@ class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
|
|||
|
||||
bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries);
|
||||
|
||||
void GetFdes(std::vector<const DwarfFde*>* fdes) override;
|
||||
|
||||
protected:
|
||||
uint8_t version_;
|
||||
uint8_t ptr_encoding_;
|
||||
|
|
@ -71,6 +86,7 @@ class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
|
|||
uint64_t entries_data_offset_;
|
||||
uint64_t cur_entries_offset_ = 0;
|
||||
|
||||
uint64_t fde_count_;
|
||||
std::unordered_map<uint64_t, FdeInfo> fde_info_;
|
||||
};
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -43,7 +43,12 @@ class DwarfSection {
|
|||
|
||||
class iterator : public std::iterator<std::bidirectional_iterator_tag, DwarfFde*> {
|
||||
public:
|
||||
iterator(DwarfSection* section, size_t index) : section_(section), index_(index) {}
|
||||
iterator(DwarfSection* section, size_t index) : index_(index) {
|
||||
section->GetFdes(&fdes_);
|
||||
if (index_ == static_cast<size_t>(-1)) {
|
||||
index_ = fdes_.size();
|
||||
}
|
||||
}
|
||||
|
||||
iterator& operator++() {
|
||||
index_++;
|
||||
|
|
@ -65,15 +70,18 @@ class DwarfSection {
|
|||
bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
|
||||
bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
|
||||
|
||||
const DwarfFde* operator*() { return section_->GetFdeFromIndex(index_); }
|
||||
const DwarfFde* operator*() {
|
||||
if (index_ > fdes_.size()) return nullptr;
|
||||
return fdes_[index_];
|
||||
}
|
||||
|
||||
private:
|
||||
DwarfSection* section_ = nullptr;
|
||||
std::vector<const DwarfFde*> fdes_;
|
||||
size_t index_ = 0;
|
||||
};
|
||||
|
||||
iterator begin() { return iterator(this, 0); }
|
||||
iterator end() { return iterator(this, fde_count_); }
|
||||
iterator end() { return iterator(this, static_cast<size_t>(-1)); }
|
||||
|
||||
DwarfErrorCode LastErrorCode() { return last_error_.code; }
|
||||
uint64_t LastErrorAddress() { return last_error_.address; }
|
||||
|
|
@ -82,15 +90,11 @@ class DwarfSection {
|
|||
|
||||
virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
|
||||
|
||||
virtual bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) = 0;
|
||||
|
||||
virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) = 0;
|
||||
|
||||
virtual const DwarfFde* GetFdeFromIndex(size_t index) = 0;
|
||||
virtual void GetFdes(std::vector<const DwarfFde*>* fdes) = 0;
|
||||
|
||||
const DwarfFde* GetFdeFromPc(uint64_t pc);
|
||||
|
||||
virtual const DwarfFde* GetFdeFromOffset(uint64_t fde_offset) = 0;
|
||||
virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0;
|
||||
|
||||
virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) = 0;
|
||||
|
||||
|
|
@ -109,7 +113,6 @@ class DwarfSection {
|
|||
uint32_t cie32_value_ = 0;
|
||||
uint64_t cie64_value_ = 0;
|
||||
|
||||
uint64_t fde_count_ = 0;
|
||||
std::unordered_map<uint64_t, DwarfFde> fde_entries_;
|
||||
std::unordered_map<uint64_t, DwarfCie> cie_entries_;
|
||||
std::unordered_map<uint64_t, dwarf_loc_regs_t> cie_loc_regs_;
|
||||
|
|
@ -119,55 +122,73 @@ class DwarfSection {
|
|||
template <typename AddressType>
|
||||
class DwarfSectionImpl : public DwarfSection {
|
||||
public:
|
||||
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;
|
||||
};
|
||||
|
||||
DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
|
||||
virtual ~DwarfSectionImpl() = default;
|
||||
|
||||
bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
|
||||
const DwarfCie* GetCieFromOffset(uint64_t offset);
|
||||
|
||||
bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override;
|
||||
|
||||
const DwarfFde* GetFdeFromIndex(size_t index) override;
|
||||
const DwarfFde* GetFdeFromOffset(uint64_t offset);
|
||||
|
||||
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,
|
||||
Regs* regs, bool* finished) override;
|
||||
|
||||
const DwarfCie* GetCie(uint64_t offset);
|
||||
bool FillInCie(DwarfCie* cie);
|
||||
|
||||
const DwarfFde* GetFdeFromOffset(uint64_t offset) override;
|
||||
bool FillInFde(DwarfFde* fde);
|
||||
|
||||
bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) override;
|
||||
|
||||
bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) override;
|
||||
|
||||
protected:
|
||||
bool FillInCieHeader(DwarfCie* cie);
|
||||
|
||||
bool FillInCie(DwarfCie* cie);
|
||||
|
||||
bool FillInFdeHeader(DwarfFde* fde);
|
||||
|
||||
bool FillInFde(DwarfFde* fde);
|
||||
|
||||
bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
|
||||
RegsInfo<AddressType>* regs_info, bool* is_dex_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();
|
||||
|
||||
uint64_t load_bias_ = 0;
|
||||
uint64_t entries_offset_ = 0;
|
||||
uint64_t entries_end_ = 0;
|
||||
uint64_t pc_offset_ = 0;
|
||||
};
|
||||
|
||||
std::vector<FdeInfo> fdes_;
|
||||
uint64_t entries_offset_;
|
||||
uint64_t entries_end_;
|
||||
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>::load_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, uint64_t load_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;
|
||||
|
||||
std::map<uint64_t, std::pair<uint64_t, const DwarfFde*>> fdes_;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/DwarfError.h>
|
||||
|
|
@ -29,51 +28,33 @@
|
|||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class MockDwarfEhFrame : public DwarfEhFrame<TypeParam> {
|
||||
public:
|
||||
MockDwarfEhFrame(Memory* memory) : DwarfEhFrame<TypeParam>(memory) {}
|
||||
~MockDwarfEhFrame() = default;
|
||||
|
||||
void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
|
||||
void TestSetOffset(uint64_t offset) { this->entries_offset_ = offset; }
|
||||
void TestSetEndOffset(uint64_t offset) { this->entries_end_ = offset; }
|
||||
void TestPushFdeInfo(const typename DwarfEhFrame<TypeParam>::FdeInfo& info) {
|
||||
this->fdes_.push_back(info);
|
||||
}
|
||||
|
||||
uint64_t TestGetFdeCount() { return this->fde_count_; }
|
||||
uint8_t TestGetOffset() { return this->offset_; }
|
||||
uint8_t TestGetEndOffset() { return this->end_offset_; }
|
||||
void TestGetFdeInfo(size_t index, typename DwarfEhFrame<TypeParam>::FdeInfo* info) {
|
||||
*info = this->fdes_[index];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TypeParam>
|
||||
class DwarfEhFrameTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
memory_.Clear();
|
||||
eh_frame_ = new MockDwarfEhFrame<TypeParam>(&memory_);
|
||||
eh_frame_ = new DwarfEhFrame<TypeParam>(&memory_);
|
||||
ResetLogs();
|
||||
}
|
||||
|
||||
void TearDown() override { delete eh_frame_; }
|
||||
|
||||
MemoryFake memory_;
|
||||
MockDwarfEhFrame<TypeParam>* eh_frame_ = nullptr;
|
||||
DwarfEhFrame<TypeParam>* eh_frame_ = nullptr;
|
||||
};
|
||||
TYPED_TEST_CASE_P(DwarfEhFrameTest);
|
||||
|
||||
// NOTE: All test class variables need to be referenced as this->.
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, Init32) {
|
||||
// Only verify different cie/fde format. All other DwarfSection corner
|
||||
// cases are tested in DwarfDebugFrameTest.cpp.
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, GetFdeCieFromOffset32) {
|
||||
// CIE 32 information.
|
||||
this->memory_.SetData32(0x5000, 0xfc);
|
||||
// Indicates this is a cie for eh_frame.
|
||||
this->memory_.SetData32(0x5004, 0);
|
||||
this->memory_.SetData8(0x5008, 1);
|
||||
this->memory_.SetData8(0x5009, '\0');
|
||||
this->memory_.SetMemory(0x5008, std::vector<uint8_t>{1, '\0', 16, 32, 1});
|
||||
|
||||
// FDE 32 information.
|
||||
this->memory_.SetData32(0x5100, 0xfc);
|
||||
|
|
@ -81,415 +62,70 @@ TYPED_TEST_P(DwarfEhFrameTest, Init32) {
|
|||
this->memory_.SetData32(0x5108, 0x1500);
|
||||
this->memory_.SetData32(0x510c, 0x200);
|
||||
|
||||
this->memory_.SetData32(0x5200, 0xfc);
|
||||
this->memory_.SetData32(0x5204, 0x204);
|
||||
this->memory_.SetData32(0x5208, 0x2500);
|
||||
this->memory_.SetData32(0x520c, 0x300);
|
||||
const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x5100);
|
||||
ASSERT_TRUE(fde != nullptr);
|
||||
EXPECT_EQ(0x5000U, fde->cie_offset);
|
||||
EXPECT_EQ(0x5110U, fde->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x5200U, fde->cfa_instructions_end);
|
||||
EXPECT_EQ(0x6608U, fde->pc_start);
|
||||
EXPECT_EQ(0x6808U, fde->pc_end);
|
||||
EXPECT_EQ(0U, fde->lsda_address);
|
||||
|
||||
// CIE 32 information.
|
||||
this->memory_.SetData32(0x5300, 0xfc);
|
||||
this->memory_.SetData32(0x5304, 0);
|
||||
this->memory_.SetData8(0x5308, 1);
|
||||
this->memory_.SetData8(0x5309, '\0');
|
||||
|
||||
// FDE 32 information.
|
||||
this->memory_.SetData32(0x5400, 0xfc);
|
||||
this->memory_.SetData32(0x5404, 0x104);
|
||||
this->memory_.SetData32(0x5408, 0x3500);
|
||||
this->memory_.SetData32(0x540c, 0x400);
|
||||
|
||||
this->memory_.SetData32(0x5500, 0xfc);
|
||||
this->memory_.SetData32(0x5504, 0x204);
|
||||
this->memory_.SetData32(0x5508, 0x4500);
|
||||
this->memory_.SetData32(0x550c, 0x500);
|
||||
|
||||
ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600, 0));
|
||||
ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
|
||||
|
||||
typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
|
||||
|
||||
this->eh_frame_->TestGetFdeInfo(0, &info);
|
||||
EXPECT_EQ(0x5100U, info.offset);
|
||||
EXPECT_EQ(0x6608U, info.start);
|
||||
EXPECT_EQ(0x6808U, info.end);
|
||||
|
||||
this->eh_frame_->TestGetFdeInfo(1, &info);
|
||||
EXPECT_EQ(0x5200U, info.offset);
|
||||
EXPECT_EQ(0x7708U, info.start);
|
||||
EXPECT_EQ(0x7a08U, info.end);
|
||||
|
||||
this->eh_frame_->TestGetFdeInfo(2, &info);
|
||||
EXPECT_EQ(0x5400U, info.offset);
|
||||
EXPECT_EQ(0x8908U, info.start);
|
||||
EXPECT_EQ(0x8d08U, info.end);
|
||||
|
||||
this->eh_frame_->TestGetFdeInfo(3, &info);
|
||||
EXPECT_EQ(0x5500U, info.offset);
|
||||
EXPECT_EQ(0x9a08U, info.start);
|
||||
EXPECT_EQ(0x9f08U, info.end);
|
||||
const DwarfCie* cie = fde->cie;
|
||||
ASSERT_TRUE(cie != nullptr);
|
||||
EXPECT_EQ(1U, cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
|
||||
EXPECT_EQ(0U, cie->segment_size);
|
||||
EXPECT_EQ('\0', cie->augmentation_string[0]);
|
||||
EXPECT_EQ(0U, cie->personality_handler);
|
||||
EXPECT_EQ(0x500dU, cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x5100U, cie->cfa_instructions_end);
|
||||
EXPECT_EQ(16U, cie->code_alignment_factor);
|
||||
EXPECT_EQ(32U, cie->data_alignment_factor);
|
||||
EXPECT_EQ(1U, cie->return_address_register);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, Init32_fde_not_following_cie) {
|
||||
// CIE 32 information.
|
||||
this->memory_.SetData32(0x5000, 0xfc);
|
||||
this->memory_.SetData32(0x5004, 0);
|
||||
this->memory_.SetData8(0x5008, 1);
|
||||
this->memory_.SetData8(0x5009, '\0');
|
||||
|
||||
// FDE 32 information.
|
||||
this->memory_.SetData32(0x5100, 0xfc);
|
||||
this->memory_.SetData32(0x5104, 0x1000);
|
||||
this->memory_.SetData32(0x5108, 0x1500);
|
||||
this->memory_.SetData32(0x510c, 0x200);
|
||||
|
||||
ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600, 0));
|
||||
ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, Init64) {
|
||||
TYPED_TEST_P(DwarfEhFrameTest, GetFdeCieFromOffset64) {
|
||||
// CIE 64 information.
|
||||
this->memory_.SetData32(0x5000, 0xffffffff);
|
||||
this->memory_.SetData64(0x5004, 0xf4);
|
||||
this->memory_.SetData64(0x5004, 0xfc);
|
||||
// Indicates this is a cie for eh_frame.
|
||||
this->memory_.SetData64(0x500c, 0);
|
||||
this->memory_.SetData8(0x5014, 1);
|
||||
this->memory_.SetData8(0x5015, '\0');
|
||||
this->memory_.SetMemory(0x5014, std::vector<uint8_t>{1, '\0', 16, 32, 1});
|
||||
|
||||
// FDE 64 information.
|
||||
this->memory_.SetData32(0x5100, 0xffffffff);
|
||||
this->memory_.SetData64(0x5104, 0xf4);
|
||||
this->memory_.SetData64(0x5104, 0xfc);
|
||||
this->memory_.SetData64(0x510c, 0x10c);
|
||||
this->memory_.SetData64(0x5114, 0x1500);
|
||||
this->memory_.SetData64(0x511c, 0x200);
|
||||
|
||||
this->memory_.SetData32(0x5200, 0xffffffff);
|
||||
this->memory_.SetData64(0x5204, 0xf4);
|
||||
this->memory_.SetData64(0x520c, 0x20c);
|
||||
this->memory_.SetData64(0x5214, 0x2500);
|
||||
this->memory_.SetData64(0x521c, 0x300);
|
||||
|
||||
// CIE 64 information.
|
||||
this->memory_.SetData32(0x5300, 0xffffffff);
|
||||
this->memory_.SetData64(0x5304, 0xf4);
|
||||
this->memory_.SetData64(0x530c, 0);
|
||||
this->memory_.SetData8(0x5314, 1);
|
||||
this->memory_.SetData8(0x5315, '\0');
|
||||
|
||||
// FDE 64 information.
|
||||
this->memory_.SetData32(0x5400, 0xffffffff);
|
||||
this->memory_.SetData64(0x5404, 0xf4);
|
||||
this->memory_.SetData64(0x540c, 0x10c);
|
||||
this->memory_.SetData64(0x5414, 0x3500);
|
||||
this->memory_.SetData64(0x541c, 0x400);
|
||||
|
||||
this->memory_.SetData32(0x5500, 0xffffffff);
|
||||
this->memory_.SetData64(0x5504, 0xf4);
|
||||
this->memory_.SetData64(0x550c, 0x20c);
|
||||
this->memory_.SetData64(0x5514, 0x4500);
|
||||
this->memory_.SetData64(0x551c, 0x500);
|
||||
|
||||
ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600, 0));
|
||||
ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
|
||||
|
||||
typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
|
||||
|
||||
this->eh_frame_->TestGetFdeInfo(0, &info);
|
||||
EXPECT_EQ(0x5100U, info.offset);
|
||||
EXPECT_EQ(0x6618U, info.start);
|
||||
EXPECT_EQ(0x6818U, info.end);
|
||||
|
||||
this->eh_frame_->TestGetFdeInfo(1, &info);
|
||||
EXPECT_EQ(0x5200U, info.offset);
|
||||
EXPECT_EQ(0x7718U, info.start);
|
||||
EXPECT_EQ(0x7a18U, info.end);
|
||||
|
||||
this->eh_frame_->TestGetFdeInfo(2, &info);
|
||||
EXPECT_EQ(0x5400U, info.offset);
|
||||
EXPECT_EQ(0x8918U, info.start);
|
||||
EXPECT_EQ(0x8d18U, info.end);
|
||||
|
||||
this->eh_frame_->TestGetFdeInfo(3, &info);
|
||||
EXPECT_EQ(0x5500U, info.offset);
|
||||
EXPECT_EQ(0x9a18U, info.start);
|
||||
EXPECT_EQ(0x9f18U, info.end);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, Init64_fde_not_following_cie) {
|
||||
// CIE 64 information.
|
||||
this->memory_.SetData32(0x5000, 0xffffffff);
|
||||
this->memory_.SetData64(0x5004, 0xf4);
|
||||
this->memory_.SetData64(0x500c, 0);
|
||||
this->memory_.SetData8(0x5014, 1);
|
||||
this->memory_.SetData8(0x5015, '\0');
|
||||
|
||||
// FDE 64 information.
|
||||
this->memory_.SetData32(0x5100, 0xffffffff);
|
||||
this->memory_.SetData64(0x5104, 0xf4);
|
||||
this->memory_.SetData64(0x510c, 0x1000);
|
||||
this->memory_.SetData64(0x5114, 0x1500);
|
||||
this->memory_.SetData64(0x511c, 0x200);
|
||||
|
||||
ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600, 0));
|
||||
ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, Init_non_zero_load_bias) {
|
||||
// CIE 32 information.
|
||||
this->memory_.SetData32(0x5000, 0xfc);
|
||||
this->memory_.SetData32(0x5004, 0);
|
||||
this->memory_.SetData8(0x5008, 1);
|
||||
this->memory_.SetData8(0x5009, 'z');
|
||||
this->memory_.SetData8(0x500a, 'R');
|
||||
this->memory_.SetData8(0x500b, '\0');
|
||||
this->memory_.SetData8(0x500c, 0);
|
||||
this->memory_.SetData8(0x500d, 0);
|
||||
this->memory_.SetData8(0x500e, 0);
|
||||
this->memory_.SetData8(0x500f, 0);
|
||||
this->memory_.SetData8(0x5010, 0x1b);
|
||||
|
||||
// FDE 32 information.
|
||||
this->memory_.SetData32(0x5100, 0xfc);
|
||||
this->memory_.SetData32(0x5104, 0x104);
|
||||
this->memory_.SetData32(0x5108, 0x1500);
|
||||
this->memory_.SetData32(0x510c, 0x200);
|
||||
this->memory_.SetData8(0x5110, 0);
|
||||
this->memory_.SetData8(0x5111, 0);
|
||||
|
||||
ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200, 0x2000));
|
||||
ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
|
||||
|
||||
typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
|
||||
|
||||
this->eh_frame_->TestGetFdeInfo(0, &info);
|
||||
EXPECT_EQ(0x5100U, info.offset);
|
||||
EXPECT_EQ(0x8608U, info.start);
|
||||
EXPECT_EQ(0x8808U, info.end);
|
||||
|
||||
const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x8700);
|
||||
const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x5100);
|
||||
ASSERT_TRUE(fde != nullptr);
|
||||
EXPECT_EQ(0x8608U, fde->pc_start);
|
||||
EXPECT_EQ(0x8808U, fde->pc_end);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, Init_version1) {
|
||||
// CIE 32 information.
|
||||
this->memory_.SetData32(0x5000, 0xfc);
|
||||
this->memory_.SetData32(0x5004, 0);
|
||||
this->memory_.SetData8(0x5008, 1);
|
||||
// Augment string.
|
||||
this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'R', 'P', 'L', '\0'});
|
||||
// Code alignment factor.
|
||||
this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x80, 0x00});
|
||||
// Data alignment factor.
|
||||
this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
|
||||
// Return address register
|
||||
this->memory_.SetData8(0x5014, 0x84);
|
||||
// Augmentation length
|
||||
this->memory_.SetMemory(0x5015, std::vector<uint8_t>{0x84, 0x00});
|
||||
// R data.
|
||||
this->memory_.SetData8(0x5017, DW_EH_PE_pcrel | DW_EH_PE_udata2);
|
||||
|
||||
// FDE 32 information.
|
||||
this->memory_.SetData32(0x5100, 0xfc);
|
||||
this->memory_.SetData32(0x5104, 0x104);
|
||||
this->memory_.SetData16(0x5108, 0x1500);
|
||||
this->memory_.SetData16(0x510a, 0x200);
|
||||
|
||||
ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200, 0));
|
||||
ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
|
||||
|
||||
typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
|
||||
this->eh_frame_->TestGetFdeInfo(0, &info);
|
||||
EXPECT_EQ(0x5100U, info.offset);
|
||||
EXPECT_EQ(0x6606U, info.start);
|
||||
EXPECT_EQ(0x6806U, info.end);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, Init_version4) {
|
||||
// CIE 32 information.
|
||||
this->memory_.SetData32(0x5000, 0xfc);
|
||||
this->memory_.SetData32(0x5004, 0);
|
||||
this->memory_.SetData8(0x5008, 4);
|
||||
// Augment string.
|
||||
this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
|
||||
// Address size.
|
||||
this->memory_.SetData8(0x500e, 4);
|
||||
// Segment size.
|
||||
this->memory_.SetData8(0x500f, 0);
|
||||
// Code alignment factor.
|
||||
this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x80, 0x00});
|
||||
// Data alignment factor.
|
||||
this->memory_.SetMemory(0x5012, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
|
||||
// Return address register
|
||||
this->memory_.SetMemory(0x5016, std::vector<uint8_t>{0x85, 0x10});
|
||||
// Augmentation length
|
||||
this->memory_.SetMemory(0x5018, std::vector<uint8_t>{0x84, 0x00});
|
||||
// L data.
|
||||
this->memory_.SetData8(0x501a, 0x10);
|
||||
// P data.
|
||||
this->memory_.SetData8(0x501b, DW_EH_PE_udata4);
|
||||
this->memory_.SetData32(0x501c, 0x100);
|
||||
// R data.
|
||||
this->memory_.SetData8(0x5020, DW_EH_PE_pcrel | DW_EH_PE_udata2);
|
||||
|
||||
// FDE 32 information.
|
||||
this->memory_.SetData32(0x5100, 0xfc);
|
||||
this->memory_.SetData32(0x5104, 0x104);
|
||||
this->memory_.SetData16(0x5108, 0x1500);
|
||||
this->memory_.SetData16(0x510a, 0x200);
|
||||
|
||||
ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200, 0));
|
||||
ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
|
||||
|
||||
typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
|
||||
this->eh_frame_->TestGetFdeInfo(0, &info);
|
||||
EXPECT_EQ(0x5100U, info.offset);
|
||||
EXPECT_EQ(0x6606U, info.start);
|
||||
EXPECT_EQ(0x6806U, info.end);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc) {
|
||||
typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
info.start = 0x1000 * (i + 1);
|
||||
info.end = 0x1000 * (i + 2) - 0x10;
|
||||
info.offset = 0x5000 + i * 0x20;
|
||||
this->eh_frame_->TestPushFdeInfo(info);
|
||||
}
|
||||
|
||||
this->eh_frame_->TestSetFdeCount(0);
|
||||
uint64_t fde_offset;
|
||||
ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset));
|
||||
ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
|
||||
|
||||
this->eh_frame_->TestSetFdeCount(9);
|
||||
ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
|
||||
ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
|
||||
// Odd number of elements.
|
||||
for (size_t i = 0; i < 9; i++) {
|
||||
TypeParam pc = 0x1000 * (i + 1);
|
||||
ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i;
|
||||
EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
|
||||
ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i;
|
||||
EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
|
||||
ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
|
||||
<< "Failed at index " << i;
|
||||
EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
|
||||
ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
|
||||
<< "Failed at index " << i;
|
||||
ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
|
||||
}
|
||||
|
||||
// Even number of elements.
|
||||
this->eh_frame_->TestSetFdeCount(10);
|
||||
info.start = 0xa000;
|
||||
info.end = 0xaff0;
|
||||
info.offset = 0x5120;
|
||||
this->eh_frame_->TestPushFdeInfo(info);
|
||||
|
||||
for (size_t i = 0; i < 10; i++) {
|
||||
TypeParam pc = 0x1000 * (i + 1);
|
||||
ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i;
|
||||
EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
|
||||
ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i;
|
||||
EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
|
||||
ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
|
||||
<< "Failed at index " << i;
|
||||
EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
|
||||
ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
|
||||
<< "Failed at index " << i;
|
||||
ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) {
|
||||
this->eh_frame_->TestSetOffset(0x4000);
|
||||
|
||||
// CIE 32 information.
|
||||
this->memory_.SetData32(0xf000, 0x100);
|
||||
this->memory_.SetData32(0xf004, 0);
|
||||
this->memory_.SetData8(0xf008, 0x1);
|
||||
this->memory_.SetData8(0xf009, '\0');
|
||||
this->memory_.SetData8(0xf00a, 4);
|
||||
this->memory_.SetData8(0xf00b, 8);
|
||||
this->memory_.SetData8(0xf00c, 0x20);
|
||||
|
||||
// FDE 32 information.
|
||||
this->memory_.SetData32(0x14000, 0x20);
|
||||
this->memory_.SetData32(0x14004, 0x5004);
|
||||
this->memory_.SetData32(0x14008, 0x9000);
|
||||
this->memory_.SetData32(0x1400c, 0x100);
|
||||
|
||||
const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x14000);
|
||||
ASSERT_TRUE(fde != nullptr);
|
||||
EXPECT_EQ(0x14010U, fde->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x14024U, fde->cfa_instructions_end);
|
||||
EXPECT_EQ(0x1d008U, fde->pc_start);
|
||||
EXPECT_EQ(0x1d108U, fde->pc_end);
|
||||
EXPECT_EQ(0xf000U, fde->cie_offset);
|
||||
EXPECT_EQ(0x5000U, fde->cie_offset);
|
||||
EXPECT_EQ(0x5124U, fde->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x5208U, fde->cfa_instructions_end);
|
||||
EXPECT_EQ(0x6618U, fde->pc_start);
|
||||
EXPECT_EQ(0x6818U, fde->pc_end);
|
||||
EXPECT_EQ(0U, fde->lsda_address);
|
||||
|
||||
ASSERT_TRUE(fde->cie != nullptr);
|
||||
EXPECT_EQ(1U, fde->cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
|
||||
EXPECT_EQ(0U, fde->cie->segment_size);
|
||||
EXPECT_EQ(1U, fde->cie->augmentation_string.size());
|
||||
EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
|
||||
EXPECT_EQ(0U, fde->cie->personality_handler);
|
||||
EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end);
|
||||
EXPECT_EQ(4U, fde->cie->code_alignment_factor);
|
||||
EXPECT_EQ(8, fde->cie->data_alignment_factor);
|
||||
EXPECT_EQ(0x20U, fde->cie->return_address_register);
|
||||
const DwarfCie* cie = fde->cie;
|
||||
ASSERT_TRUE(cie != nullptr);
|
||||
EXPECT_EQ(1U, cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
|
||||
EXPECT_EQ(0U, cie->segment_size);
|
||||
EXPECT_EQ('\0', cie->augmentation_string[0]);
|
||||
EXPECT_EQ(0U, cie->personality_handler);
|
||||
EXPECT_EQ(0x5019U, cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x5108U, cie->cfa_instructions_end);
|
||||
EXPECT_EQ(16U, cie->code_alignment_factor);
|
||||
EXPECT_EQ(32U, cie->data_alignment_factor);
|
||||
EXPECT_EQ(1U, cie->return_address_register);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) {
|
||||
this->eh_frame_->TestSetOffset(0x2000);
|
||||
|
||||
// CIE 64 information.
|
||||
this->memory_.SetData32(0x6000, 0xffffffff);
|
||||
this->memory_.SetData64(0x6004, 0x100);
|
||||
this->memory_.SetData64(0x600c, 0);
|
||||
this->memory_.SetData8(0x6014, 0x1);
|
||||
this->memory_.SetData8(0x6015, '\0');
|
||||
this->memory_.SetData8(0x6016, 4);
|
||||
this->memory_.SetData8(0x6017, 8);
|
||||
this->memory_.SetData8(0x6018, 0x20);
|
||||
|
||||
// FDE 64 information.
|
||||
this->memory_.SetData32(0x8000, 0xffffffff);
|
||||
this->memory_.SetData64(0x8004, 0x200);
|
||||
this->memory_.SetData64(0x800c, 0x200c);
|
||||
this->memory_.SetData64(0x8014, 0x5000);
|
||||
this->memory_.SetData64(0x801c, 0x300);
|
||||
|
||||
const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x8000);
|
||||
ASSERT_TRUE(fde != nullptr);
|
||||
EXPECT_EQ(0x8024U, fde->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x820cU, fde->cfa_instructions_end);
|
||||
EXPECT_EQ(0xd018U, fde->pc_start);
|
||||
EXPECT_EQ(0xd318U, fde->pc_end);
|
||||
EXPECT_EQ(0x6000U, fde->cie_offset);
|
||||
EXPECT_EQ(0U, fde->lsda_address);
|
||||
|
||||
ASSERT_TRUE(fde->cie != nullptr);
|
||||
EXPECT_EQ(1U, fde->cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
|
||||
EXPECT_EQ(0U, fde->cie->segment_size);
|
||||
EXPECT_EQ(1U, fde->cie->augmentation_string.size());
|
||||
EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
|
||||
EXPECT_EQ(0U, fde->cie->personality_handler);
|
||||
EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end);
|
||||
EXPECT_EQ(4U, fde->cie->code_alignment_factor);
|
||||
EXPECT_EQ(8, fde->cie->data_alignment_factor);
|
||||
EXPECT_EQ(0x20U, fde->cie->return_address_register);
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64,
|
||||
Init64_fde_not_following_cie, Init_non_zero_load_bias, Init_version1,
|
||||
Init_version4, GetFdeOffsetFromPc, GetCieFde32, GetCieFde64);
|
||||
REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, GetFdeCieFromOffset32, GetFdeCieFromOffset64);
|
||||
|
||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes);
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@
|
|||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class MockDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr<TypeParam> {
|
||||
class TestDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr<TypeParam> {
|
||||
public:
|
||||
MockDwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrameWithHdr<TypeParam>(memory) {}
|
||||
~MockDwarfEhFrameWithHdr() = default;
|
||||
TestDwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrameWithHdr<TypeParam>(memory) {}
|
||||
~TestDwarfEhFrameWithHdr() = default;
|
||||
|
||||
void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; }
|
||||
void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; }
|
||||
|
|
@ -64,14 +64,14 @@ class DwarfEhFrameWithHdrTest : public ::testing::Test {
|
|||
protected:
|
||||
void SetUp() override {
|
||||
memory_.Clear();
|
||||
eh_frame_ = new MockDwarfEhFrameWithHdr<TypeParam>(&memory_);
|
||||
eh_frame_ = new TestDwarfEhFrameWithHdr<TypeParam>(&memory_);
|
||||
ResetLogs();
|
||||
}
|
||||
|
||||
void TearDown() override { delete eh_frame_; }
|
||||
|
||||
MemoryFake memory_;
|
||||
MockDwarfEhFrameWithHdr<TypeParam>* eh_frame_ = nullptr;
|
||||
TestDwarfEhFrameWithHdr<TypeParam>* eh_frame_ = nullptr;
|
||||
};
|
||||
TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest);
|
||||
|
||||
|
|
@ -121,23 +121,14 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias) {
|
|||
// CIE 32 information.
|
||||
this->memory_.SetData32(0x1300, 0xfc);
|
||||
this->memory_.SetData32(0x1304, 0);
|
||||
this->memory_.SetData8(0x1308, 1);
|
||||
this->memory_.SetData8(0x1309, 'z');
|
||||
this->memory_.SetData8(0x130a, 'R');
|
||||
this->memory_.SetData8(0x130b, '\0');
|
||||
this->memory_.SetData8(0x130c, 0);
|
||||
this->memory_.SetData8(0x130d, 0);
|
||||
this->memory_.SetData8(0x130e, 0);
|
||||
this->memory_.SetData8(0x130f, 0);
|
||||
this->memory_.SetData8(0x1310, 0x1b);
|
||||
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, 0x10f8);
|
||||
this->memory_.SetData32(0x140c, 0x200);
|
||||
this->memory_.SetData8(0x1410, 0);
|
||||
this->memory_.SetData8(0x1411, 0);
|
||||
this->memory_.SetData16(0x1410, 0);
|
||||
|
||||
ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000));
|
||||
EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
|
||||
|
|
@ -157,6 +148,68 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias) {
|
|||
EXPECT_EQ(0x4700U, fde->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});
|
||||
this->memory_.SetData16(0x1004, 0x500);
|
||||
this->memory_.SetData32(0x1006, 4);
|
||||
|
||||
// Header information.
|
||||
this->memory_.SetData32(0x100a, 0x4600);
|
||||
this->memory_.SetData32(0x100e, 0x1500);
|
||||
this->memory_.SetData32(0x1012, 0x5500);
|
||||
this->memory_.SetData32(0x1016, 0x1400);
|
||||
this->memory_.SetData32(0x101a, 0x6800);
|
||||
this->memory_.SetData32(0x101e, 0x1700);
|
||||
this->memory_.SetData32(0x1022, 0x7700);
|
||||
this->memory_.SetData32(0x1026, 0x1600);
|
||||
|
||||
// CIE 32 information.
|
||||
this->memory_.SetData32(0x1300, 0xfc);
|
||||
this->memory_.SetData32(0x1304, 0);
|
||||
this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, '\0', 0, 0, 0});
|
||||
|
||||
// FDE 32 information.
|
||||
// pc 0x5500 - 0x5700
|
||||
this->memory_.SetData32(0x1400, 0xfc);
|
||||
this->memory_.SetData32(0x1404, 0x104);
|
||||
this->memory_.SetData32(0x1408, 0x40f8);
|
||||
this->memory_.SetData32(0x140c, 0x200);
|
||||
|
||||
// pc 0x4600 - 0x4800
|
||||
this->memory_.SetData32(0x1500, 0xfc);
|
||||
this->memory_.SetData32(0x1504, 0x204);
|
||||
this->memory_.SetData32(0x1508, 0x30f8);
|
||||
this->memory_.SetData32(0x150c, 0x200);
|
||||
|
||||
// pc 0x7700 - 0x7900
|
||||
this->memory_.SetData32(0x1600, 0xfc);
|
||||
this->memory_.SetData32(0x1604, 0x304);
|
||||
this->memory_.SetData32(0x1608, 0x60f8);
|
||||
this->memory_.SetData32(0x160c, 0x200);
|
||||
|
||||
// pc 0x6800 - 0x6a00
|
||||
this->memory_.SetData32(0x1700, 0xfc);
|
||||
this->memory_.SetData32(0x1704, 0x404);
|
||||
this->memory_.SetData32(0x1708, 0x50f8);
|
||||
this->memory_.SetData32(0x170c, 0x200);
|
||||
|
||||
ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
|
||||
|
||||
std::vector<const DwarfFde*> fdes;
|
||||
this->eh_frame_->GetFdes(&fdes);
|
||||
ASSERT_EQ(4U, fdes.size());
|
||||
|
||||
EXPECT_EQ(0x4600U, fdes[0]->pc_start);
|
||||
EXPECT_EQ(0x4800U, fdes[0]->pc_end);
|
||||
EXPECT_EQ(0x5500U, fdes[1]->pc_start);
|
||||
EXPECT_EQ(0x5700U, fdes[1]->pc_end);
|
||||
EXPECT_EQ(0x6800U, fdes[2]->pc_start);
|
||||
EXPECT_EQ(0x6a00U, fdes[2]->pc_end);
|
||||
EXPECT_EQ(0x7700U, fdes[3]->pc_start);
|
||||
EXPECT_EQ(0x7900U, fdes[3]->pc_end);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
|
||||
this->eh_frame_->TestSetTableEntrySize(0x10);
|
||||
this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
|
||||
|
|
@ -388,11 +441,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) {
|
|||
// CIE 32 information.
|
||||
this->memory_.SetData32(0xf000, 0x100);
|
||||
this->memory_.SetData32(0xf004, 0);
|
||||
this->memory_.SetData8(0xf008, 0x1);
|
||||
this->memory_.SetData8(0xf009, '\0');
|
||||
this->memory_.SetData8(0xf00a, 4);
|
||||
this->memory_.SetData8(0xf00b, 8);
|
||||
this->memory_.SetData8(0xf00c, 0x20);
|
||||
this->memory_.SetMemory(0xf008, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
|
||||
|
||||
// FDE 32 information.
|
||||
this->memory_.SetData32(0x14000, 0x20);
|
||||
|
|
@ -429,11 +478,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde64) {
|
|||
this->memory_.SetData32(0x6000, 0xffffffff);
|
||||
this->memory_.SetData64(0x6004, 0x100);
|
||||
this->memory_.SetData64(0x600c, 0);
|
||||
this->memory_.SetData8(0x6014, 0x1);
|
||||
this->memory_.SetData8(0x6015, '\0');
|
||||
this->memory_.SetData8(0x6016, 4);
|
||||
this->memory_.SetData8(0x6017, 8);
|
||||
this->memory_.SetData8(0x6018, 0x20);
|
||||
this->memory_.SetMemory(0x6014, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
|
||||
|
||||
// FDE 64 information.
|
||||
this->memory_.SetData32(0x8000, 0xffffffff);
|
||||
|
|
@ -478,7 +523,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) {
|
|||
ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias,
|
||||
REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, GetFdes,
|
||||
GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel,
|
||||
GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached,
|
||||
GetFdeOffsetBinary_verify, GetFdeOffsetBinary_index_fail,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <unwindstack/DwarfError.h>
|
||||
|
|
@ -31,42 +30,27 @@
|
|||
namespace unwindstack {
|
||||
|
||||
template <typename TypeParam>
|
||||
class MockDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
|
||||
class TestDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
|
||||
public:
|
||||
MockDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
|
||||
virtual ~MockDwarfSectionImpl() = default;
|
||||
TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
|
||||
virtual ~TestDwarfSectionImpl() = default;
|
||||
|
||||
MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t));
|
||||
bool Init(uint64_t, uint64_t, uint64_t) override { return false; }
|
||||
|
||||
MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*));
|
||||
void GetFdes(std::vector<const DwarfFde*>*) override {}
|
||||
|
||||
MOCK_METHOD1(GetFdeFromIndex, const DwarfFde*(size_t));
|
||||
const DwarfFde* GetFdeFromPc(uint64_t) override { return nullptr; }
|
||||
|
||||
MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t));
|
||||
uint64_t GetCieOffsetFromFde32(uint32_t) { return 0; }
|
||||
|
||||
MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t));
|
||||
uint64_t GetCieOffsetFromFde64(uint64_t) { return 0; }
|
||||
|
||||
MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t));
|
||||
|
||||
void TestSetCie32Value(uint32_t value32) { this->cie32_value_ = value32; }
|
||||
|
||||
void TestSetCie64Value(uint64_t value64) { this->cie64_value_ = value64; }
|
||||
|
||||
void TestSetCachedCieEntry(uint64_t offset, const DwarfCie& cie) {
|
||||
this->cie_entries_[offset] = cie;
|
||||
}
|
||||
void TestClearCachedCieEntry() { this->cie_entries_.clear(); }
|
||||
|
||||
void TestSetCachedFdeEntry(uint64_t offset, const DwarfFde& fde) {
|
||||
this->fde_entries_[offset] = fde;
|
||||
}
|
||||
void TestClearCachedFdeEntry() { this->fde_entries_.clear(); }
|
||||
uint64_t AdjustPcFromFde(uint64_t) override { return 0; }
|
||||
|
||||
void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) {
|
||||
this->cie_loc_regs_[offset] = loc_regs;
|
||||
}
|
||||
void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); }
|
||||
|
||||
void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
|
||||
};
|
||||
|
||||
|
|
@ -75,21 +59,41 @@ class DwarfSectionImplTest : public ::testing::Test {
|
|||
protected:
|
||||
void SetUp() override {
|
||||
memory_.Clear();
|
||||
section_ = new MockDwarfSectionImpl<TypeParam>(&memory_);
|
||||
section_ = new TestDwarfSectionImpl<TypeParam>(&memory_);
|
||||
ResetLogs();
|
||||
section_->TestSetCie32Value(static_cast<uint32_t>(-1));
|
||||
section_->TestSetCie64Value(static_cast<uint64_t>(-1));
|
||||
}
|
||||
|
||||
void TearDown() override { delete section_; }
|
||||
|
||||
MemoryFake memory_;
|
||||
MockDwarfSectionImpl<TypeParam>* section_ = nullptr;
|
||||
TestDwarfSectionImpl<TypeParam>* section_ = nullptr;
|
||||
};
|
||||
TYPED_TEST_CASE_P(DwarfSectionImplTest);
|
||||
|
||||
// NOTE: All test class variables need to be referenced as this->.
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache) {
|
||||
ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
|
||||
EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
|
||||
|
||||
this->section_->TestClearError();
|
||||
ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
|
||||
EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
|
||||
ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
|
||||
EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
|
||||
|
||||
this->section_->TestClearError();
|
||||
ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
|
||||
EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
|
||||
DwarfCie cie{.version = 3, .return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
|
|
@ -487,334 +491,6 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
|
|||
EXPECT_EQ(0x80000000U, regs.pc());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) {
|
||||
ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
|
||||
EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
|
||||
this->section_->TestClearError();
|
||||
ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
|
||||
EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) {
|
||||
this->memory_.SetData32(0x5000, 0x100);
|
||||
this->memory_.SetData32(0x5004, 0xffffffff);
|
||||
this->memory_.SetData8(0x5008, 0x1);
|
||||
this->memory_.SetData8(0x5009, '\0');
|
||||
this->memory_.SetData8(0x500a, 4);
|
||||
this->memory_.SetData8(0x500b, 8);
|
||||
this->memory_.SetData8(0x500c, 0x20);
|
||||
|
||||
const DwarfCie* cie = this->section_->GetCie(0x5000);
|
||||
ASSERT_TRUE(cie != nullptr);
|
||||
EXPECT_EQ(1U, cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
|
||||
EXPECT_EQ(0U, cie->segment_size);
|
||||
EXPECT_EQ(1U, cie->augmentation_string.size());
|
||||
EXPECT_EQ('\0', cie->augmentation_string[0]);
|
||||
EXPECT_EQ(0U, cie->personality_handler);
|
||||
EXPECT_EQ(0x500dU, cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
|
||||
EXPECT_EQ(4U, cie->code_alignment_factor);
|
||||
EXPECT_EQ(8, cie->data_alignment_factor);
|
||||
EXPECT_EQ(0x20U, cie->return_address_register);
|
||||
EXPECT_EQ(DWARF_ERROR_NONE, this->section_->LastErrorCode());
|
||||
|
||||
this->section_->TestClearCachedCieEntry();
|
||||
// Set version to 0, 2, 5 and verify we fail.
|
||||
this->memory_.SetData8(0x5008, 0x0);
|
||||
this->section_->TestClearError();
|
||||
ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
|
||||
|
||||
this->memory_.SetData8(0x5008, 0x2);
|
||||
this->section_->TestClearError();
|
||||
ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
|
||||
|
||||
this->memory_.SetData8(0x5008, 0x5);
|
||||
this->section_->TestClearError();
|
||||
ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) {
|
||||
this->memory_.SetData32(0x5000, 0x100);
|
||||
this->memory_.SetData32(0x5004, 0xffffffff);
|
||||
this->memory_.SetData8(0x5008, 0x1);
|
||||
this->memory_.SetData8(0x5009, '\0');
|
||||
this->memory_.SetData8(0x500a, 4);
|
||||
this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f});
|
||||
this->memory_.SetData8(0x5010, 0x20);
|
||||
|
||||
const DwarfCie* cie = this->section_->GetCie(0x5000);
|
||||
ASSERT_TRUE(cie != nullptr);
|
||||
EXPECT_EQ(1U, cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
|
||||
EXPECT_EQ(0U, cie->segment_size);
|
||||
EXPECT_EQ(1U, cie->augmentation_string.size());
|
||||
EXPECT_EQ('\0', cie->augmentation_string[0]);
|
||||
EXPECT_EQ(0U, cie->personality_handler);
|
||||
EXPECT_EQ(0x5011U, cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
|
||||
EXPECT_EQ(4U, cie->code_alignment_factor);
|
||||
EXPECT_EQ(-4, cie->data_alignment_factor);
|
||||
EXPECT_EQ(0x20U, cie->return_address_register);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) {
|
||||
this->memory_.SetData32(0x8000, 0xffffffff);
|
||||
this->memory_.SetData64(0x8004, 0x200);
|
||||
this->memory_.SetData64(0x800c, 0xffffffffffffffffULL);
|
||||
this->memory_.SetData8(0x8014, 0x1);
|
||||
this->memory_.SetData8(0x8015, '\0');
|
||||
this->memory_.SetData8(0x8016, 4);
|
||||
this->memory_.SetData8(0x8017, 8);
|
||||
this->memory_.SetData8(0x8018, 0x20);
|
||||
|
||||
const DwarfCie* cie = this->section_->GetCie(0x8000);
|
||||
ASSERT_TRUE(cie != nullptr);
|
||||
EXPECT_EQ(1U, cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
|
||||
EXPECT_EQ(0U, cie->segment_size);
|
||||
EXPECT_EQ(1U, cie->augmentation_string.size());
|
||||
EXPECT_EQ('\0', cie->augmentation_string[0]);
|
||||
EXPECT_EQ(0U, cie->personality_handler);
|
||||
EXPECT_EQ(0x8019U, cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x820cU, cie->cfa_instructions_end);
|
||||
EXPECT_EQ(4U, cie->code_alignment_factor);
|
||||
EXPECT_EQ(8, cie->data_alignment_factor);
|
||||
EXPECT_EQ(0x20U, cie->return_address_register);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCie_augment) {
|
||||
this->memory_.SetData32(0x5000, 0x100);
|
||||
this->memory_.SetData32(0x5004, 0xffffffff);
|
||||
this->memory_.SetData8(0x5008, 0x1);
|
||||
this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
|
||||
this->memory_.SetData8(0x500e, 4);
|
||||
this->memory_.SetData8(0x500f, 8);
|
||||
this->memory_.SetData8(0x5010, 0x10);
|
||||
// Augment length.
|
||||
this->memory_.SetData8(0x5011, 0xf);
|
||||
// L data.
|
||||
this->memory_.SetData8(0x5012, DW_EH_PE_textrel | DW_EH_PE_udata2);
|
||||
// P data.
|
||||
this->memory_.SetData8(0x5013, DW_EH_PE_udata4);
|
||||
this->memory_.SetData32(0x5014, 0x12345678);
|
||||
// R data.
|
||||
this->memory_.SetData8(0x5018, DW_EH_PE_udata2);
|
||||
|
||||
const DwarfCie* cie = this->section_->GetCie(0x5000);
|
||||
ASSERT_TRUE(cie != nullptr);
|
||||
EXPECT_EQ(1U, cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding);
|
||||
EXPECT_EQ(0U, cie->segment_size);
|
||||
EXPECT_EQ(5U, cie->augmentation_string.size());
|
||||
EXPECT_EQ('z', cie->augmentation_string[0]);
|
||||
EXPECT_EQ('L', cie->augmentation_string[1]);
|
||||
EXPECT_EQ('P', cie->augmentation_string[2]);
|
||||
EXPECT_EQ('R', cie->augmentation_string[3]);
|
||||
EXPECT_EQ('\0', cie->augmentation_string[4]);
|
||||
EXPECT_EQ(0x12345678U, cie->personality_handler);
|
||||
EXPECT_EQ(0x5021U, cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
|
||||
EXPECT_EQ(4U, cie->code_alignment_factor);
|
||||
EXPECT_EQ(8, cie->data_alignment_factor);
|
||||
EXPECT_EQ(0x10U, cie->return_address_register);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_3) {
|
||||
this->memory_.SetData32(0x5000, 0x100);
|
||||
this->memory_.SetData32(0x5004, 0xffffffff);
|
||||
this->memory_.SetData8(0x5008, 0x3);
|
||||
this->memory_.SetData8(0x5009, '\0');
|
||||
this->memory_.SetData8(0x500a, 4);
|
||||
this->memory_.SetData8(0x500b, 8);
|
||||
this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03});
|
||||
|
||||
const DwarfCie* cie = this->section_->GetCie(0x5000);
|
||||
ASSERT_TRUE(cie != nullptr);
|
||||
EXPECT_EQ(3U, cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
|
||||
EXPECT_EQ(0U, cie->segment_size);
|
||||
EXPECT_EQ(1U, cie->augmentation_string.size());
|
||||
EXPECT_EQ('\0', cie->augmentation_string[0]);
|
||||
EXPECT_EQ(0U, cie->personality_handler);
|
||||
EXPECT_EQ(0x500eU, cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
|
||||
EXPECT_EQ(4U, cie->code_alignment_factor);
|
||||
EXPECT_EQ(8, cie->data_alignment_factor);
|
||||
EXPECT_EQ(0x181U, cie->return_address_register);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) {
|
||||
this->memory_.SetData32(0x5000, 0x100);
|
||||
this->memory_.SetData32(0x5004, 0xffffffff);
|
||||
this->memory_.SetData8(0x5008, 0x4);
|
||||
this->memory_.SetData8(0x5009, '\0');
|
||||
this->memory_.SetData8(0x500a, 4);
|
||||
this->memory_.SetData8(0x500b, 0x13);
|
||||
this->memory_.SetData8(0x500c, 4);
|
||||
this->memory_.SetData8(0x500d, 8);
|
||||
this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03});
|
||||
|
||||
const DwarfCie* cie = this->section_->GetCie(0x5000);
|
||||
ASSERT_TRUE(cie != nullptr);
|
||||
EXPECT_EQ(4U, cie->version);
|
||||
EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
|
||||
EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
|
||||
EXPECT_EQ(0x13U, cie->segment_size);
|
||||
EXPECT_EQ(1U, cie->augmentation_string.size());
|
||||
EXPECT_EQ('\0', cie->augmentation_string[0]);
|
||||
EXPECT_EQ(0U, cie->personality_handler);
|
||||
EXPECT_EQ(0x5010U, cie->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
|
||||
EXPECT_EQ(4U, cie->code_alignment_factor);
|
||||
EXPECT_EQ(8, cie->data_alignment_factor);
|
||||
EXPECT_EQ(0x181U, cie->return_address_register);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
|
||||
ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
|
||||
EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
|
||||
this->section_->TestClearError();
|
||||
ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
|
||||
EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) {
|
||||
this->memory_.SetData32(0x4000, 0x20);
|
||||
this->memory_.SetData32(0x4004, 0x8000);
|
||||
this->memory_.SetData32(0x4008, 0x5000);
|
||||
this->memory_.SetData32(0x400c, 0x100);
|
||||
|
||||
EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
|
||||
DwarfCie cie{};
|
||||
cie.fde_address_encoding = DW_EH_PE_udata4;
|
||||
this->section_->TestSetCachedCieEntry(0x8000, cie);
|
||||
EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
|
||||
|
||||
const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
|
||||
ASSERT_TRUE(fde != nullptr);
|
||||
ASSERT_TRUE(fde->cie != nullptr);
|
||||
EXPECT_EQ(0x4010U, fde->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x4024U, fde->cfa_instructions_end);
|
||||
EXPECT_EQ(0x5000U, fde->pc_start);
|
||||
EXPECT_EQ(0x5100U, fde->pc_end);
|
||||
EXPECT_EQ(0x8000U, fde->cie_offset);
|
||||
EXPECT_EQ(0U, fde->lsda_address);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment_non_zero_segment_size) {
|
||||
this->memory_.SetData32(0x4000, 0x30);
|
||||
this->memory_.SetData32(0x4004, 0x8000);
|
||||
this->memory_.SetData32(0x4018, 0x5000);
|
||||
this->memory_.SetData32(0x401c, 0x100);
|
||||
|
||||
EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
|
||||
DwarfCie cie{};
|
||||
cie.fde_address_encoding = DW_EH_PE_udata4;
|
||||
cie.segment_size = 0x10;
|
||||
this->section_->TestSetCachedCieEntry(0x8000, cie);
|
||||
EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
|
||||
|
||||
const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
|
||||
ASSERT_TRUE(fde != nullptr);
|
||||
ASSERT_TRUE(fde->cie != nullptr);
|
||||
EXPECT_EQ(0x4020U, fde->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x4034U, fde->cfa_instructions_end);
|
||||
EXPECT_EQ(0x5000U, fde->pc_start);
|
||||
EXPECT_EQ(0x5100U, fde->pc_end);
|
||||
EXPECT_EQ(0x8000U, fde->cie_offset);
|
||||
EXPECT_EQ(0U, fde->lsda_address);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_augment) {
|
||||
this->memory_.SetData32(0x4000, 0x100);
|
||||
this->memory_.SetData32(0x4004, 0x8000);
|
||||
this->memory_.SetData32(0x4008, 0x5000);
|
||||
this->memory_.SetData32(0x400c, 0x100);
|
||||
this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01});
|
||||
this->memory_.SetData16(0x4012, 0x1234);
|
||||
|
||||
EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
|
||||
DwarfCie cie{};
|
||||
cie.fde_address_encoding = DW_EH_PE_udata4;
|
||||
cie.augmentation_string.push_back('z');
|
||||
cie.lsda_encoding = DW_EH_PE_udata2;
|
||||
this->section_->TestSetCachedCieEntry(0x8000, cie);
|
||||
EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
|
||||
|
||||
const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
|
||||
ASSERT_TRUE(fde != nullptr);
|
||||
ASSERT_TRUE(fde->cie != nullptr);
|
||||
EXPECT_EQ(0x4094U, fde->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x4104U, fde->cfa_instructions_end);
|
||||
EXPECT_EQ(0x5000U, fde->pc_start);
|
||||
EXPECT_EQ(0x5100U, fde->pc_end);
|
||||
EXPECT_EQ(0x8000U, fde->cie_offset);
|
||||
EXPECT_EQ(0x1234U, fde->lsda_address);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_64_no_augment) {
|
||||
this->memory_.SetData32(0x4000, 0xffffffff);
|
||||
this->memory_.SetData64(0x4004, 0x100);
|
||||
this->memory_.SetData64(0x400c, 0x12345678);
|
||||
this->memory_.SetData32(0x4014, 0x5000);
|
||||
this->memory_.SetData32(0x4018, 0x100);
|
||||
|
||||
EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678))
|
||||
.WillOnce(::testing::Return(0x12345678));
|
||||
DwarfCie cie{};
|
||||
cie.fde_address_encoding = DW_EH_PE_udata4;
|
||||
this->section_->TestSetCachedCieEntry(0x12345678, cie);
|
||||
EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
|
||||
|
||||
const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
|
||||
ASSERT_TRUE(fde != nullptr);
|
||||
ASSERT_TRUE(fde->cie != nullptr);
|
||||
EXPECT_EQ(0x401cU, fde->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x410cU, fde->cfa_instructions_end);
|
||||
EXPECT_EQ(0x5000U, fde->pc_start);
|
||||
EXPECT_EQ(0x5100U, fde->pc_end);
|
||||
EXPECT_EQ(0x12345678U, fde->cie_offset);
|
||||
EXPECT_EQ(0U, fde->lsda_address);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_cached) {
|
||||
DwarfCie cie{};
|
||||
cie.fde_address_encoding = DW_EH_PE_udata4;
|
||||
cie.augmentation_string.push_back('z');
|
||||
cie.lsda_encoding = DW_EH_PE_udata2;
|
||||
|
||||
DwarfFde fde_cached{};
|
||||
fde_cached.cfa_instructions_offset = 0x1000;
|
||||
fde_cached.cfa_instructions_end = 0x1100;
|
||||
fde_cached.pc_start = 0x9000;
|
||||
fde_cached.pc_end = 0x9400;
|
||||
fde_cached.cie_offset = 0x30000;
|
||||
fde_cached.cie = &cie;
|
||||
this->section_->TestSetCachedFdeEntry(0x6000, fde_cached);
|
||||
|
||||
const DwarfFde* fde = this->section_->GetFdeFromOffset(0x6000);
|
||||
ASSERT_TRUE(fde != nullptr);
|
||||
ASSERT_EQ(&cie, fde->cie);
|
||||
EXPECT_EQ(0x1000U, fde->cfa_instructions_offset);
|
||||
EXPECT_EQ(0x1100U, fde->cfa_instructions_end);
|
||||
EXPECT_EQ(0x9000U, fde->pc_start);
|
||||
EXPECT_EQ(0x9400U, fde->pc_end);
|
||||
EXPECT_EQ(0x30000U, fde->cie_offset);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
|
||||
DwarfCie cie{};
|
||||
cie.cfa_instructions_offset = 0x3000;
|
||||
|
|
@ -895,18 +571,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Log) {
|
|||
ASSERT_EQ("", GetFakeLogBuf());
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_CASE_P(
|
||||
DwarfSectionImplTest, Eval_cfa_expr_eval_fail, Eval_cfa_expr_no_stack,
|
||||
Eval_cfa_expr_is_register, Eval_cfa_expr, Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa,
|
||||
Eval_cfa_bad, Eval_cfa_register_prev, Eval_cfa_register_from_value, Eval_double_indirection,
|
||||
Eval_register_reference_chain, Eval_dex_pc, Eval_invalid_register, Eval_different_reg_locations,
|
||||
Eval_return_address_undefined, Eval_pc_zero, Eval_return_address, Eval_ignore_large_reg_loc,
|
||||
Eval_reg_expr, Eval_reg_val_expr, GetCie_fail_should_not_cache, GetCie_32_version_check,
|
||||
GetCie_negative_data_alignment_factor, GetCie_64_no_augment, GetCie_augment, GetCie_version_3,
|
||||
GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment,
|
||||
GetFdeFromOffset_32_no_augment_non_zero_segment_size, GetFdeFromOffset_32_augment,
|
||||
GetFdeFromOffset_64_no_augment, GetFdeFromOffset_cached, GetCfaLocationInfo_cie_not_cached,
|
||||
GetCfaLocationInfo_cie_cached, Log);
|
||||
REGISTER_TYPED_TEST_CASE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache,
|
||||
GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail,
|
||||
Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr,
|
||||
Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad,
|
||||
Eval_cfa_register_prev, Eval_cfa_register_from_value,
|
||||
Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc,
|
||||
Eval_invalid_register, Eval_different_reg_locations,
|
||||
Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
|
||||
Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
|
||||
GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
|
||||
|
||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
|
||||
|
|
|
|||
|
|
@ -30,24 +30,18 @@ class MockDwarfSection : public DwarfSection {
|
|||
MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
|
||||
virtual ~MockDwarfSection() = default;
|
||||
|
||||
MOCK_METHOD3(Log, bool(uint8_t, uint64_t, const DwarfFde*));
|
||||
MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t));
|
||||
|
||||
MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*));
|
||||
|
||||
MOCK_METHOD3(Log, bool(uint8_t, uint64_t, const DwarfFde*));
|
||||
|
||||
MOCK_METHOD1(GetFdes, void(std::vector<const DwarfFde*>*));
|
||||
|
||||
MOCK_METHOD1(GetFdeFromPc, const DwarfFde*(uint64_t));
|
||||
|
||||
MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*));
|
||||
|
||||
MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t));
|
||||
|
||||
MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*));
|
||||
|
||||
MOCK_METHOD1(GetFdeFromOffset, const DwarfFde*(uint64_t));
|
||||
|
||||
MOCK_METHOD1(GetFdeFromIndex, const DwarfFde*(size_t));
|
||||
|
||||
MOCK_METHOD1(IsCie32, bool(uint32_t));
|
||||
|
||||
MOCK_METHOD1(IsCie64, bool(uint64_t));
|
||||
|
||||
MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t));
|
||||
|
||||
MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t));
|
||||
|
|
@ -57,112 +51,60 @@ class MockDwarfSection : public DwarfSection {
|
|||
|
||||
class DwarfSectionTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override { section_.reset(new MockDwarfSection(&memory_)); }
|
||||
|
||||
MemoryFake memory_;
|
||||
std::unique_ptr<MockDwarfSection> section_;
|
||||
};
|
||||
|
||||
TEST_F(DwarfSectionTest, GetFdeOffsetFromPc_fail_from_pc) {
|
||||
MockDwarfSection mock_section(&memory_);
|
||||
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
|
||||
.WillOnce(::testing::Return(false));
|
||||
|
||||
// Verify nullptr when GetFdeOffsetFromPc fails.
|
||||
ASSERT_TRUE(mock_section.GetFdeFromPc(0x1000) == nullptr);
|
||||
}
|
||||
|
||||
TEST_F(DwarfSectionTest, GetFdeOffsetFromPc_fail_fde_pc_end) {
|
||||
MockDwarfSection mock_section(&memory_);
|
||||
|
||||
DwarfFde fde{};
|
||||
fde.pc_end = 0x500;
|
||||
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
|
||||
|
||||
// Verify nullptr when GetFdeOffsetFromPc fails.
|
||||
ASSERT_TRUE(mock_section.GetFdeFromPc(0x1000) == nullptr);
|
||||
}
|
||||
|
||||
TEST_F(DwarfSectionTest, GetFdeOffsetFromPc_pass) {
|
||||
MockDwarfSection mock_section(&memory_);
|
||||
|
||||
DwarfFde fde{};
|
||||
fde.pc_end = 0x2000;
|
||||
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
|
||||
|
||||
// Verify nullptr when GetFdeOffsetFromPc fails.
|
||||
ASSERT_EQ(&fde, mock_section.GetFdeFromPc(0x1000));
|
||||
}
|
||||
|
||||
TEST_F(DwarfSectionTest, Step_fail_fde) {
|
||||
MockDwarfSection mock_section(&memory_);
|
||||
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
|
||||
.WillOnce(::testing::Return(false));
|
||||
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(nullptr));
|
||||
|
||||
bool finished;
|
||||
ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr, &finished));
|
||||
ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
|
||||
}
|
||||
|
||||
TEST_F(DwarfSectionTest, Step_fail_cie_null) {
|
||||
MockDwarfSection mock_section(&memory_);
|
||||
|
||||
DwarfFde fde{};
|
||||
fde.pc_end = 0x2000;
|
||||
fde.cie = nullptr;
|
||||
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
|
||||
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
|
||||
|
||||
bool finished;
|
||||
ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr, &finished));
|
||||
ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
|
||||
}
|
||||
|
||||
TEST_F(DwarfSectionTest, Step_fail_cfa_location) {
|
||||
MockDwarfSection mock_section(&memory_);
|
||||
|
||||
DwarfCie cie{};
|
||||
DwarfFde fde{};
|
||||
fde.pc_end = 0x2000;
|
||||
fde.cie = &cie;
|
||||
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
|
||||
|
||||
EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
|
||||
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
|
||||
EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
|
||||
.WillOnce(::testing::Return(false));
|
||||
|
||||
bool finished;
|
||||
ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr, &finished));
|
||||
ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
|
||||
}
|
||||
|
||||
TEST_F(DwarfSectionTest, Step_pass) {
|
||||
MockDwarfSection mock_section(&memory_);
|
||||
|
||||
DwarfCie cie{};
|
||||
DwarfFde fde{};
|
||||
fde.pc_end = 0x2000;
|
||||
fde.cie = &cie;
|
||||
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
|
||||
|
||||
EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
|
||||
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
|
||||
EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
|
||||
MemoryFake process;
|
||||
EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
|
||||
EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
|
||||
bool finished;
|
||||
ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
|
||||
}
|
||||
|
||||
static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde,
|
||||
|
|
@ -173,64 +115,53 @@ static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde,
|
|||
}
|
||||
|
||||
TEST_F(DwarfSectionTest, Step_cache) {
|
||||
MockDwarfSection mock_section(&memory_);
|
||||
|
||||
DwarfCie cie{};
|
||||
DwarfFde fde{};
|
||||
fde.pc_start = 0x500;
|
||||
fde.pc_end = 0x2000;
|
||||
fde.cie = &cie;
|
||||
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
|
||||
|
||||
EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
|
||||
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
|
||||
EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
|
||||
.WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
|
||||
|
||||
MemoryFake process;
|
||||
EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
|
||||
EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
|
||||
.WillRepeatedly(::testing::Return(true));
|
||||
|
||||
bool finished;
|
||||
ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(mock_section.Step(0x1500, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(section_->Step(0x1500, nullptr, &process, &finished));
|
||||
}
|
||||
|
||||
TEST_F(DwarfSectionTest, Step_cache_not_in_pc) {
|
||||
MockDwarfSection mock_section(&memory_);
|
||||
|
||||
DwarfCie cie{};
|
||||
DwarfFde fde0{};
|
||||
fde0.pc_start = 0x1000;
|
||||
fde0.pc_end = 0x2000;
|
||||
fde0.cie = &cie;
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde0));
|
||||
EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde0, ::testing::_))
|
||||
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde0));
|
||||
EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde0, ::testing::_))
|
||||
.WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
|
||||
|
||||
MemoryFake process;
|
||||
EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
|
||||
EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
|
||||
.WillRepeatedly(::testing::Return(true));
|
||||
|
||||
bool finished;
|
||||
ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
|
||||
|
||||
DwarfFde fde1{};
|
||||
fde1.pc_start = 0x500;
|
||||
fde1.pc_end = 0x800;
|
||||
fde1.cie = &cie;
|
||||
EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x600, ::testing::_))
|
||||
.WillOnce(::testing::Return(true));
|
||||
EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde1));
|
||||
EXPECT_CALL(mock_section, GetCfaLocationInfo(0x600, &fde1, ::testing::_))
|
||||
EXPECT_CALL(*section_, GetFdeFromPc(0x600)).WillOnce(::testing::Return(&fde1));
|
||||
EXPECT_CALL(*section_, GetCfaLocationInfo(0x600, &fde1, ::testing::_))
|
||||
.WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
|
||||
|
||||
ASSERT_TRUE(mock_section.Step(0x600, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(mock_section.Step(0x700, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(section_->Step(0x600, nullptr, &process, &finished));
|
||||
ASSERT_TRUE(section_->Step(0x700, nullptr, &process, &finished));
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
|||
|
|
@ -656,8 +656,7 @@ void ElfInterfaceTest::InitHeadersDebugFrame() {
|
|||
|
||||
memory_.SetData32(0x5000, 0xfc);
|
||||
memory_.SetData32(0x5004, 0xffffffff);
|
||||
memory_.SetData8(0x5008, 1);
|
||||
memory_.SetData8(0x5009, '\0');
|
||||
memory_.SetMemory(0x5008, std::vector<uint8_t>{1, '\0', 4, 8, 2});
|
||||
|
||||
memory_.SetData32(0x5100, 0xfc);
|
||||
memory_.SetData32(0x5104, 0);
|
||||
|
|
@ -678,56 +677,6 @@ TEST_F(ElfInterfaceTest, init_headers_debug_frame64) {
|
|||
InitHeadersDebugFrame<ElfInterface64Fake>();
|
||||
}
|
||||
|
||||
template <typename ElfType>
|
||||
void ElfInterfaceTest::InitHeadersEhFrameFail() {
|
||||
ElfType elf(&memory_);
|
||||
|
||||
elf.FakeSetEhFrameOffset(0x1000);
|
||||
elf.FakeSetEhFrameSize(0x100);
|
||||
elf.FakeSetDebugFrameOffset(0);
|
||||
elf.FakeSetDebugFrameSize(0);
|
||||
|
||||
elf.InitHeaders(0);
|
||||
|
||||
EXPECT_TRUE(elf.eh_frame() == nullptr);
|
||||
EXPECT_EQ(0U, elf.eh_frame_offset());
|
||||
EXPECT_EQ(static_cast<uint64_t>(-1), elf.eh_frame_size());
|
||||
EXPECT_TRUE(elf.debug_frame() == nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, init_headers_eh_frame32_fail) {
|
||||
InitHeadersEhFrameFail<ElfInterface32Fake>();
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, init_headers_eh_frame64_fail) {
|
||||
InitHeadersEhFrameFail<ElfInterface64Fake>();
|
||||
}
|
||||
|
||||
template <typename ElfType>
|
||||
void ElfInterfaceTest::InitHeadersDebugFrameFail() {
|
||||
ElfType elf(&memory_);
|
||||
|
||||
elf.FakeSetEhFrameOffset(0);
|
||||
elf.FakeSetEhFrameSize(0);
|
||||
elf.FakeSetDebugFrameOffset(0x1000);
|
||||
elf.FakeSetDebugFrameSize(0x100);
|
||||
|
||||
elf.InitHeaders(0);
|
||||
|
||||
EXPECT_TRUE(elf.eh_frame() == nullptr);
|
||||
EXPECT_TRUE(elf.debug_frame() == nullptr);
|
||||
EXPECT_EQ(0U, elf.debug_frame_offset());
|
||||
EXPECT_EQ(static_cast<uint64_t>(-1), elf.debug_frame_size());
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, init_headers_debug_frame32_fail) {
|
||||
InitHeadersDebugFrameFail<ElfInterface32Fake>();
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, init_headers_debug_frame64_fail) {
|
||||
InitHeadersDebugFrameFail<ElfInterface64Fake>();
|
||||
}
|
||||
|
||||
template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
|
||||
void ElfInterfaceTest::InitSectionHeadersMalformed() {
|
||||
std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
|
||||
|
|
@ -1024,11 +973,7 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_debug_frame) {
|
|||
// CIE 32.
|
||||
memory_.SetData32(0x600, 0xfc);
|
||||
memory_.SetData32(0x604, 0xffffffff);
|
||||
memory_.SetData8(0x608, 1);
|
||||
memory_.SetData8(0x609, '\0');
|
||||
memory_.SetData8(0x60a, 0x4);
|
||||
memory_.SetData8(0x60b, 0x4);
|
||||
memory_.SetData8(0x60c, 0x1);
|
||||
memory_.SetMemory(0x608, std::vector<uint8_t>{1, '\0', 4, 4, 1});
|
||||
|
||||
// FDE 32.
|
||||
memory_.SetData32(0x700, 0xfc);
|
||||
|
|
@ -1085,11 +1030,7 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_eh_frame) {
|
|||
// CIE 32.
|
||||
memory_.SetData32(0x600, 0xfc);
|
||||
memory_.SetData32(0x604, 0);
|
||||
memory_.SetData8(0x608, 1);
|
||||
memory_.SetData8(0x609, '\0');
|
||||
memory_.SetData8(0x60a, 0x4);
|
||||
memory_.SetData8(0x60b, 0x4);
|
||||
memory_.SetData8(0x60c, 0x1);
|
||||
memory_.SetMemory(0x608, std::vector<uint8_t>{1, '\0', 4, 4, 1});
|
||||
|
||||
// FDE 32.
|
||||
memory_.SetData32(0x700, 0xfc);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue