diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index 8d2299fcb..b0f37867f 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp @@ -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/*", diff --git a/libunwindstack/DwarfEhFrameWithHdr.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp index 802beca85..24b94f0b3 100644 --- a/libunwindstack/DwarfEhFrameWithHdr.cpp +++ b/libunwindstack/DwarfEhFrameWithHdr.cpp @@ -32,8 +32,8 @@ static inline bool IsEncodingRelative(uint8_t encoding) { } template -bool DwarfEhFrameWithHdr::Init(uint64_t offset, uint64_t size, uint64_t load_bias) { - load_bias_ = load_bias; +bool DwarfEhFrameWithHdr::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::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; diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h index 0e5eef720..b8dd3dd40 100644 --- a/libunwindstack/DwarfEhFrameWithHdr.h +++ b/libunwindstack/DwarfEhFrameWithHdr.h @@ -38,7 +38,7 @@ class DwarfEhFrameWithHdr : public DwarfSectionImpl { using DwarfSectionImpl::entries_offset_; using DwarfSectionImpl::entries_end_; using DwarfSectionImpl::last_error_; - using DwarfSectionImpl::load_bias_; + using DwarfSectionImpl::section_bias_; struct FdeInfo { AddressType pc; @@ -61,7 +61,7 @@ class DwarfEhFrameWithHdr : public DwarfSectionImpl { 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; diff --git a/libunwindstack/DwarfMemory.cpp b/libunwindstack/DwarfMemory.cpp index b5059007c..2e388c689 100644 --- a/libunwindstack/DwarfMemory.cpp +++ b/libunwindstack/DwarfMemory.cpp @@ -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(-1)) { + if (pc_offset_ == INT64_MAX) { // Unsupported encoding. return false; } diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp index 849a31a90..cdb61413b 100644 --- a/libunwindstack/DwarfSection.cpp +++ b/libunwindstack/DwarfSection.cpp @@ -333,7 +333,7 @@ bool DwarfSectionImpl::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(cie->fde_address_encoding, &fde->pc_start); fde->pc_start = AdjustPcFromFde(fde->pc_start); @@ -591,8 +591,9 @@ bool DwarfSectionImpl::Log(uint8_t indent, uint64_t pc, const Dwarf } template -bool DwarfSectionImplNoHdr::Init(uint64_t offset, uint64_t size, uint64_t load_bias) { - load_bias_ = load_bias; +bool DwarfSectionImplNoHdr::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; diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp index 345491356..c141b2e00 100644 --- a/libunwindstack/Elf.cpp +++ b/libunwindstack/Elf.cpp @@ -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(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(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; } diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp index be1f09260..e34273cd5 100644 --- a/libunwindstack/ElfInterface.cpp +++ b/libunwindstack/ElfInterface.cpp @@ -124,10 +124,10 @@ Memory* ElfInterface::CreateGnuDebugdataMemory() { } template -void ElfInterface::InitHeadersWithTemplate(uint64_t load_bias) { +void ElfInterface::InitHeadersWithTemplate() { if (eh_frame_hdr_offset_ != 0) { eh_frame_.reset(new DwarfEhFrameWithHdr(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(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(-1); eh_frame_offset_ = 0; + eh_frame_section_bias_ = 0; eh_frame_size_ = static_cast(-1); } if (debug_frame_offset_ != 0) { debug_frame_.reset(new DwarfDebugFrame(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(-1); @@ -159,7 +161,7 @@ void ElfInterface::InitHeadersWithTemplate(uint64_t load_bias) { } template -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 -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(phdr.p_vaddr) - phdr.p_offset; } } return 0; } template -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(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(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(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(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(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(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(uint64_t); -template void ElfInterface::InitHeadersWithTemplate(uint64_t); +template void ElfInterface::InitHeadersWithTemplate(); +template void ElfInterface::InitHeadersWithTemplate(); -template bool ElfInterface::ReadAllHeaders(uint64_t*); -template bool ElfInterface::ReadAllHeaders(uint64_t*); +template bool ElfInterface::ReadAllHeaders(int64_t*); +template bool ElfInterface::ReadAllHeaders(int64_t*); -template void ElfInterface::ReadProgramHeaders(const Elf32_Ehdr&, - uint64_t*); -template void ElfInterface::ReadProgramHeaders(const Elf64_Ehdr&, - uint64_t*); +template void ElfInterface::ReadProgramHeaders(const Elf32_Ehdr&, int64_t*); +template void ElfInterface::ReadProgramHeaders(const Elf64_Ehdr&, int64_t*); template void ElfInterface::ReadSectionHeaders(const Elf32_Ehdr&); template void ElfInterface::ReadSectionHeaders(const Elf64_Ehdr&); @@ -673,8 +668,8 @@ template bool ElfInterface::GetGlobalVariableWithTemplate(const std:: template void ElfInterface::GetMaxSizeWithTemplate(Memory*, uint64_t*); template void ElfInterface::GetMaxSizeWithTemplate(Memory*, uint64_t*); -template uint64_t ElfInterface::GetLoadBias(Memory*); -template uint64_t ElfInterface::GetLoadBias(Memory*); +template int64_t ElfInterface::GetLoadBias(Memory*); +template int64_t ElfInterface::GetLoadBias(Memory*); template std::string ElfInterface::ReadBuildIDFromMemory( Memory*); diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp index 3dd5d54fe..76f2dc882 100644 --- a/libunwindstack/ElfInterfaceArm.cpp +++ b/libunwindstack/ElfInterfaceArm.cpp @@ -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; } diff --git a/libunwindstack/ElfInterfaceArm.h b/libunwindstack/ElfInterfaceArm.h index 4c3a0c347..1d71cacd1 100644 --- a/libunwindstack/ElfInterfaceArm.h +++ b/libunwindstack/ElfInterfaceArm.h @@ -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); diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp index 5b30a4d7b..f2dad843b 100644 --- a/libunwindstack/MapInfo.cpp +++ b/libunwindstack/MapInfo.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -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& process_memory) { - uint64_t cur_load_bias = load_bias.load(); - if (cur_load_bias != static_cast(-1)) { + int64_t cur_load_bias = load_bias.load(); + if (cur_load_bias != INT64_MAX) { return cur_load_bias; } diff --git a/libunwindstack/include/unwindstack/DwarfMemory.h b/libunwindstack/include/unwindstack/DwarfMemory.h index 8dd8d2bb1..c45699a9e 100644 --- a/libunwindstack/include/unwindstack/DwarfMemory.h +++ b/libunwindstack/include/unwindstack/DwarfMemory.h @@ -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(-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(-1); } @@ -65,7 +65,7 @@ class DwarfMemory { Memory* memory_; uint64_t cur_offset_ = 0; - uint64_t pc_offset_ = static_cast(-1); + int64_t pc_offset_ = INT64_MAX; uint64_t data_offset_ = static_cast(-1); uint64_t func_offset_ = static_cast(-1); uint64_t text_offset_ = static_cast(-1); diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h index e9942decd..0b3f6d478 100644 --- a/libunwindstack/include/unwindstack/DwarfSection.h +++ b/libunwindstack/include/unwindstack/DwarfSection.h @@ -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* 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 { using DwarfSectionImpl::entries_offset_; using DwarfSectionImpl::entries_end_; using DwarfSectionImpl::last_error_; - using DwarfSectionImpl::load_bias_; + using DwarfSectionImpl::section_bias_; using DwarfSectionImpl::cie_entries_; using DwarfSectionImpl::fde_entries_; using DwarfSectionImpl::cie32_value_; @@ -175,7 +175,7 @@ class DwarfSectionImplNoHdr : public DwarfSectionImpl { DwarfSectionImplNoHdr(Memory* memory) : DwarfSectionImpl(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; diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h index 56bf318c8..fc3f2a610 100644 --- a/libunwindstack/include/unwindstack/Elf.h +++ b/libunwindstack/include/unwindstack/Elf.h @@ -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 interface_; std::unique_ptr memory_; uint32_t machine_type_; diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h index dbd917d67..ae9bd9a61 100644 --- a/libunwindstack/include/unwindstack/ElfInterface.h +++ b/libunwindstack/include/unwindstack/ElfInterface.h @@ -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 - static uint64_t GetLoadBias(Memory* memory); + static int64_t GetLoadBias(Memory* memory); template static std::string ReadBuildIDFromMemory(Memory* memory); protected: template - void InitHeadersWithTemplate(uint64_t load_bias); + void InitHeadersWithTemplate(); template - bool ReadAllHeaders(uint64_t* load_bias); + bool ReadAllHeaders(int64_t* load_bias); template - void ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias); + void ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias); template 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(load_bias); } - void InitHeaders(uint64_t load_bias) override { - ElfInterface::InitHeadersWithTemplate(load_bias); - } + void InitHeaders() override { ElfInterface::InitHeadersWithTemplate(); } std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate(); } @@ -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(load_bias); } - void InitHeaders(uint64_t load_bias) override { - ElfInterface::InitHeadersWithTemplate(load_bias); - } + void InitHeaders() override { ElfInterface::InitHeadersWithTemplate(); } std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate(); } diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h index 6c5cfc484..8f0c5160b 100644 --- a/libunwindstack/include/unwindstack/MapInfo.h +++ b/libunwindstack/include/unwindstack/MapInfo.h @@ -39,7 +39,7 @@ struct MapInfo { flags(flags), name(name), prev_map(map_info), - load_bias(static_cast(-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(-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 diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp index b386ef495..a9d6dadda 100644 --- a/libunwindstack/tests/DwarfSectionImplTest.cpp +++ b/libunwindstack/tests/DwarfSectionImplTest.cpp @@ -35,7 +35,7 @@ class TestDwarfSectionImpl : public DwarfSectionImpl { TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl(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*) override {} diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp index d754fcc50..6df2baecb 100644 --- a/libunwindstack/tests/DwarfSectionTest.cpp +++ b/libunwindstack/tests/DwarfSectionTest.cpp @@ -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*)); diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h index bd3083ce4..832e64ab1 100644 --- a/libunwindstack/tests/ElfFake.h +++ b/libunwindstack/tests/ElfFake.h @@ -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; diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp index 5b2036bdb..b048b178f 100644 --- a/libunwindstack/tests/ElfInterfaceTest.cpp +++ b/libunwindstack/tests/ElfInterfaceTest.cpp @@ -112,6 +112,21 @@ class ElfInterfaceTest : public ::testing::Test { template void InitSectionHeadersOffsets(); + template + void InitSectionHeadersOffsetsEhFrameSectionBias(uint64_t addr, uint64_t offset, + int64_t expected_bias); + + template + void InitSectionHeadersOffsetsEhFrameHdrSectionBias(uint64_t addr, uint64_t offset, + int64_t expected_bias); + + template + void InitSectionHeadersOffsetsDebugFrameSectionBias(uint64_t addr, uint64_t offset, + int64_t expected_bias); + + template + void CheckGnuEhFrame(uint64_t addr, uint64_t offset, int64_t expected_bias); + template void InitSym(uint64_t offset, uint32_t value, uint32_t size, uint32_t name_offset, uint64_t sym_offset, const char* name); @@ -132,10 +147,10 @@ class ElfInterfaceTest : public ::testing::Test { void BuildIDSectionTooSmallForHeader(); template - void CheckLoadBiasInFirstPhdr(uint64_t load_bias); + void CheckLoadBiasInFirstPhdr(int64_t load_bias); template - void CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr, uint64_t load_bias); + void CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr, int64_t load_bias); MemoryFake memory_; }; @@ -172,9 +187,9 @@ void ElfInterfaceTest::SinglePtLoad() { phdr.p_align = 0x1000; memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000U, load_bias); + EXPECT_EQ(0x2000, load_bias); const std::unordered_map& pt_loads = elf->pt_loads(); ASSERT_EQ(1U, pt_loads.size()); @@ -184,11 +199,11 @@ void ElfInterfaceTest::SinglePtLoad() { ASSERT_EQ(0x10000U, load_data.table_size); } -TEST_F(ElfInterfaceTest, elf32_single_pt_load) { +TEST_F(ElfInterfaceTest, single_pt_load_32) { SinglePtLoad(); } -TEST_F(ElfInterfaceTest, elf64_single_pt_load) { +TEST_F(ElfInterfaceTest, single_pt_load_64) { SinglePtLoad(); } @@ -228,9 +243,9 @@ void ElfInterfaceTest::MultipleExecutablePtLoads() { phdr.p_align = 0x1002; memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000U, load_bias); + EXPECT_EQ(0x2000, load_bias); const std::unordered_map& pt_loads = elf->pt_loads(); ASSERT_EQ(3U, pt_loads.size()); @@ -251,11 +266,11 @@ void ElfInterfaceTest::MultipleExecutablePtLoads() { ASSERT_EQ(0x10002U, load_data.table_size); } -TEST_F(ElfInterfaceTest, elf32_multiple_executable_pt_loads) { +TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_32) { MultipleExecutablePtLoads(); } -TEST_F(ElfInterfaceTest, elf64_multiple_executable_pt_loads) { +TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_64) { MultipleExecutablePtLoads(); } @@ -295,9 +310,9 @@ void ElfInterfaceTest::MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr() { phdr.p_align = 0x1002; memory_.SetMemory(0x100 + 2 * (sizeof(phdr) + 100), &phdr, sizeof(phdr)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000U, load_bias); + EXPECT_EQ(0x2000, load_bias); const std::unordered_map& pt_loads = elf->pt_loads(); ASSERT_EQ(3U, pt_loads.size()); @@ -318,12 +333,12 @@ void ElfInterfaceTest::MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr() { ASSERT_EQ(0x10002U, load_data.table_size); } -TEST_F(ElfInterfaceTest, elf32_multiple_executable_pt_loads_increments_not_size_of_phdr) { +TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_increments_not_size_of_phdr_32) { MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr(); } -TEST_F(ElfInterfaceTest, elf64_multiple_executable_pt_loads_increments_not_size_of_phdr) { +TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_increments_not_size_of_phdr_64) { MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr(); } @@ -364,9 +379,9 @@ void ElfInterfaceTest::NonExecutablePtLoads() { phdr.p_align = 0x1002; memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x1001U, load_bias); + EXPECT_EQ(0x1001, load_bias); const std::unordered_map& pt_loads = elf->pt_loads(); ASSERT_EQ(1U, pt_loads.size()); @@ -377,11 +392,11 @@ void ElfInterfaceTest::NonExecutablePtLoads() { ASSERT_EQ(0x10001U, load_data.table_size); } -TEST_F(ElfInterfaceTest, elf32_non_executable_pt_loads) { +TEST_F(ElfInterfaceTest, non_executable_pt_loads_32) { NonExecutablePtLoads(); } -TEST_F(ElfInterfaceTest, elf64_non_executable_pt_loads) { +TEST_F(ElfInterfaceTest, non_executable_pt_loads_64) { NonExecutablePtLoads(); } @@ -434,11 +449,10 @@ void ElfInterfaceTest::ManyPhdrs() { memset(&phdr, 0, sizeof(phdr)); phdr.p_type = PT_GNU_EH_FRAME; memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - phdr_offset += sizeof(phdr); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000U, load_bias); + EXPECT_EQ(0x2000, load_bias); const std::unordered_map& pt_loads = elf->pt_loads(); ASSERT_EQ(1U, pt_loads.size()); @@ -449,15 +463,15 @@ void ElfInterfaceTest::ManyPhdrs() { ASSERT_EQ(0x10000U, load_data.table_size); } -TEST_F(ElfInterfaceTest, elf32_many_phdrs) { +TEST_F(ElfInterfaceTest, many_phdrs_32) { ElfInterfaceTest::ManyPhdrs(); } -TEST_F(ElfInterfaceTest, elf64_many_phdrs) { +TEST_F(ElfInterfaceTest, many_phdrs_64) { ElfInterfaceTest::ManyPhdrs(); } -TEST_F(ElfInterfaceTest, elf32_arm) { +TEST_F(ElfInterfaceTest, arm32) { ElfInterfaceArm elf_arm(&memory_); Elf32_Ehdr ehdr = {}; @@ -476,9 +490,9 @@ TEST_F(ElfInterfaceTest, elf32_arm) { memory_.SetData32(0x2000, 0x1000); memory_.SetData32(0x2008, 0x1000); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf_arm.Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); std::vector entries; for (auto addr : elf_arm) { @@ -557,19 +571,19 @@ template void ElfInterfaceTest::Soname() { std::unique_ptr elf(new ElfInterfaceType(&memory_)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); ASSERT_EQ("fake_soname.so", elf->GetSoname()); } -TEST_F(ElfInterfaceTest, elf32_soname) { +TEST_F(ElfInterfaceTest, soname_32) { SonameInit(); Soname(); } -TEST_F(ElfInterfaceTest, elf64_soname) { +TEST_F(ElfInterfaceTest, soname_64) { SonameInit(); Soname(); } @@ -578,19 +592,19 @@ template void ElfInterfaceTest::SonameAfterDtNull() { std::unique_ptr elf(new ElfInterfaceType(&memory_)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); ASSERT_EQ("", elf->GetSoname()); } -TEST_F(ElfInterfaceTest, elf32_soname_after_dt_null) { +TEST_F(ElfInterfaceTest, soname_after_dt_null_32) { SonameInit(SONAME_DTNULL_AFTER); SonameAfterDtNull(); } -TEST_F(ElfInterfaceTest, elf64_soname_after_dt_null) { +TEST_F(ElfInterfaceTest, soname_after_dt_null_64) { SonameInit(SONAME_DTNULL_AFTER); SonameAfterDtNull(); } @@ -599,19 +613,19 @@ template void ElfInterfaceTest::SonameSize() { std::unique_ptr elf(new ElfInterfaceType(&memory_)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); ASSERT_EQ("", elf->GetSoname()); } -TEST_F(ElfInterfaceTest, elf32_soname_size) { +TEST_F(ElfInterfaceTest, soname_size_32) { SonameInit(SONAME_DTSIZE_SMALL); SonameSize(); } -TEST_F(ElfInterfaceTest, elf64_soname_size) { +TEST_F(ElfInterfaceTest, soname_size_64) { SonameInit(SONAME_DTSIZE_SMALL); SonameSize(); } @@ -622,19 +636,19 @@ template void ElfInterfaceTest::SonameMissingMap() { std::unique_ptr elf(new ElfInterfaceType(&memory_)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); ASSERT_EQ("", elf->GetSoname()); } -TEST_F(ElfInterfaceTest, elf32_soname_missing_map) { +TEST_F(ElfInterfaceTest, soname_missing_map_32) { SonameInit(SONAME_MISSING_MAP); SonameMissingMap(); } -TEST_F(ElfInterfaceTest, elf64_soname_missing_map) { +TEST_F(ElfInterfaceTest, soname_missing_map_64) { SonameInit(SONAME_MISSING_MAP); SonameMissingMap(); } @@ -653,17 +667,17 @@ void ElfInterfaceTest::InitHeadersEhFrameTest() { memory_.SetData32(0x10004, 0x500); memory_.SetData32(0x10008, 250); - elf.InitHeaders(0); + elf.InitHeaders(); EXPECT_FALSE(elf.eh_frame() == nullptr); EXPECT_TRUE(elf.debug_frame() == nullptr); } -TEST_F(ElfInterfaceTest, init_headers_eh_frame32) { +TEST_F(ElfInterfaceTest, init_headers_eh_frame_32) { InitHeadersEhFrameTest(); } -TEST_F(ElfInterfaceTest, init_headers_eh_frame64) { +TEST_F(ElfInterfaceTest, init_headers_eh_frame_64) { InitHeadersEhFrameTest(); } @@ -685,17 +699,17 @@ void ElfInterfaceTest::InitHeadersDebugFrame() { memory_.SetData32(0x5108, 0x1500); memory_.SetData32(0x510c, 0x200); - elf.InitHeaders(0); + elf.InitHeaders(); EXPECT_TRUE(elf.eh_frame() == nullptr); EXPECT_FALSE(elf.debug_frame() == nullptr); } -TEST_F(ElfInterfaceTest, init_headers_debug_frame32) { +TEST_F(ElfInterfaceTest, init_headers_debug_frame_32) { InitHeadersDebugFrame(); } -TEST_F(ElfInterfaceTest, init_headers_debug_frame64) { +TEST_F(ElfInterfaceTest, init_headers_debug_frame_64) { InitHeadersDebugFrame(); } @@ -709,16 +723,16 @@ void ElfInterfaceTest::InitProgramHeadersMalformed() { ehdr.e_phentsize = sizeof(Phdr); memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); } -TEST_F(ElfInterfaceTest, init_program_headers_malformed32) { +TEST_F(ElfInterfaceTest, init_program_headers_malformed_32) { InitProgramHeadersMalformed(); } -TEST_F(ElfInterfaceTest, init_program_headers_malformed64) { +TEST_F(ElfInterfaceTest, init_program_headers_malformed_64) { InitProgramHeadersMalformed(); } @@ -732,16 +746,16 @@ void ElfInterfaceTest::InitSectionHeadersMalformed() { ehdr.e_shentsize = sizeof(Shdr); memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); } -TEST_F(ElfInterfaceTest, init_section_headers_malformed32) { +TEST_F(ElfInterfaceTest, init_section_headers_malformed_32) { InitSectionHeadersMalformed(); } -TEST_F(ElfInterfaceTest, init_section_headers_malformed64) { +TEST_F(ElfInterfaceTest, init_section_headers_malformed_64) { InitSectionHeadersMalformed(); } @@ -796,11 +810,10 @@ void ElfInterfaceTest::InitSectionHeadersMalformedSymData() { shdr.sh_offset = 0xf000; shdr.sh_size = 0x1000; memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); EXPECT_EQ(0U, elf->debug_frame_offset()); EXPECT_EQ(0U, elf->debug_frame_size()); EXPECT_EQ(0U, elf->gnu_debugdata_offset()); @@ -811,11 +824,11 @@ void ElfInterfaceTest::InitSectionHeadersMalformedSymData() { ASSERT_FALSE(elf->GetFunctionName(0x90010, &name, &name_offset)); } -TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata32) { +TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata_32) { InitSectionHeadersMalformedSymData(); } -TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata64) { +TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata_64) { InitSectionHeadersMalformedSymData(); } @@ -866,14 +879,13 @@ void ElfInterfaceTest::InitSectionHeaders(uint64_t entry_size) { shdr.sh_offset = 0xf000; shdr.sh_size = 0x1000; memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; InitSym(0x5000, 0x90000, 0x1000, 0x100, 0xf000, "function_one"); InitSym(0x6000, 0xd0000, 0x1000, 0x300, 0xf000, "function_two"); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); EXPECT_EQ(0U, elf->debug_frame_offset()); EXPECT_EQ(0U, elf->debug_frame_size()); EXPECT_EQ(0U, elf->gnu_debugdata_offset()); @@ -890,19 +902,19 @@ void ElfInterfaceTest::InitSectionHeaders(uint64_t entry_size) { EXPECT_EQ(32U, name_offset); } -TEST_F(ElfInterfaceTest, init_section_headers32) { +TEST_F(ElfInterfaceTest, init_section_headers_32) { InitSectionHeaders(sizeof(Elf32_Shdr)); } -TEST_F(ElfInterfaceTest, init_section_headers64) { +TEST_F(ElfInterfaceTest, init_section_headers_64) { InitSectionHeaders(sizeof(Elf64_Shdr)); } -TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size32) { +TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size_32) { InitSectionHeaders(0x100); } -TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size64) { +TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size_64) { InitSectionHeaders(0x100); } @@ -967,7 +979,7 @@ void ElfInterfaceTest::InitSectionHeadersOffsets() { shdr.sh_type = SHT_PROGBITS; shdr.sh_link = 2; shdr.sh_name = 0x400; - shdr.sh_addr = 0x6000; + shdr.sh_addr = 0xa000; shdr.sh_offset = 0xa000; shdr.sh_entsize = 0x100; shdr.sh_size = 0xf00; @@ -977,10 +989,10 @@ void ElfInterfaceTest::InitSectionHeadersOffsets() { memset(&shdr, 0, sizeof(shdr)); shdr.sh_type = SHT_NOTE; shdr.sh_name = 0x500; + shdr.sh_addr = 0xb000; shdr.sh_offset = 0xb000; shdr.sh_size = 0xf00; memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame")); memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata")); @@ -988,29 +1000,352 @@ void ElfInterfaceTest::InitSectionHeadersOffsets() { memory_.SetMemory(0xf400, ".eh_frame_hdr", sizeof(".eh_frame_hdr")); memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); EXPECT_EQ(0x6000U, elf->debug_frame_offset()); + EXPECT_EQ(0, elf->debug_frame_section_bias()); EXPECT_EQ(0x500U, elf->debug_frame_size()); + EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset()); EXPECT_EQ(0x800U, elf->gnu_debugdata_size()); + EXPECT_EQ(0x7000U, elf->eh_frame_offset()); + EXPECT_EQ(0, elf->eh_frame_section_bias()); EXPECT_EQ(0x800U, elf->eh_frame_size()); + EXPECT_EQ(0xa000U, elf->eh_frame_hdr_offset()); + EXPECT_EQ(0, elf->eh_frame_hdr_section_bias()); EXPECT_EQ(0xf00U, elf->eh_frame_hdr_size()); + EXPECT_EQ(0xb000U, elf->gnu_build_id_offset()); EXPECT_EQ(0xf00U, elf->gnu_build_id_size()); } -TEST_F(ElfInterfaceTest, init_section_headers_offsets32) { +TEST_F(ElfInterfaceTest, init_section_headers_offsets_32) { InitSectionHeadersOffsets(); } -TEST_F(ElfInterfaceTest, init_section_headers_offsets64) { +TEST_F(ElfInterfaceTest, init_section_headers_offsets_64) { InitSectionHeadersOffsets(); } +template +void ElfInterfaceTest::InitSectionHeadersOffsetsEhFrameSectionBias(uint64_t addr, uint64_t offset, + int64_t expected_bias) { + std::unique_ptr elf(new ElfInterfaceType(&memory_)); + + uint64_t elf_offset = 0x2000; + + Ehdr ehdr = {}; + ehdr.e_shoff = elf_offset; + ehdr.e_shnum = 4; + ehdr.e_shentsize = sizeof(Shdr); + ehdr.e_shstrndx = 2; + memory_.SetMemory(0, &ehdr, sizeof(ehdr)); + + elf_offset += ehdr.e_shentsize; + + Shdr shdr = {}; + shdr.sh_type = SHT_PROGBITS; + shdr.sh_link = 2; + shdr.sh_name = 0x200; + shdr.sh_addr = 0x8000; + shdr.sh_offset = 0x8000; + shdr.sh_entsize = 0x100; + shdr.sh_size = 0x800; + memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); + elf_offset += ehdr.e_shentsize; + + // The string data for section header names. + memset(&shdr, 0, sizeof(shdr)); + shdr.sh_type = SHT_STRTAB; + shdr.sh_name = 0x20000; + shdr.sh_offset = 0xf000; + shdr.sh_size = 0x1000; + memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); + elf_offset += ehdr.e_shentsize; + + memset(&shdr, 0, sizeof(shdr)); + shdr.sh_type = SHT_PROGBITS; + shdr.sh_link = 2; + shdr.sh_name = 0x100; + shdr.sh_addr = addr; + shdr.sh_offset = offset; + shdr.sh_entsize = 0x100; + shdr.sh_size = 0x500; + memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); + + memory_.SetMemory(0xf100, ".eh_frame", sizeof(".eh_frame")); + memory_.SetMemory(0xf200, ".eh_frame_hdr", sizeof(".eh_frame_hdr")); + + int64_t load_bias = 0; + ASSERT_TRUE(elf->Init(&load_bias)); + EXPECT_EQ(0, load_bias); + EXPECT_EQ(offset, elf->eh_frame_offset()); + EXPECT_EQ(expected_bias, elf->eh_frame_section_bias()); + EXPECT_EQ(0x500U, elf->eh_frame_size()); + + EXPECT_EQ(0x8000U, elf->eh_frame_hdr_offset()); + EXPECT_EQ(0, elf->eh_frame_hdr_section_bias()); + EXPECT_EQ(0x800U, elf->eh_frame_hdr_size()); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_zero_32) { + InitSectionHeadersOffsetsEhFrameSectionBias(0x4000, + 0x4000, 0); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_zero_64) { + InitSectionHeadersOffsetsEhFrameSectionBias(0x6000, + 0x6000, 0); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_positive_32) { + InitSectionHeadersOffsetsEhFrameSectionBias( + 0x5000, 0x4000, 0x1000); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_positive_64) { + InitSectionHeadersOffsetsEhFrameSectionBias( + 0x6000, 0x4000, 0x2000); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_negative_32) { + InitSectionHeadersOffsetsEhFrameSectionBias( + 0x3000, 0x4000, -0x1000); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_negative_64) { + InitSectionHeadersOffsetsEhFrameSectionBias( + 0x6000, 0x9000, -0x3000); +} + +template +void ElfInterfaceTest::InitSectionHeadersOffsetsEhFrameHdrSectionBias(uint64_t addr, + uint64_t offset, + int64_t expected_bias) { + std::unique_ptr elf(new ElfInterfaceType(&memory_)); + + uint64_t elf_offset = 0x2000; + + Ehdr ehdr = {}; + ehdr.e_shoff = elf_offset; + ehdr.e_shnum = 4; + ehdr.e_shentsize = sizeof(Shdr); + ehdr.e_shstrndx = 2; + memory_.SetMemory(0, &ehdr, sizeof(ehdr)); + + elf_offset += ehdr.e_shentsize; + + Shdr shdr = {}; + shdr.sh_type = SHT_PROGBITS; + shdr.sh_link = 2; + shdr.sh_name = 0x200; + shdr.sh_addr = addr; + shdr.sh_offset = offset; + shdr.sh_entsize = 0x100; + shdr.sh_size = 0x800; + memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); + elf_offset += ehdr.e_shentsize; + + // The string data for section header names. + memset(&shdr, 0, sizeof(shdr)); + shdr.sh_type = SHT_STRTAB; + shdr.sh_name = 0x20000; + shdr.sh_offset = 0xf000; + shdr.sh_size = 0x1000; + memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); + elf_offset += ehdr.e_shentsize; + + memset(&shdr, 0, sizeof(shdr)); + shdr.sh_type = SHT_PROGBITS; + shdr.sh_link = 2; + shdr.sh_name = 0x100; + shdr.sh_addr = 0x5000; + shdr.sh_offset = 0x5000; + shdr.sh_entsize = 0x100; + shdr.sh_size = 0x500; + memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); + + memory_.SetMemory(0xf100, ".eh_frame", sizeof(".eh_frame")); + memory_.SetMemory(0xf200, ".eh_frame_hdr", sizeof(".eh_frame_hdr")); + + int64_t load_bias = 0; + ASSERT_TRUE(elf->Init(&load_bias)); + EXPECT_EQ(0, load_bias); + EXPECT_EQ(0x5000U, elf->eh_frame_offset()); + EXPECT_EQ(0, elf->eh_frame_section_bias()); + EXPECT_EQ(0x500U, elf->eh_frame_size()); + EXPECT_EQ(offset, elf->eh_frame_hdr_offset()); + EXPECT_EQ(expected_bias, elf->eh_frame_hdr_section_bias()); + EXPECT_EQ(0x800U, elf->eh_frame_hdr_size()); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_zero_32) { + InitSectionHeadersOffsetsEhFrameHdrSectionBias(0x9000, + 0x9000, 0); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_zero_64) { + InitSectionHeadersOffsetsEhFrameHdrSectionBias(0xa000, + 0xa000, 0); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_positive_32) { + InitSectionHeadersOffsetsEhFrameHdrSectionBias( + 0x9000, 0x4000, 0x5000); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_positive_64) { + InitSectionHeadersOffsetsEhFrameHdrSectionBias( + 0x6000, 0x1000, 0x5000); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_negative_32) { + InitSectionHeadersOffsetsEhFrameHdrSectionBias( + 0x3000, 0x5000, -0x2000); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_negative_64) { + InitSectionHeadersOffsetsEhFrameHdrSectionBias( + 0x5000, 0x9000, -0x4000); +} + +template +void ElfInterfaceTest::InitSectionHeadersOffsetsDebugFrameSectionBias(uint64_t addr, + uint64_t offset, + int64_t expected_bias) { + std::unique_ptr elf(new ElfInterfaceType(&memory_)); + + uint64_t elf_offset = 0x2000; + + Ehdr ehdr = {}; + ehdr.e_shoff = elf_offset; + ehdr.e_shnum = 3; + ehdr.e_shentsize = sizeof(Shdr); + ehdr.e_shstrndx = 2; + memory_.SetMemory(0, &ehdr, sizeof(ehdr)); + + elf_offset += ehdr.e_shentsize; + + Shdr shdr = {}; + shdr.sh_type = SHT_PROGBITS; + shdr.sh_link = 2; + shdr.sh_name = 0x100; + shdr.sh_addr = addr; + shdr.sh_offset = offset; + shdr.sh_entsize = 0x100; + shdr.sh_size = 0x800; + memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); + elf_offset += ehdr.e_shentsize; + + // The string data for section header names. + memset(&shdr, 0, sizeof(shdr)); + shdr.sh_type = SHT_STRTAB; + shdr.sh_name = 0x20000; + shdr.sh_offset = 0xf000; + shdr.sh_size = 0x1000; + memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); + + memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame")); + + int64_t load_bias = 0; + ASSERT_TRUE(elf->Init(&load_bias)); + EXPECT_EQ(0, load_bias); + EXPECT_EQ(offset, elf->debug_frame_offset()); + EXPECT_EQ(expected_bias, elf->debug_frame_section_bias()); + EXPECT_EQ(0x800U, elf->debug_frame_size()); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_zero_32) { + InitSectionHeadersOffsetsDebugFrameSectionBias(0x5000, + 0x5000, 0); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_zero_64) { + InitSectionHeadersOffsetsDebugFrameSectionBias(0xa000, + 0xa000, 0); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_positive_32) { + InitSectionHeadersOffsetsDebugFrameSectionBias( + 0x5000, 0x2000, 0x3000); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_positive_64) { + InitSectionHeadersOffsetsDebugFrameSectionBias( + 0x7000, 0x1000, 0x6000); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_negative_32) { + InitSectionHeadersOffsetsDebugFrameSectionBias( + 0x6000, 0x7000, -0x1000); +} + +TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_negative_64) { + InitSectionHeadersOffsetsDebugFrameSectionBias( + 0x3000, 0x5000, -0x2000); +} + +template +void ElfInterfaceTest::CheckGnuEhFrame(uint64_t addr, uint64_t offset, int64_t expected_bias) { + std::unique_ptr elf(new ElfInterfaceType(&memory_)); + + Ehdr ehdr = {}; + ehdr.e_phoff = 0x100; + ehdr.e_phnum = 2; + ehdr.e_phentsize = sizeof(Phdr); + memory_.SetMemory(0, &ehdr, sizeof(ehdr)); + + uint64_t phdr_offset = 0x100; + + Phdr phdr = {}; + phdr.p_type = PT_LOAD; + phdr.p_memsz = 0x10000; + phdr.p_flags = PF_R | PF_X; + phdr.p_align = 0x1000; + memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); + phdr_offset += sizeof(phdr); + + memset(&phdr, 0, sizeof(phdr)); + phdr.p_type = PT_GNU_EH_FRAME; + phdr.p_paddr = addr; + phdr.p_offset = offset; + memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); + + int64_t load_bias = 0; + ASSERT_TRUE(elf->Init(&load_bias)); + EXPECT_EQ(0, load_bias); + EXPECT_EQ(expected_bias, elf->eh_frame_hdr_section_bias()); +} + +TEST_F(ElfInterfaceTest, eh_frame_zero_section_bias_32) { + ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x4000, 0); +} + +TEST_F(ElfInterfaceTest, eh_frame_zero_section_bias_64) { + ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x4000, 0); +} + +TEST_F(ElfInterfaceTest, eh_frame_positive_section_bias_32) { + ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x1000, 0x3000); +} + +TEST_F(ElfInterfaceTest, eh_frame_positive_section_bias_64) { + ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x1000, 0x3000); +} + +TEST_F(ElfInterfaceTest, eh_frame_negative_section_bias_32) { + ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x5000, + -0x1000); +} + +TEST_F(ElfInterfaceTest, eh_frame_negative_section_bias_64) { + ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x5000, + -0x1000); +} + TEST_F(ElfInterfaceTest, is_valid_pc_from_pt_load) { std::unique_ptr elf(new ElfInterface32(&memory_)); @@ -1028,9 +1363,9 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_pt_load) { phdr.p_align = 0x1000; memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0U, load_bias); + EXPECT_EQ(0, load_bias); EXPECT_TRUE(elf->IsValidPc(0)); EXPECT_TRUE(elf->IsValidPc(0x5000)); EXPECT_TRUE(elf->IsValidPc(0xffff)); @@ -1054,9 +1389,9 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_pt_load_non_zero_load_bias) { phdr.p_align = 0x1000; memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000U, load_bias); + EXPECT_EQ(0x2000, load_bias); EXPECT_FALSE(elf->IsValidPc(0)); EXPECT_FALSE(elf->IsValidPc(0x1000)); EXPECT_FALSE(elf->IsValidPc(0x1fff)); @@ -1111,10 +1446,10 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_debug_frame) { memory_.SetData32(0x708, 0x2100); memory_.SetData32(0x70c, 0x200); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - elf->InitHeaders(0); - EXPECT_EQ(0U, load_bias); + elf->InitHeaders(); + EXPECT_EQ(0, load_bias); EXPECT_FALSE(elf->IsValidPc(0)); EXPECT_FALSE(elf->IsValidPc(0x20ff)); EXPECT_TRUE(elf->IsValidPc(0x2100)); @@ -1168,10 +1503,10 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_eh_frame) { memory_.SetData32(0x708, 0x20f8); memory_.SetData32(0x70c, 0x200); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); - elf->InitHeaders(0); - EXPECT_EQ(0U, load_bias); + elf->InitHeaders(); + EXPECT_EQ(0, load_bias); EXPECT_FALSE(elf->IsValidPc(0)); EXPECT_FALSE(elf->IsValidPc(0x27ff)); EXPECT_TRUE(elf->IsValidPc(0x2800)); @@ -1207,7 +1542,6 @@ void ElfInterfaceTest::BuildID() { note_offset += sizeof("GNU"); // This part of the note does not contain any trailing '\0'. memcpy(¬e_section[note_offset], "BUILDID", 7); - note_offset += 8; Shdr shdr = {}; shdr.sh_type = SHT_NOTE; @@ -1224,16 +1558,23 @@ void ElfInterfaceTest::BuildID() { shdr.sh_offset = 0xf000; shdr.sh_size = 0x1000; memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); ASSERT_EQ("BUILDID", elf->GetBuildID()); } +TEST_F(ElfInterfaceTest, build_id_32) { + BuildID(); +} + +TEST_F(ElfInterfaceTest, build_id_64) { + BuildID(); +} + template void ElfInterfaceTest::BuildIDTwoNotes() { std::unique_ptr elf(new ElfInterfaceType(&memory_)); @@ -1272,7 +1613,6 @@ void ElfInterfaceTest::BuildIDTwoNotes() { note_offset += sizeof("GNU"); // This part of the note does not contain any trailing '\0'. memcpy(¬e_section[note_offset], "BUILDID", 7); - note_offset += 8; Shdr shdr = {}; shdr.sh_type = SHT_NOTE; @@ -1289,16 +1629,23 @@ void ElfInterfaceTest::BuildIDTwoNotes() { shdr.sh_offset = 0xf000; shdr.sh_size = 0x1000; memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); ASSERT_EQ("BUILDID", elf->GetBuildID()); } +TEST_F(ElfInterfaceTest, build_id_two_notes_32) { + BuildIDTwoNotes(); +} + +TEST_F(ElfInterfaceTest, build_id_two_notes_64) { + BuildIDTwoNotes(); +} + template void ElfInterfaceTest::BuildIDSectionTooSmallForName () { std::unique_ptr elf(new ElfInterfaceType(&memory_)); @@ -1326,7 +1673,6 @@ void ElfInterfaceTest::BuildIDSectionTooSmallForName () { note_offset += sizeof("GNU"); // This part of the note does not contain any trailing '\0'. memcpy(¬e_section[note_offset], "BUILDID", 7); - note_offset += 8; Shdr shdr = {}; shdr.sh_type = SHT_NOTE; @@ -1343,16 +1689,23 @@ void ElfInterfaceTest::BuildIDSectionTooSmallForName () { shdr.sh_offset = 0xf000; shdr.sh_size = 0x1000; memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); ASSERT_EQ("", elf->GetBuildID()); } +TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name_32) { + BuildIDSectionTooSmallForName(); +} + +TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name_64) { + BuildIDSectionTooSmallForName(); +} + template void ElfInterfaceTest::BuildIDSectionTooSmallForDesc () { std::unique_ptr elf(new ElfInterfaceType(&memory_)); @@ -1380,7 +1733,6 @@ void ElfInterfaceTest::BuildIDSectionTooSmallForDesc () { note_offset += sizeof("GNU"); // This part of the note does not contain any trailing '\0'. memcpy(¬e_section[note_offset], "BUILDID", 7); - note_offset += 8; Shdr shdr = {}; shdr.sh_type = SHT_NOTE; @@ -1397,16 +1749,23 @@ void ElfInterfaceTest::BuildIDSectionTooSmallForDesc () { shdr.sh_offset = 0xf000; shdr.sh_size = 0x1000; memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); ASSERT_EQ("", elf->GetBuildID()); } +TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc_32) { + BuildIDSectionTooSmallForDesc(); +} + +TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc_64) { + BuildIDSectionTooSmallForDesc(); +} + template void ElfInterfaceTest::BuildIDSectionTooSmallForHeader () { std::unique_ptr elf(new ElfInterfaceType(&memory_)); @@ -1434,7 +1793,6 @@ void ElfInterfaceTest::BuildIDSectionTooSmallForHeader () { note_offset += sizeof("GNU"); // This part of the note does not contain any trailing '\0'. memcpy(¬e_section[note_offset], "BUILDID", 7); - note_offset += 8; Shdr shdr = {}; shdr.sh_type = SHT_NOTE; @@ -1451,58 +1809,25 @@ void ElfInterfaceTest::BuildIDSectionTooSmallForHeader () { shdr.sh_offset = 0xf000; shdr.sh_size = 0x1000; memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - uint64_t load_bias = 0; + int64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); ASSERT_EQ("", elf->GetBuildID()); } -TEST_F(ElfInterfaceTest, build_id32) { - BuildID(); -} - -TEST_F(ElfInterfaceTest, build_id64) { - BuildID(); -} - -TEST_F(ElfInterfaceTest, build_id_two_notes32) { - BuildIDTwoNotes(); -} - -TEST_F(ElfInterfaceTest, build_id_two_notes64) { - BuildIDTwoNotes(); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name32) { - BuildIDSectionTooSmallForName(); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name64) { - BuildIDSectionTooSmallForName(); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc32) { - BuildIDSectionTooSmallForDesc(); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc64) { - BuildIDSectionTooSmallForDesc(); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header32) { +TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header_32) { BuildIDSectionTooSmallForHeader(); } -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header64) { +TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header_64) { BuildIDSectionTooSmallForHeader(); } template -void ElfInterfaceTest::CheckLoadBiasInFirstPhdr(uint64_t load_bias) { +void ElfInterfaceTest::CheckLoadBiasInFirstPhdr(int64_t load_bias) { Ehdr ehdr = {}; ehdr.e_phoff = 0x100; ehdr.e_phnum = 2; @@ -1526,11 +1851,11 @@ void ElfInterfaceTest::CheckLoadBiasInFirstPhdr(uint64_t load_bias) { phdr.p_align = 0x1000; memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr)); - uint64_t static_load_bias = ElfInterface::GetLoadBias(&memory_); + int64_t static_load_bias = ElfInterface::GetLoadBias(&memory_); ASSERT_EQ(load_bias, static_load_bias); std::unique_ptr elf(new ElfInterfaceType(&memory_)); - uint64_t init_load_bias = 0; + int64_t init_load_bias = 0; ASSERT_TRUE(elf->Init(&init_load_bias)); ASSERT_EQ(init_load_bias, static_load_bias); } @@ -1553,7 +1878,7 @@ TEST_F(ElfInterfaceTest, get_load_bias_non_zero_64) { template void ElfInterfaceTest::CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr, - uint64_t load_bias) { + int64_t load_bias) { Ehdr ehdr = {}; ehdr.e_phoff = 0x100; ehdr.e_phnum = 3; @@ -1586,11 +1911,11 @@ void ElfInterfaceTest::CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t va phdr.p_align = 0x1000; memory_.SetMemory(0x200 + sizeof(phdr), &phdr, sizeof(phdr)); - uint64_t static_load_bias = ElfInterface::GetLoadBias(&memory_); + int64_t static_load_bias = ElfInterface::GetLoadBias(&memory_); ASSERT_EQ(load_bias, static_load_bias); std::unique_ptr elf(new ElfInterfaceType(&memory_)); - uint64_t init_load_bias = 0; + int64_t init_load_bias = 0; ASSERT_TRUE(elf->Init(&init_load_bias)); ASSERT_EQ(init_load_bias, static_load_bias); } @@ -1603,20 +1928,20 @@ TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_64) { CheckLoadBiasInFirstExecPhdr(0x1000, 0x1000, 0); } -TEST_F(ElfInterfaceTest, get_load_bias_exec_non_zero_32) { +TEST_F(ElfInterfaceTest, get_load_bias_exec_positive_32) { CheckLoadBiasInFirstExecPhdr(0x1000, 0x4000, 0x3000); } -TEST_F(ElfInterfaceTest, get_load_bias_exec_non_zero_64) { +TEST_F(ElfInterfaceTest, get_load_bias_exec_positive_64) { CheckLoadBiasInFirstExecPhdr(0x1000, 0x4000, 0x3000); } -TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_from_error_32) { - CheckLoadBiasInFirstExecPhdr(0x5000, 0x1000, 0); +TEST_F(ElfInterfaceTest, get_load_bias_exec_negative_32) { + CheckLoadBiasInFirstExecPhdr(0x5000, 0x1000, -0x4000); } -TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_from_error_64) { - CheckLoadBiasInFirstExecPhdr(0x5000, 0x1000, 0); +TEST_F(ElfInterfaceTest, get_load_bias_exec_negative_64) { + CheckLoadBiasInFirstExecPhdr(0x5000, 0x1000, -0x4000); } } // namespace unwindstack diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp index c432d6d4f..8c1eade0d 100644 --- a/libunwindstack/tests/ElfTest.cpp +++ b/libunwindstack/tests/ElfTest.cpp @@ -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 ""; } diff --git a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp index 2c9892847..da3dbf2ee 100644 --- a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp +++ b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp @@ -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(-1); + map_info_->load_bias = INT64_MAX; elf_->FakeSetLoadBias(0x1000); EXPECT_EQ(0x1000U, map_info_->GetLoadBias(process_memory_)); } diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoTest.cpp index e2cbb9812..ef76b1b11 100644 --- a/libunwindstack/tests/MapInfoTest.cpp +++ b/libunwindstack/tests/MapInfoTest.cpp @@ -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(-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(-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); } diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp index bded57aca..72eef3e0b 100644 --- a/libunwindstack/tests/UnwindOfflineTest.cpp +++ b/libunwindstack/tests/UnwindOfflineTest.cpp @@ -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 diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so new file mode 100644 index 000000000..7bb7156bb Binary files /dev/null and b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64 b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64 new file mode 100644 index 000000000..00a3896d6 Binary files /dev/null and b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64 differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt new file mode 100644 index 000000000..a2babee1c --- /dev/null +++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt @@ -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 diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt new file mode 100644 index 000000000..3c601e15e --- /dev/null +++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt @@ -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 diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data new file mode 100644 index 000000000..167473373 Binary files /dev/null and b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data new file mode 100644 index 000000000..6d7b48ab1 Binary files /dev/null and b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test new file mode 100644 index 000000000..3a75b8fbe Binary files /dev/null and b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso new file mode 100644 index 000000000..49409167f Binary files /dev/null and b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso differ