Handle when bias is different in elf headers.
The original code assumed that the load bias in the program headers would be exactly the same as in eh_frame/eh_frame_hdr/debug_frame. This isn't guaranteed, so add a section bias for use when creating a DwarfSection. In addtion, make the load bias and section bias a signed value. There is no reason that this value needs to be positive, so don't force it to be. Add a new offline test that has a different load bias in eh_frame than in the executable load. Add additional unit tests to verify the load bias values are set properly. Clean up the tests in ElfInterfaceTest, making all tests names follow the same convention. Bug: 141888859 Bug: 142094469 Test: New units and old unit tests pass on host and taimen. Change-Id: Ib878123ab5545f0f315c749cfe0d27b012d873ee
This commit is contained in:
parent
6c1668d660
commit
819f13116e
31 changed files with 651 additions and 237 deletions
|
@ -245,6 +245,7 @@ cc_defaults {
|
|||
"tests/files/offline/jit_debug_x86/*",
|
||||
"tests/files/offline/jit_map_arm/*",
|
||||
"tests/files/offline/gnu_debugdata_arm/*",
|
||||
"tests/files/offline/load_bias_different_section_bias_arm64/*",
|
||||
"tests/files/offline/load_bias_ro_rx_x86_64/*",
|
||||
"tests/files/offline/offset_arm/*",
|
||||
"tests/files/offline/shared_lib_in_apk_arm64/*",
|
||||
|
|
|
@ -32,8 +32,8 @@ static inline bool IsEncodingRelative(uint8_t encoding) {
|
|||
}
|
||||
|
||||
template <typename AddressType>
|
||||
bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint64_t load_bias) {
|
||||
load_bias_ = load_bias;
|
||||
bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, int64_t section_bias) {
|
||||
section_bias_ = section_bias;
|
||||
|
||||
memory_.clear_func_offset();
|
||||
memory_.clear_text_offset();
|
||||
|
@ -138,7 +138,7 @@ DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) {
|
|||
|
||||
// Relative encodings require adding in the load bias.
|
||||
if (IsEncodingRelative(table_encoding_)) {
|
||||
value += load_bias_;
|
||||
value += section_bias_;
|
||||
}
|
||||
info->pc = value;
|
||||
return info;
|
||||
|
|
|
@ -38,7 +38,7 @@ class DwarfEhFrameWithHdr : public DwarfSectionImpl<AddressType> {
|
|||
using DwarfSectionImpl<AddressType>::entries_offset_;
|
||||
using DwarfSectionImpl<AddressType>::entries_end_;
|
||||
using DwarfSectionImpl<AddressType>::last_error_;
|
||||
using DwarfSectionImpl<AddressType>::load_bias_;
|
||||
using DwarfSectionImpl<AddressType>::section_bias_;
|
||||
|
||||
struct FdeInfo {
|
||||
AddressType pc;
|
||||
|
@ -61,7 +61,7 @@ class DwarfEhFrameWithHdr : public DwarfSectionImpl<AddressType> {
|
|||
return pc + this->memory_.cur_offset() - 4;
|
||||
}
|
||||
|
||||
bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
|
||||
bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
|
||||
|
||||
const DwarfFde* GetFdeFromPc(uint64_t pc) override;
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ bool DwarfMemory::AdjustEncodedValue(uint8_t encoding, uint64_t* value) {
|
|||
// Nothing to do.
|
||||
break;
|
||||
case DW_EH_PE_pcrel:
|
||||
if (pc_offset_ == static_cast<uint64_t>(-1)) {
|
||||
if (pc_offset_ == INT64_MAX) {
|
||||
// Unsupported encoding.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -333,7 +333,7 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
|
|||
memory_.set_cur_offset(cur_offset);
|
||||
|
||||
// The load bias only applies to the start.
|
||||
memory_.set_pc_offset(load_bias_);
|
||||
memory_.set_pc_offset(section_bias_);
|
||||
bool valid = memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_start);
|
||||
fde->pc_start = AdjustPcFromFde(fde->pc_start);
|
||||
|
||||
|
@ -591,8 +591,9 @@ bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const Dwarf
|
|||
}
|
||||
|
||||
template <typename AddressType>
|
||||
bool DwarfSectionImplNoHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint64_t load_bias) {
|
||||
load_bias_ = load_bias;
|
||||
bool DwarfSectionImplNoHdr<AddressType>::Init(uint64_t offset, uint64_t size,
|
||||
int64_t section_bias) {
|
||||
section_bias_ = section_bias;
|
||||
entries_offset_ = offset;
|
||||
next_entries_offset_ = offset;
|
||||
entries_end_ = offset + size;
|
||||
|
|
|
@ -53,7 +53,7 @@ bool Elf::Init() {
|
|||
|
||||
valid_ = interface_->Init(&load_bias_);
|
||||
if (valid_) {
|
||||
interface_->InitHeaders(load_bias_);
|
||||
interface_->InitHeaders();
|
||||
InitGnuDebugdata();
|
||||
} else {
|
||||
interface_.reset(nullptr);
|
||||
|
@ -77,9 +77,9 @@ void Elf::InitGnuDebugdata() {
|
|||
|
||||
// Ignore the load_bias from the compressed section, the correct load bias
|
||||
// is in the uncompressed data.
|
||||
uint64_t load_bias;
|
||||
int64_t load_bias;
|
||||
if (gnu->Init(&load_bias)) {
|
||||
gnu->InitHeaders(load_bias);
|
||||
gnu->InitHeaders();
|
||||
interface_->SetGnuDebugdataInterface(gnu);
|
||||
} else {
|
||||
// Free all of the memory associated with the gnu_debugdata section.
|
||||
|
@ -124,7 +124,7 @@ bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) {
|
|||
}
|
||||
|
||||
// Adjust by the load bias.
|
||||
if (*memory_address < load_bias_) {
|
||||
if (load_bias_ > 0 && *memory_address < static_cast<uint64_t>(load_bias_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,7 @@ bool Elf::GetInfo(Memory* memory, uint64_t* size) {
|
|||
}
|
||||
|
||||
bool Elf::IsValidPc(uint64_t pc) {
|
||||
if (!valid_ || pc < load_bias_) {
|
||||
if (!valid_ || (load_bias_ > 0 && pc < static_cast<uint64_t>(load_bias_))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
|
|||
return interface.release();
|
||||
}
|
||||
|
||||
uint64_t Elf::GetLoadBias(Memory* memory) {
|
||||
int64_t Elf::GetLoadBias(Memory* memory) {
|
||||
if (!IsValidElf(memory)) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -124,10 +124,10 @@ Memory* ElfInterface::CreateGnuDebugdataMemory() {
|
|||
}
|
||||
|
||||
template <typename AddressType>
|
||||
void ElfInterface::InitHeadersWithTemplate(uint64_t load_bias) {
|
||||
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_, load_bias)) {
|
||||
if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, eh_frame_hdr_section_bias_)) {
|
||||
eh_frame_.reset(nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -136,21 +136,23 @@ void ElfInterface::InitHeadersWithTemplate(uint64_t load_bias) {
|
|||
// If there is an eh_frame section without an eh_frame_hdr section,
|
||||
// or using the frame hdr object failed to init.
|
||||
eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
|
||||
if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, load_bias)) {
|
||||
if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, eh_frame_section_bias_)) {
|
||||
eh_frame_.reset(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (eh_frame_.get() == nullptr) {
|
||||
eh_frame_hdr_offset_ = 0;
|
||||
eh_frame_hdr_section_bias_ = 0;
|
||||
eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
|
||||
eh_frame_offset_ = 0;
|
||||
eh_frame_section_bias_ = 0;
|
||||
eh_frame_size_ = static_cast<uint64_t>(-1);
|
||||
}
|
||||
|
||||
if (debug_frame_offset_ != 0) {
|
||||
debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
|
||||
if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, load_bias)) {
|
||||
if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, debug_frame_section_bias_)) {
|
||||
debug_frame_.reset(nullptr);
|
||||
debug_frame_offset_ = 0;
|
||||
debug_frame_size_ = static_cast<uint64_t>(-1);
|
||||
|
@ -159,7 +161,7 @@ void ElfInterface::InitHeadersWithTemplate(uint64_t load_bias) {
|
|||
}
|
||||
|
||||
template <typename EhdrType, typename PhdrType, typename ShdrType>
|
||||
bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
|
||||
bool ElfInterface::ReadAllHeaders(int64_t* load_bias) {
|
||||
EhdrType ehdr;
|
||||
if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
|
||||
last_error_.code = ERROR_MEMORY_INVALID;
|
||||
|
@ -175,7 +177,7 @@ bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
|
|||
}
|
||||
|
||||
template <typename EhdrType, typename PhdrType>
|
||||
uint64_t ElfInterface::GetLoadBias(Memory* memory) {
|
||||
int64_t ElfInterface::GetLoadBias(Memory* memory) {
|
||||
EhdrType ehdr;
|
||||
if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
|
||||
return false;
|
||||
|
@ -190,17 +192,14 @@ uint64_t ElfInterface::GetLoadBias(Memory* memory) {
|
|||
|
||||
// Find the first executable load when looking for the load bias.
|
||||
if (phdr.p_type == PT_LOAD && (phdr.p_flags & PF_X)) {
|
||||
if (phdr.p_vaddr > phdr.p_offset) {
|
||||
return phdr.p_vaddr - phdr.p_offset;
|
||||
}
|
||||
break;
|
||||
return static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename EhdrType, typename PhdrType>
|
||||
void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
|
||||
void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias) {
|
||||
uint64_t offset = ehdr.e_phoff;
|
||||
bool first_exec_load_header = true;
|
||||
for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
|
||||
|
@ -219,8 +218,8 @@ void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
|
|||
pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
|
||||
static_cast<size_t>(phdr.p_memsz)};
|
||||
// Only set the load bias from the first executable load header.
|
||||
if (first_exec_load_header && phdr.p_vaddr > phdr.p_offset) {
|
||||
*load_bias = phdr.p_vaddr - phdr.p_offset;
|
||||
if (first_exec_load_header) {
|
||||
*load_bias = static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
|
||||
}
|
||||
first_exec_load_header = false;
|
||||
break;
|
||||
|
@ -229,6 +228,7 @@ void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
|
|||
case PT_GNU_EH_FRAME:
|
||||
// This is really the pointer to the .eh_frame_hdr section.
|
||||
eh_frame_hdr_offset_ = phdr.p_offset;
|
||||
eh_frame_hdr_section_bias_ = static_cast<uint64_t>(phdr.p_paddr) - phdr.p_offset;
|
||||
eh_frame_hdr_size_ = phdr.p_memsz;
|
||||
break;
|
||||
|
||||
|
@ -343,24 +343,21 @@ void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
|
|||
if (shdr.sh_name < sec_size) {
|
||||
std::string name;
|
||||
if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
|
||||
uint64_t* offset_ptr = nullptr;
|
||||
uint64_t* size_ptr = nullptr;
|
||||
if (name == ".debug_frame") {
|
||||
offset_ptr = &debug_frame_offset_;
|
||||
size_ptr = &debug_frame_size_;
|
||||
debug_frame_offset_ = shdr.sh_offset;
|
||||
debug_frame_size_ = shdr.sh_size;
|
||||
debug_frame_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
|
||||
} else if (name == ".gnu_debugdata") {
|
||||
offset_ptr = &gnu_debugdata_offset_;
|
||||
size_ptr = &gnu_debugdata_size_;
|
||||
gnu_debugdata_offset_ = shdr.sh_offset;
|
||||
gnu_debugdata_size_ = shdr.sh_size;
|
||||
} else if (name == ".eh_frame") {
|
||||
offset_ptr = &eh_frame_offset_;
|
||||
size_ptr = &eh_frame_size_;
|
||||
eh_frame_offset_ = shdr.sh_offset;
|
||||
eh_frame_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
|
||||
eh_frame_size_ = shdr.sh_size;
|
||||
} else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
|
||||
offset_ptr = &eh_frame_hdr_offset_;
|
||||
size_ptr = &eh_frame_hdr_size_;
|
||||
}
|
||||
if (offset_ptr != nullptr) {
|
||||
*offset_ptr = shdr.sh_offset;
|
||||
*size_ptr = shdr.sh_size;
|
||||
eh_frame_hdr_offset_ = shdr.sh_offset;
|
||||
eh_frame_hdr_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
|
||||
eh_frame_hdr_size_ = shdr.sh_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -642,16 +639,14 @@ std::string ElfInterface::ReadBuildIDFromMemory(Memory* memory) {
|
|||
}
|
||||
|
||||
// Instantiate all of the needed template functions.
|
||||
template void ElfInterface::InitHeadersWithTemplate<uint32_t>(uint64_t);
|
||||
template void ElfInterface::InitHeadersWithTemplate<uint64_t>(uint64_t);
|
||||
template void ElfInterface::InitHeadersWithTemplate<uint32_t>();
|
||||
template void ElfInterface::InitHeadersWithTemplate<uint64_t>();
|
||||
|
||||
template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*);
|
||||
template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*);
|
||||
template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(int64_t*);
|
||||
template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(int64_t*);
|
||||
|
||||
template void ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&,
|
||||
uint64_t*);
|
||||
template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&,
|
||||
uint64_t*);
|
||||
template void ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, int64_t*);
|
||||
template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, int64_t*);
|
||||
|
||||
template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
|
||||
template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
|
||||
|
@ -673,8 +668,8 @@ template bool ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(const std::
|
|||
template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*);
|
||||
template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*);
|
||||
|
||||
template uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
|
||||
template uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
|
||||
template int64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
|
||||
template int64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
|
||||
|
||||
template std::string ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(
|
||||
Memory*);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
namespace unwindstack {
|
||||
|
||||
bool ElfInterfaceArm::Init(uint64_t* load_bias) {
|
||||
bool ElfInterfaceArm::Init(int64_t* load_bias) {
|
||||
if (!ElfInterface32::Init(load_bias)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ class ElfInterfaceArm : public ElfInterface32 {
|
|||
iterator begin() { return iterator(this, 0); }
|
||||
iterator end() { return iterator(this, total_entries_); }
|
||||
|
||||
bool Init(uint64_t* load_bias) override;
|
||||
bool Init(int64_t* section_bias) override;
|
||||
|
||||
bool GetPrel31Addr(uint32_t offset, uint32_t* addr);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
@ -263,8 +264,8 @@ bool MapInfo::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_o
|
|||
}
|
||||
|
||||
uint64_t MapInfo::GetLoadBias(const std::shared_ptr<Memory>& process_memory) {
|
||||
uint64_t cur_load_bias = load_bias.load();
|
||||
if (cur_load_bias != static_cast<uint64_t>(-1)) {
|
||||
int64_t cur_load_bias = load_bias.load();
|
||||
if (cur_load_bias != INT64_MAX) {
|
||||
return cur_load_bias;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ class DwarfMemory {
|
|||
uint64_t cur_offset() { return cur_offset_; }
|
||||
void set_cur_offset(uint64_t cur_offset) { cur_offset_ = cur_offset; }
|
||||
|
||||
void set_pc_offset(uint64_t offset) { pc_offset_ = offset; }
|
||||
void clear_pc_offset() { pc_offset_ = static_cast<uint64_t>(-1); }
|
||||
void set_pc_offset(int64_t offset) { pc_offset_ = offset; }
|
||||
void clear_pc_offset() { pc_offset_ = INT64_MAX; }
|
||||
|
||||
void set_data_offset(uint64_t offset) { data_offset_ = offset; }
|
||||
void clear_data_offset() { data_offset_ = static_cast<uint64_t>(-1); }
|
||||
|
@ -65,7 +65,7 @@ class DwarfMemory {
|
|||
Memory* memory_;
|
||||
uint64_t cur_offset_ = 0;
|
||||
|
||||
uint64_t pc_offset_ = static_cast<uint64_t>(-1);
|
||||
int64_t pc_offset_ = INT64_MAX;
|
||||
uint64_t data_offset_ = static_cast<uint64_t>(-1);
|
||||
uint64_t func_offset_ = static_cast<uint64_t>(-1);
|
||||
uint64_t text_offset_ = static_cast<uint64_t>(-1);
|
||||
|
|
|
@ -86,7 +86,7 @@ class DwarfSection {
|
|||
DwarfErrorCode LastErrorCode() { return last_error_.code; }
|
||||
uint64_t LastErrorAddress() { return last_error_.address; }
|
||||
|
||||
virtual bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) = 0;
|
||||
virtual bool Init(uint64_t offset, uint64_t size, int64_t section_bias) = 0;
|
||||
|
||||
virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
|
||||
|
||||
|
@ -150,7 +150,7 @@ class DwarfSectionImpl : public DwarfSection {
|
|||
bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
|
||||
RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
|
||||
|
||||
uint64_t load_bias_ = 0;
|
||||
int64_t section_bias_ = 0;
|
||||
uint64_t entries_offset_ = 0;
|
||||
uint64_t entries_end_ = 0;
|
||||
uint64_t pc_offset_ = 0;
|
||||
|
@ -166,7 +166,7 @@ class DwarfSectionImplNoHdr : public DwarfSectionImpl<AddressType> {
|
|||
using DwarfSectionImpl<AddressType>::entries_offset_;
|
||||
using DwarfSectionImpl<AddressType>::entries_end_;
|
||||
using DwarfSectionImpl<AddressType>::last_error_;
|
||||
using DwarfSectionImpl<AddressType>::load_bias_;
|
||||
using DwarfSectionImpl<AddressType>::section_bias_;
|
||||
using DwarfSectionImpl<AddressType>::cie_entries_;
|
||||
using DwarfSectionImpl<AddressType>::fde_entries_;
|
||||
using DwarfSectionImpl<AddressType>::cie32_value_;
|
||||
|
@ -175,7 +175,7 @@ class DwarfSectionImplNoHdr : public DwarfSectionImpl<AddressType> {
|
|||
DwarfSectionImplNoHdr(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
|
||||
virtual ~DwarfSectionImplNoHdr() = default;
|
||||
|
||||
bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
|
||||
bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
|
||||
|
||||
const DwarfFde* GetFdeFromPc(uint64_t pc) override;
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ class Elf {
|
|||
|
||||
std::string GetBuildID();
|
||||
|
||||
uint64_t GetLoadBias() { return load_bias_; }
|
||||
int64_t GetLoadBias() { return load_bias_; }
|
||||
|
||||
bool IsValidPc(uint64_t pc);
|
||||
|
||||
|
@ -101,7 +101,7 @@ class Elf {
|
|||
|
||||
static bool GetInfo(Memory* memory, uint64_t* size);
|
||||
|
||||
static uint64_t GetLoadBias(Memory* memory);
|
||||
static int64_t GetLoadBias(Memory* memory);
|
||||
|
||||
static std::string GetBuildID(Memory* memory);
|
||||
|
||||
|
@ -116,7 +116,7 @@ class Elf {
|
|||
|
||||
protected:
|
||||
bool valid_ = false;
|
||||
uint64_t load_bias_ = 0;
|
||||
int64_t load_bias_ = 0;
|
||||
std::unique_ptr<ElfInterface> interface_;
|
||||
std::unique_ptr<Memory> memory_;
|
||||
uint32_t machine_type_;
|
||||
|
|
|
@ -52,9 +52,9 @@ class ElfInterface {
|
|||
ElfInterface(Memory* memory) : memory_(memory) {}
|
||||
virtual ~ElfInterface();
|
||||
|
||||
virtual bool Init(uint64_t* load_bias) = 0;
|
||||
virtual bool Init(int64_t* load_bias) = 0;
|
||||
|
||||
virtual void InitHeaders(uint64_t load_bias) = 0;
|
||||
virtual void InitHeaders() = 0;
|
||||
|
||||
virtual std::string GetSoname() = 0;
|
||||
|
||||
|
@ -80,10 +80,13 @@ class ElfInterface {
|
|||
uint64_t dynamic_vaddr() { return dynamic_vaddr_; }
|
||||
uint64_t dynamic_size() { return dynamic_size_; }
|
||||
uint64_t eh_frame_hdr_offset() { return eh_frame_hdr_offset_; }
|
||||
int64_t eh_frame_hdr_section_bias() { return eh_frame_hdr_section_bias_; }
|
||||
uint64_t eh_frame_hdr_size() { return eh_frame_hdr_size_; }
|
||||
uint64_t eh_frame_offset() { return eh_frame_offset_; }
|
||||
int64_t eh_frame_section_bias() { return eh_frame_section_bias_; }
|
||||
uint64_t eh_frame_size() { return eh_frame_size_; }
|
||||
uint64_t debug_frame_offset() { return debug_frame_offset_; }
|
||||
int64_t debug_frame_section_bias() { return debug_frame_section_bias_; }
|
||||
uint64_t debug_frame_size() { return debug_frame_size_; }
|
||||
uint64_t gnu_debugdata_offset() { return gnu_debugdata_offset_; }
|
||||
uint64_t gnu_debugdata_size() { return gnu_debugdata_size_; }
|
||||
|
@ -98,20 +101,20 @@ class ElfInterface {
|
|||
uint64_t LastErrorAddress() { return last_error_.address; }
|
||||
|
||||
template <typename EhdrType, typename PhdrType>
|
||||
static uint64_t GetLoadBias(Memory* memory);
|
||||
static int64_t GetLoadBias(Memory* memory);
|
||||
|
||||
template <typename EhdrType, typename ShdrType, typename NhdrType>
|
||||
static std::string ReadBuildIDFromMemory(Memory* memory);
|
||||
|
||||
protected:
|
||||
template <typename AddressType>
|
||||
void InitHeadersWithTemplate(uint64_t load_bias);
|
||||
void InitHeadersWithTemplate();
|
||||
|
||||
template <typename EhdrType, typename PhdrType, typename ShdrType>
|
||||
bool ReadAllHeaders(uint64_t* load_bias);
|
||||
bool ReadAllHeaders(int64_t* load_bias);
|
||||
|
||||
template <typename EhdrType, typename PhdrType>
|
||||
void ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias);
|
||||
void ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias);
|
||||
|
||||
template <typename EhdrType, typename ShdrType>
|
||||
void ReadSectionHeaders(const EhdrType& ehdr);
|
||||
|
@ -142,12 +145,15 @@ class ElfInterface {
|
|||
uint64_t dynamic_size_ = 0;
|
||||
|
||||
uint64_t eh_frame_hdr_offset_ = 0;
|
||||
int64_t eh_frame_hdr_section_bias_ = 0;
|
||||
uint64_t eh_frame_hdr_size_ = 0;
|
||||
|
||||
uint64_t eh_frame_offset_ = 0;
|
||||
int64_t eh_frame_section_bias_ = 0;
|
||||
uint64_t eh_frame_size_ = 0;
|
||||
|
||||
uint64_t debug_frame_offset_ = 0;
|
||||
int64_t debug_frame_section_bias_ = 0;
|
||||
uint64_t debug_frame_size_ = 0;
|
||||
|
||||
uint64_t gnu_debugdata_offset_ = 0;
|
||||
|
@ -175,13 +181,11 @@ class ElfInterface32 : public ElfInterface {
|
|||
ElfInterface32(Memory* memory) : ElfInterface(memory) {}
|
||||
virtual ~ElfInterface32() = default;
|
||||
|
||||
bool Init(uint64_t* load_bias) override {
|
||||
bool Init(int64_t* load_bias) override {
|
||||
return ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(load_bias);
|
||||
}
|
||||
|
||||
void InitHeaders(uint64_t load_bias) override {
|
||||
ElfInterface::InitHeadersWithTemplate<uint32_t>(load_bias);
|
||||
}
|
||||
void InitHeaders() override { ElfInterface::InitHeadersWithTemplate<uint32_t>(); }
|
||||
|
||||
std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(); }
|
||||
|
||||
|
@ -205,13 +209,11 @@ class ElfInterface64 : public ElfInterface {
|
|||
ElfInterface64(Memory* memory) : ElfInterface(memory) {}
|
||||
virtual ~ElfInterface64() = default;
|
||||
|
||||
bool Init(uint64_t* load_bias) override {
|
||||
bool Init(int64_t* load_bias) override {
|
||||
return ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(load_bias);
|
||||
}
|
||||
|
||||
void InitHeaders(uint64_t load_bias) override {
|
||||
ElfInterface::InitHeadersWithTemplate<uint64_t>(load_bias);
|
||||
}
|
||||
void InitHeaders() override { ElfInterface::InitHeadersWithTemplate<uint64_t>(); }
|
||||
|
||||
std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(); }
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ struct MapInfo {
|
|||
flags(flags),
|
||||
name(name),
|
||||
prev_map(map_info),
|
||||
load_bias(static_cast<uint64_t>(-1)),
|
||||
load_bias(INT64_MAX),
|
||||
build_id(0) {}
|
||||
MapInfo(MapInfo* map_info, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
|
||||
const std::string& name)
|
||||
|
@ -49,7 +49,7 @@ struct MapInfo {
|
|||
flags(flags),
|
||||
name(name),
|
||||
prev_map(map_info),
|
||||
load_bias(static_cast<uint64_t>(-1)),
|
||||
load_bias(INT64_MAX),
|
||||
build_id(0) {}
|
||||
~MapInfo();
|
||||
|
||||
|
@ -72,7 +72,7 @@ struct MapInfo {
|
|||
|
||||
MapInfo* prev_map = nullptr;
|
||||
|
||||
std::atomic_uint64_t load_bias;
|
||||
std::atomic_int64_t load_bias;
|
||||
|
||||
// This is a pointer to a new'd std::string.
|
||||
// Using an atomic value means that we don't need to lock and will
|
||||
|
|
|
@ -35,7 +35,7 @@ class TestDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
|
|||
TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
|
||||
virtual ~TestDwarfSectionImpl() = default;
|
||||
|
||||
bool Init(uint64_t, uint64_t, uint64_t) override { return false; }
|
||||
bool Init(uint64_t, uint64_t, int64_t) override { return false; }
|
||||
|
||||
void GetFdes(std::vector<const DwarfFde*>*) override {}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class MockDwarfSection : public DwarfSection {
|
|||
MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
|
||||
virtual ~MockDwarfSection() = default;
|
||||
|
||||
MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t));
|
||||
MOCK_METHOD3(Init, bool(uint64_t, uint64_t, int64_t));
|
||||
|
||||
MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*));
|
||||
|
||||
|
|
|
@ -66,8 +66,8 @@ class ElfInterfaceFake : public ElfInterface {
|
|||
ElfInterfaceFake(Memory* memory) : ElfInterface(memory) {}
|
||||
virtual ~ElfInterfaceFake() = default;
|
||||
|
||||
bool Init(uint64_t*) override { return false; }
|
||||
void InitHeaders(uint64_t) override {}
|
||||
bool Init(int64_t*) override { return false; }
|
||||
void InitHeaders() override {}
|
||||
std::string GetSoname() override { return fake_soname_; }
|
||||
|
||||
bool GetFunctionName(uint64_t, std::string*, uint64_t*) override;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -310,8 +310,8 @@ class ElfInterfaceMock : public ElfInterface {
|
|||
ElfInterfaceMock(Memory* memory) : ElfInterface(memory) {}
|
||||
virtual ~ElfInterfaceMock() = default;
|
||||
|
||||
bool Init(uint64_t*) override { return false; }
|
||||
void InitHeaders(uint64_t) override {}
|
||||
bool Init(int64_t*) override { return false; }
|
||||
void InitHeaders() override {}
|
||||
std::string GetSoname() override { return ""; }
|
||||
bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; }
|
||||
std::string GetBuildID() override { return ""; }
|
||||
|
|
|
@ -84,7 +84,7 @@ TEST_F(MapInfoGetLoadBiasTest, elf_exists) {
|
|||
elf_->FakeSetLoadBias(0);
|
||||
EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_));
|
||||
|
||||
map_info_->load_bias = static_cast<uint64_t>(-1);
|
||||
map_info_->load_bias = INT64_MAX;
|
||||
elf_->FakeSetLoadBias(0x1000);
|
||||
EXPECT_EQ(0x1000U, map_info_->GetLoadBias(process_memory_));
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ TEST(MapInfoTest, maps_constructor_const_char) {
|
|||
EXPECT_EQ(3UL, map_info.offset);
|
||||
EXPECT_EQ(4UL, map_info.flags);
|
||||
EXPECT_EQ("map", map_info.name);
|
||||
EXPECT_EQ(static_cast<uint64_t>(-1), map_info.load_bias);
|
||||
EXPECT_EQ(INT64_MAX, map_info.load_bias);
|
||||
EXPECT_EQ(0UL, map_info.elf_offset);
|
||||
EXPECT_TRUE(map_info.elf.get() == nullptr);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ TEST(MapInfoTest, maps_constructor_string) {
|
|||
EXPECT_EQ(3UL, map_info.offset);
|
||||
EXPECT_EQ(4UL, map_info.flags);
|
||||
EXPECT_EQ("string_map", map_info.name);
|
||||
EXPECT_EQ(static_cast<uint64_t>(-1), map_info.load_bias);
|
||||
EXPECT_EQ(INT64_MAX, map_info.load_bias);
|
||||
EXPECT_EQ(0UL, map_info.elf_offset);
|
||||
EXPECT_TRUE(map_info.elf.get() == nullptr);
|
||||
}
|
||||
|
|
|
@ -1534,4 +1534,53 @@ TEST_F(UnwindOfflineTest, load_bias_ro_rx_x86_64) {
|
|||
EXPECT_EQ(0x7ffd22415e90ULL, unwinder.frames()[16].sp);
|
||||
}
|
||||
|
||||
TEST_F(UnwindOfflineTest, load_bias_different_section_bias_arm64) {
|
||||
ASSERT_NO_FATAL_FAILURE(Init("load_bias_different_section_bias_arm64/", ARCH_ARM64));
|
||||
|
||||
Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
|
||||
unwinder.Unwind();
|
||||
|
||||
std::string frame_info(DumpFrames(unwinder));
|
||||
ASSERT_EQ(12U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
|
||||
EXPECT_EQ(
|
||||
" #00 pc 00000000000d59bc linker64 (__dl_syscall+28)\n"
|
||||
" #01 pc 00000000000554e8 linker64 (__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1148)\n"
|
||||
" #02 pc 00000000000008c0 vdso (__kernel_rt_sigreturn)\n"
|
||||
" #03 pc 000000000007f3e8 libc.so (abort+168)\n"
|
||||
" #04 pc 00000000000459fc test (std::__ndk1::__throw_bad_cast()+4)\n"
|
||||
" #05 pc 0000000000056d80 test (testing::Test::Run()+88)\n"
|
||||
" #06 pc 000000000005724c test (testing::TestInfo::Run()+112)\n"
|
||||
" #07 pc 0000000000057558 test (testing::TestSuite::Run()+116)\n"
|
||||
" #08 pc 000000000005bffc test (testing::internal::UnitTestImpl::RunAllTests()+464)\n"
|
||||
" #09 pc 000000000005bd9c test (testing::UnitTest::Run()+116)\n"
|
||||
" #10 pc 00000000000464e4 test (main+144)\n"
|
||||
" #11 pc 000000000007aa34 libc.so (__libc_init+108)\n",
|
||||
frame_info);
|
||||
|
||||
EXPECT_EQ(0x7112cb99bcULL, unwinder.frames()[0].pc);
|
||||
EXPECT_EQ(0x7112bdbbf0ULL, unwinder.frames()[0].sp);
|
||||
EXPECT_EQ(0x7112c394e8ULL, unwinder.frames()[1].pc);
|
||||
EXPECT_EQ(0x7112bdbbf0ULL, unwinder.frames()[1].sp);
|
||||
EXPECT_EQ(0x7112be28c0ULL, unwinder.frames()[2].pc);
|
||||
EXPECT_EQ(0x7112bdbda0ULL, unwinder.frames()[2].sp);
|
||||
EXPECT_EQ(0x71115ab3e8ULL, unwinder.frames()[3].pc);
|
||||
EXPECT_EQ(0x7fdd4a3f00ULL, unwinder.frames()[3].sp);
|
||||
EXPECT_EQ(0x5f739dc9fcULL, unwinder.frames()[4].pc);
|
||||
EXPECT_EQ(0x7fdd4a3fe0ULL, unwinder.frames()[4].sp);
|
||||
EXPECT_EQ(0x5f739edd80ULL, unwinder.frames()[5].pc);
|
||||
EXPECT_EQ(0x7fdd4a3ff0ULL, unwinder.frames()[5].sp);
|
||||
EXPECT_EQ(0x5f739ee24cULL, unwinder.frames()[6].pc);
|
||||
EXPECT_EQ(0x7fdd4a4010ULL, unwinder.frames()[6].sp);
|
||||
EXPECT_EQ(0x5f739ee558ULL, unwinder.frames()[7].pc);
|
||||
EXPECT_EQ(0x7fdd4a4040ULL, unwinder.frames()[7].sp);
|
||||
EXPECT_EQ(0x5f739f2ffcULL, unwinder.frames()[8].pc);
|
||||
EXPECT_EQ(0x7fdd4a4070ULL, unwinder.frames()[8].sp);
|
||||
EXPECT_EQ(0x5f739f2d9cULL, unwinder.frames()[9].pc);
|
||||
EXPECT_EQ(0x7fdd4a4100ULL, unwinder.frames()[9].sp);
|
||||
EXPECT_EQ(0x5f739dd4e4ULL, unwinder.frames()[10].pc);
|
||||
EXPECT_EQ(0x7fdd4a4130ULL, unwinder.frames()[10].sp);
|
||||
EXPECT_EQ(0x71115a6a34ULL, unwinder.frames()[11].pc);
|
||||
EXPECT_EQ(0x7fdd4a4170ULL, unwinder.frames()[11].sp);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
5f73997000-5f739dc000 r--p 0 00:00 0 test
|
||||
5f739dc000-5f73a43000 r-xp 44000 00:00 0 test
|
||||
711152c000-711156e000 r--p 0 00:00 0 libc.so
|
||||
711156e000-7111611000 --xp 42000 00:00 0 libc.so
|
||||
7112be2000-7112be4000 r-xp 0 00:00 0 vdso
|
||||
7112be4000-7112c1c000 r--p 0 00:00 0 linker64
|
||||
7112c1c000-7112ce1000 r-xp 38000 00:00 0 linker64
|
|
@ -0,0 +1,33 @@
|
|||
x0: 7112bdbc24
|
||||
x1: 0
|
||||
x2: ffffffff
|
||||
x3: 0
|
||||
x4: 0
|
||||
x5: 0
|
||||
x6: 0
|
||||
x7: 7f7f7f7f7f7f7f7f
|
||||
x8: 62
|
||||
x9: a78826643b37f4a1
|
||||
x10: 7112bdbc20
|
||||
x11: 4100
|
||||
x12: 7112bdbb70
|
||||
x13: 18
|
||||
x14: 1d6518077
|
||||
x15: 2a43148faf732a
|
||||
x16: 16fc0
|
||||
x17: 71115f61a0
|
||||
x18: 7111d6a000
|
||||
x19: 7112cef1b0
|
||||
x20: 7112bdbda0
|
||||
x21: 59616d61
|
||||
x22: 1
|
||||
x23: 7112bdbc24
|
||||
x24: 4b0e
|
||||
x25: 62
|
||||
x26: 2
|
||||
x27: 0
|
||||
x28: 7111934020
|
||||
x29: 7112bdbd90
|
||||
sp: 7112bdbbf0
|
||||
lr: 7112c394ec
|
||||
pc: 7112cb99bc
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue