Merge "Handle when bias is different in elf headers."

This commit is contained in:
Christopher Ferris 2019-10-08 17:41:25 +00:00 committed by Gerrit Code Review
commit c48c2afa1e
31 changed files with 651 additions and 237 deletions

View File

@ -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/*",

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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*);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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_;

View File

@ -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>(); }

View File

@ -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

View File

@ -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 {}

View File

@ -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*));

View File

@ -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

View File

@ -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 ""; }

View File

@ -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_));
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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