Loading libunwindstack/Elf.cpp +16 −18 Original line number Diff line number Diff line Loading @@ -112,37 +112,35 @@ bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offse gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset))); } bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) { bool Elf::GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset) { if (!valid_) { return false; } if (!interface_->GetGlobalVariable(name, memory_address) && uint64_t vaddr; if (!interface_->GetGlobalVariable(name, &vaddr) && (gnu_debugdata_interface_ == nullptr || !gnu_debugdata_interface_->GetGlobalVariable(name, memory_address))) { !gnu_debugdata_interface_->GetGlobalVariable(name, &vaddr))) { return false; } // Adjust by the load bias. if (load_bias_ > 0 && *memory_address < static_cast<uint64_t>(load_bias_)) { return false; // Check the .data section. uint64_t vaddr_start = interface_->data_vaddr_start(); if (vaddr >= vaddr_start && vaddr < interface_->data_vaddr_end()) { *memory_offset = vaddr - vaddr_start + interface_->data_offset(); return true; } *memory_address -= load_bias_; // If this winds up in the dynamic section, then we might need to adjust // the address. uint64_t dynamic_end = interface_->dynamic_vaddr() + interface_->dynamic_size(); if (*memory_address >= interface_->dynamic_vaddr() && *memory_address < dynamic_end) { if (interface_->dynamic_vaddr() > interface_->dynamic_offset()) { *memory_address -= interface_->dynamic_vaddr() - interface_->dynamic_offset(); } else { *memory_address += interface_->dynamic_offset() - interface_->dynamic_vaddr(); } } // Check the .dynamic section. vaddr_start = interface_->dynamic_vaddr_start(); if (vaddr >= vaddr_start && vaddr < interface_->dynamic_vaddr_end()) { *memory_offset = vaddr - vaddr_start + interface_->dynamic_offset(); return true; } return false; } std::string Elf::GetBuildID() { if (!valid_) { return ""; Loading libunwindstack/ElfInterface.cpp +15 −3 Original line number Diff line number Diff line Loading @@ -236,8 +236,12 @@ void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias) case PT_DYNAMIC: dynamic_offset_ = phdr.p_offset; dynamic_vaddr_ = phdr.p_vaddr; dynamic_size_ = phdr.p_memsz; dynamic_vaddr_start_ = phdr.p_vaddr; if (__builtin_add_overflow(dynamic_vaddr_start_, phdr.p_memsz, &dynamic_vaddr_end_)) { dynamic_offset_ = 0; dynamic_vaddr_start_ = 0; dynamic_vaddr_end_ = 0; } break; default: Loading Loading @@ -360,6 +364,14 @@ void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { 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; } else if (name == ".data") { data_offset_ = shdr.sh_offset; data_vaddr_start_ = shdr.sh_addr; if (__builtin_add_overflow(data_vaddr_start_, shdr.sh_size, &data_vaddr_end_)) { data_offset_ = 0; data_vaddr_start_ = 0; data_vaddr_end_ = 0; } } } } Loading Loading @@ -398,7 +410,7 @@ std::string ElfInterface::GetSonameWithTemplate() { // Find the soname location from the dynamic headers section. DynType dyn; uint64_t offset = dynamic_offset_; uint64_t max_offset = offset + dynamic_size_; uint64_t max_offset = offset + dynamic_vaddr_end_ - dynamic_vaddr_start_; for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) { if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) { last_error_.code = ERROR_MEMORY_INVALID; Loading libunwindstack/Global.cpp +28 −31 Original line number Diff line number Diff line Loading @@ -39,28 +39,22 @@ void Global::SetArch(ArchEnum arch) { } } uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) { if (!search_libs_.empty()) { bool found = false; const char* lib = basename(info->name.c_str()); for (const std::string& name : search_libs_) { if (name == lib) { found = true; break; } } if (!found) { return 0; bool Global::Searchable(const std::string& name) { if (search_libs_.empty()) { return true; } if (name.empty()) { return false; } Elf* elf = info->GetElf(memory_, arch()); uint64_t ptr; // Find first non-empty list (libraries might be loaded multiple times). if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) { return ptr + info->start; const char* base_name = basename(name.c_str()); for (const std::string& lib : search_libs_) { if (base_name == lib) { return true; } } return 0; return false; } void Global::FindAndReadVariable(Maps* maps, const char* var_str) { Loading @@ -78,24 +72,27 @@ void Global::FindAndReadVariable(Maps* maps, const char* var_str) { // f2000-f3000 2000 rw- /system/lib/libc.so MapInfo* map_start = nullptr; for (const auto& info : *maps) { if (map_start != nullptr) { if (map_start->name == info->name) { if (map_start != nullptr && map_start->name == info->name) { if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) { uint64_t ptr = GetVariableOffset(map_start, variable); if (ptr != 0 && ReadVariableData(ptr)) { Elf* elf = map_start->GetElf(memory_, arch()); uint64_t ptr; if (elf->GetGlobalVariableOffset(variable, &ptr) && ptr != 0) { uint64_t offset_end = info->offset + info->end - info->start; if (ptr >= info->offset && ptr < offset_end) { ptr = info->start + ptr - info->offset; if (ReadVariableData(ptr)) { break; } else { // Failed to find the global variable, do not bother trying again. map_start = nullptr; } } } else { } map_start = nullptr; } } else { map_start = nullptr; } if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 && !info->name.empty()) { Searchable(info->name)) { map_start = info.get(); } } Loading libunwindstack/include/unwindstack/Elf.h +1 −1 Original line number Diff line number Diff line Loading @@ -63,7 +63,7 @@ class Elf { bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset); bool GetGlobalVariable(const std::string& name, uint64_t* memory_address); bool GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset); uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info); Loading libunwindstack/include/unwindstack/ElfInterface.h +11 −4 Original line number Diff line number Diff line Loading @@ -77,8 +77,11 @@ class ElfInterface { void SetGnuDebugdataInterface(ElfInterface* interface) { gnu_debugdata_interface_ = interface; } uint64_t dynamic_offset() { return dynamic_offset_; } uint64_t dynamic_vaddr() { return dynamic_vaddr_; } uint64_t dynamic_size() { return dynamic_size_; } uint64_t dynamic_vaddr_start() { return dynamic_vaddr_start_; } uint64_t dynamic_vaddr_end() { return dynamic_vaddr_end_; } uint64_t data_offset() { return data_offset_; } uint64_t data_vaddr_start() { return data_vaddr_start_; } uint64_t data_vaddr_end() { return data_vaddr_end_; } 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_; } Loading Loading @@ -141,8 +144,12 @@ class ElfInterface { // Stored elf data. uint64_t dynamic_offset_ = 0; uint64_t dynamic_vaddr_ = 0; uint64_t dynamic_size_ = 0; uint64_t dynamic_vaddr_start_ = 0; uint64_t dynamic_vaddr_end_ = 0; uint64_t data_offset_ = 0; uint64_t data_vaddr_start_ = 0; uint64_t data_vaddr_end_ = 0; uint64_t eh_frame_hdr_offset_ = 0; int64_t eh_frame_hdr_section_bias_ = 0; Loading Loading
libunwindstack/Elf.cpp +16 −18 Original line number Diff line number Diff line Loading @@ -112,37 +112,35 @@ bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offse gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset))); } bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) { bool Elf::GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset) { if (!valid_) { return false; } if (!interface_->GetGlobalVariable(name, memory_address) && uint64_t vaddr; if (!interface_->GetGlobalVariable(name, &vaddr) && (gnu_debugdata_interface_ == nullptr || !gnu_debugdata_interface_->GetGlobalVariable(name, memory_address))) { !gnu_debugdata_interface_->GetGlobalVariable(name, &vaddr))) { return false; } // Adjust by the load bias. if (load_bias_ > 0 && *memory_address < static_cast<uint64_t>(load_bias_)) { return false; // Check the .data section. uint64_t vaddr_start = interface_->data_vaddr_start(); if (vaddr >= vaddr_start && vaddr < interface_->data_vaddr_end()) { *memory_offset = vaddr - vaddr_start + interface_->data_offset(); return true; } *memory_address -= load_bias_; // If this winds up in the dynamic section, then we might need to adjust // the address. uint64_t dynamic_end = interface_->dynamic_vaddr() + interface_->dynamic_size(); if (*memory_address >= interface_->dynamic_vaddr() && *memory_address < dynamic_end) { if (interface_->dynamic_vaddr() > interface_->dynamic_offset()) { *memory_address -= interface_->dynamic_vaddr() - interface_->dynamic_offset(); } else { *memory_address += interface_->dynamic_offset() - interface_->dynamic_vaddr(); } } // Check the .dynamic section. vaddr_start = interface_->dynamic_vaddr_start(); if (vaddr >= vaddr_start && vaddr < interface_->dynamic_vaddr_end()) { *memory_offset = vaddr - vaddr_start + interface_->dynamic_offset(); return true; } return false; } std::string Elf::GetBuildID() { if (!valid_) { return ""; Loading
libunwindstack/ElfInterface.cpp +15 −3 Original line number Diff line number Diff line Loading @@ -236,8 +236,12 @@ void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias) case PT_DYNAMIC: dynamic_offset_ = phdr.p_offset; dynamic_vaddr_ = phdr.p_vaddr; dynamic_size_ = phdr.p_memsz; dynamic_vaddr_start_ = phdr.p_vaddr; if (__builtin_add_overflow(dynamic_vaddr_start_, phdr.p_memsz, &dynamic_vaddr_end_)) { dynamic_offset_ = 0; dynamic_vaddr_start_ = 0; dynamic_vaddr_end_ = 0; } break; default: Loading Loading @@ -360,6 +364,14 @@ void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { 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; } else if (name == ".data") { data_offset_ = shdr.sh_offset; data_vaddr_start_ = shdr.sh_addr; if (__builtin_add_overflow(data_vaddr_start_, shdr.sh_size, &data_vaddr_end_)) { data_offset_ = 0; data_vaddr_start_ = 0; data_vaddr_end_ = 0; } } } } Loading Loading @@ -398,7 +410,7 @@ std::string ElfInterface::GetSonameWithTemplate() { // Find the soname location from the dynamic headers section. DynType dyn; uint64_t offset = dynamic_offset_; uint64_t max_offset = offset + dynamic_size_; uint64_t max_offset = offset + dynamic_vaddr_end_ - dynamic_vaddr_start_; for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) { if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) { last_error_.code = ERROR_MEMORY_INVALID; Loading
libunwindstack/Global.cpp +28 −31 Original line number Diff line number Diff line Loading @@ -39,28 +39,22 @@ void Global::SetArch(ArchEnum arch) { } } uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) { if (!search_libs_.empty()) { bool found = false; const char* lib = basename(info->name.c_str()); for (const std::string& name : search_libs_) { if (name == lib) { found = true; break; } } if (!found) { return 0; bool Global::Searchable(const std::string& name) { if (search_libs_.empty()) { return true; } if (name.empty()) { return false; } Elf* elf = info->GetElf(memory_, arch()); uint64_t ptr; // Find first non-empty list (libraries might be loaded multiple times). if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) { return ptr + info->start; const char* base_name = basename(name.c_str()); for (const std::string& lib : search_libs_) { if (base_name == lib) { return true; } } return 0; return false; } void Global::FindAndReadVariable(Maps* maps, const char* var_str) { Loading @@ -78,24 +72,27 @@ void Global::FindAndReadVariable(Maps* maps, const char* var_str) { // f2000-f3000 2000 rw- /system/lib/libc.so MapInfo* map_start = nullptr; for (const auto& info : *maps) { if (map_start != nullptr) { if (map_start->name == info->name) { if (map_start != nullptr && map_start->name == info->name) { if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) { uint64_t ptr = GetVariableOffset(map_start, variable); if (ptr != 0 && ReadVariableData(ptr)) { Elf* elf = map_start->GetElf(memory_, arch()); uint64_t ptr; if (elf->GetGlobalVariableOffset(variable, &ptr) && ptr != 0) { uint64_t offset_end = info->offset + info->end - info->start; if (ptr >= info->offset && ptr < offset_end) { ptr = info->start + ptr - info->offset; if (ReadVariableData(ptr)) { break; } else { // Failed to find the global variable, do not bother trying again. map_start = nullptr; } } } else { } map_start = nullptr; } } else { map_start = nullptr; } if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 && !info->name.empty()) { Searchable(info->name)) { map_start = info.get(); } } Loading
libunwindstack/include/unwindstack/Elf.h +1 −1 Original line number Diff line number Diff line Loading @@ -63,7 +63,7 @@ class Elf { bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset); bool GetGlobalVariable(const std::string& name, uint64_t* memory_address); bool GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset); uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info); Loading
libunwindstack/include/unwindstack/ElfInterface.h +11 −4 Original line number Diff line number Diff line Loading @@ -77,8 +77,11 @@ class ElfInterface { void SetGnuDebugdataInterface(ElfInterface* interface) { gnu_debugdata_interface_ = interface; } uint64_t dynamic_offset() { return dynamic_offset_; } uint64_t dynamic_vaddr() { return dynamic_vaddr_; } uint64_t dynamic_size() { return dynamic_size_; } uint64_t dynamic_vaddr_start() { return dynamic_vaddr_start_; } uint64_t dynamic_vaddr_end() { return dynamic_vaddr_end_; } uint64_t data_offset() { return data_offset_; } uint64_t data_vaddr_start() { return data_vaddr_start_; } uint64_t data_vaddr_end() { return data_vaddr_end_; } 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_; } Loading Loading @@ -141,8 +144,12 @@ class ElfInterface { // Stored elf data. uint64_t dynamic_offset_ = 0; uint64_t dynamic_vaddr_ = 0; uint64_t dynamic_size_ = 0; uint64_t dynamic_vaddr_start_ = 0; uint64_t dynamic_vaddr_end_ = 0; uint64_t data_offset_ = 0; uint64_t data_vaddr_start_ = 0; uint64_t data_vaddr_end_ = 0; uint64_t eh_frame_hdr_offset_ = 0; int64_t eh_frame_hdr_section_bias_ = 0; Loading