Merge "Handle when bias is different in elf headers."
This commit is contained in:
commit
c48c2afa1e
|
@ -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 New Issue