Loading libunwindstack/Elf.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,10 @@ bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) { return true; } bool Elf::GetBuildID(std::string* build_id) { return valid_ && interface_->GetBuildID(build_id); } void Elf::GetLastError(ErrorData* data) { if (valid_) { *data = interface_->last_error(); Loading libunwindstack/ElfInterface.cpp +62 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,56 @@ void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) } } template <typename NhdrType> bool ElfInterface::ReadBuildID(std::string* build_id) { // Ensure there is no overflow in any of the calulations below. uint64_t tmp; if (__builtin_add_overflow(gnu_build_id_offset_, gnu_build_id_size_, &tmp)) { return false; } uint64_t offset = 0; while (offset < gnu_build_id_size_) { if (gnu_build_id_size_ - offset < sizeof(NhdrType)) { return false; } NhdrType hdr; if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &hdr, sizeof(hdr))) { return false; } offset += sizeof(hdr); if (gnu_build_id_size_ - offset < hdr.n_namesz) { return false; } if (hdr.n_namesz > 0) { std::string name(hdr.n_namesz, '\0'); if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &(name[0]), hdr.n_namesz)) { return false; } // Trim trailing \0 as GNU is stored as a C string in the ELF file. if (name.back() == '\0') name.resize(name.size() - 1); // Align hdr.n_namesz to next power multiple of 4. See man 5 elf. offset += (hdr.n_namesz + 3) & ~3; if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) { if (gnu_build_id_size_ - offset < hdr.n_descsz) { return false; } build_id->resize(hdr.n_descsz); return memory_->ReadFully(gnu_build_id_offset_ + offset, &(*build_id)[0], hdr.n_descsz); } } // Align hdr.n_descsz to next power multiple of 4. See man 5 elf. offset += (hdr.n_descsz + 3) & ~3; } return false; } template <typename EhdrType, typename ShdrType> void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { uint64_t offset = ehdr.e_shoff; Loading Loading @@ -308,6 +358,15 @@ void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { // In order to read soname, keep track of address to offset mapping. strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr), static_cast<uint64_t>(shdr.sh_offset))); } else if (shdr.sh_type == SHT_NOTE) { if (shdr.sh_name < sec_size) { std::string name; if (memory_->ReadString(sec_offset + shdr.sh_name, &name) && name == ".note.gnu.build-id") { gnu_build_id_offset_ = shdr.sh_offset; gnu_build_id_size_ = shdr.sh_size; } } } } } Loading Loading @@ -492,6 +551,9 @@ template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&); template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&); template bool ElfInterface::ReadBuildID<Elf32_Nhdr>(std::string*); template bool ElfInterface::ReadBuildID<Elf64_Nhdr>(std::string*); template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*); template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*); Loading libunwindstack/include/unwindstack/Elf.h +2 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,8 @@ class Elf { bool GetGlobalVariable(const std::string& name, uint64_t* memory_address); bool GetBuildID(std::string* build_id); uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info); bool Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory, Loading libunwindstack/include/unwindstack/ElfInterface.h +18 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ class ElfInterface { virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0; virtual bool GetBuildID(std::string* build_id) = 0; virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished); virtual bool IsValidPc(uint64_t pc); Loading @@ -85,6 +87,8 @@ class ElfInterface { 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_; } uint64_t gnu_build_id_offset() { return gnu_build_id_offset_; } uint64_t gnu_build_id_size() { return gnu_build_id_size_; } DwarfSection* eh_frame() { return eh_frame_.get(); } DwarfSection* debug_frame() { return debug_frame_.get(); } Loading Loading @@ -123,6 +127,9 @@ class ElfInterface { template <typename EhdrType> static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size); template <typename NhdrType> bool ReadBuildID(std::string* build_id); Memory* memory_; std::unordered_map<uint64_t, LoadInfo> pt_loads_; Loading @@ -143,6 +150,9 @@ class ElfInterface { uint64_t gnu_debugdata_offset_ = 0; uint64_t gnu_debugdata_size_ = 0; uint64_t gnu_build_id_offset_ = 0; uint64_t gnu_build_id_size_ = 0; uint8_t soname_type_ = SONAME_UNKNOWN; std::string soname_; Loading Loading @@ -182,6 +192,10 @@ class ElfInterface32 : public ElfInterface { return ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(name, memory_address); } bool GetBuildID(std::string* build_id) { return ElfInterface::ReadBuildID<Elf32_Nhdr>(build_id); } static void GetMaxSize(Memory* memory, uint64_t* size) { GetMaxSizeWithTemplate<Elf32_Ehdr>(memory, size); } Loading Loading @@ -212,6 +226,10 @@ class ElfInterface64 : public ElfInterface { return ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(name, memory_address); } bool GetBuildID(std::string* build_id) { return ElfInterface::ReadBuildID<Elf64_Nhdr>(build_id); } static void GetMaxSize(Memory* memory, uint64_t* size) { GetMaxSizeWithTemplate<Elf64_Ehdr>(memory, size); } Loading libunwindstack/tests/ElfFake.h +3 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,9 @@ class ElfInterfaceFake : public ElfInterface { bool GetFunctionName(uint64_t, std::string*, uint64_t*) override; bool GetGlobalVariable(const std::string&, uint64_t*) override; bool GetBuildID(std::string*) override { return false; } bool Step(uint64_t, Regs*, Memory*, bool*) override; Loading Loading
libunwindstack/Elf.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,10 @@ bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) { return true; } bool Elf::GetBuildID(std::string* build_id) { return valid_ && interface_->GetBuildID(build_id); } void Elf::GetLastError(ErrorData* data) { if (valid_) { *data = interface_->last_error(); Loading
libunwindstack/ElfInterface.cpp +62 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,56 @@ void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) } } template <typename NhdrType> bool ElfInterface::ReadBuildID(std::string* build_id) { // Ensure there is no overflow in any of the calulations below. uint64_t tmp; if (__builtin_add_overflow(gnu_build_id_offset_, gnu_build_id_size_, &tmp)) { return false; } uint64_t offset = 0; while (offset < gnu_build_id_size_) { if (gnu_build_id_size_ - offset < sizeof(NhdrType)) { return false; } NhdrType hdr; if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &hdr, sizeof(hdr))) { return false; } offset += sizeof(hdr); if (gnu_build_id_size_ - offset < hdr.n_namesz) { return false; } if (hdr.n_namesz > 0) { std::string name(hdr.n_namesz, '\0'); if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &(name[0]), hdr.n_namesz)) { return false; } // Trim trailing \0 as GNU is stored as a C string in the ELF file. if (name.back() == '\0') name.resize(name.size() - 1); // Align hdr.n_namesz to next power multiple of 4. See man 5 elf. offset += (hdr.n_namesz + 3) & ~3; if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) { if (gnu_build_id_size_ - offset < hdr.n_descsz) { return false; } build_id->resize(hdr.n_descsz); return memory_->ReadFully(gnu_build_id_offset_ + offset, &(*build_id)[0], hdr.n_descsz); } } // Align hdr.n_descsz to next power multiple of 4. See man 5 elf. offset += (hdr.n_descsz + 3) & ~3; } return false; } template <typename EhdrType, typename ShdrType> void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { uint64_t offset = ehdr.e_shoff; Loading Loading @@ -308,6 +358,15 @@ void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { // In order to read soname, keep track of address to offset mapping. strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr), static_cast<uint64_t>(shdr.sh_offset))); } else if (shdr.sh_type == SHT_NOTE) { if (shdr.sh_name < sec_size) { std::string name; if (memory_->ReadString(sec_offset + shdr.sh_name, &name) && name == ".note.gnu.build-id") { gnu_build_id_offset_ = shdr.sh_offset; gnu_build_id_size_ = shdr.sh_size; } } } } } Loading Loading @@ -492,6 +551,9 @@ template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&); template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&); template bool ElfInterface::ReadBuildID<Elf32_Nhdr>(std::string*); template bool ElfInterface::ReadBuildID<Elf64_Nhdr>(std::string*); template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*); template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*); Loading
libunwindstack/include/unwindstack/Elf.h +2 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,8 @@ class Elf { bool GetGlobalVariable(const std::string& name, uint64_t* memory_address); bool GetBuildID(std::string* build_id); uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info); bool Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory, Loading
libunwindstack/include/unwindstack/ElfInterface.h +18 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ class ElfInterface { virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0; virtual bool GetBuildID(std::string* build_id) = 0; virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished); virtual bool IsValidPc(uint64_t pc); Loading @@ -85,6 +87,8 @@ class ElfInterface { 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_; } uint64_t gnu_build_id_offset() { return gnu_build_id_offset_; } uint64_t gnu_build_id_size() { return gnu_build_id_size_; } DwarfSection* eh_frame() { return eh_frame_.get(); } DwarfSection* debug_frame() { return debug_frame_.get(); } Loading Loading @@ -123,6 +127,9 @@ class ElfInterface { template <typename EhdrType> static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size); template <typename NhdrType> bool ReadBuildID(std::string* build_id); Memory* memory_; std::unordered_map<uint64_t, LoadInfo> pt_loads_; Loading @@ -143,6 +150,9 @@ class ElfInterface { uint64_t gnu_debugdata_offset_ = 0; uint64_t gnu_debugdata_size_ = 0; uint64_t gnu_build_id_offset_ = 0; uint64_t gnu_build_id_size_ = 0; uint8_t soname_type_ = SONAME_UNKNOWN; std::string soname_; Loading Loading @@ -182,6 +192,10 @@ class ElfInterface32 : public ElfInterface { return ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(name, memory_address); } bool GetBuildID(std::string* build_id) { return ElfInterface::ReadBuildID<Elf32_Nhdr>(build_id); } static void GetMaxSize(Memory* memory, uint64_t* size) { GetMaxSizeWithTemplate<Elf32_Ehdr>(memory, size); } Loading Loading @@ -212,6 +226,10 @@ class ElfInterface64 : public ElfInterface { return ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(name, memory_address); } bool GetBuildID(std::string* build_id) { return ElfInterface::ReadBuildID<Elf64_Nhdr>(build_id); } static void GetMaxSize(Memory* memory, uint64_t* size) { GetMaxSizeWithTemplate<Elf64_Ehdr>(memory, size); } Loading
libunwindstack/tests/ElfFake.h +3 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,9 @@ class ElfInterfaceFake : public ElfInterface { bool GetFunctionName(uint64_t, std::string*, uint64_t*) override; bool GetGlobalVariable(const std::string&, uint64_t*) override; bool GetBuildID(std::string*) override { return false; } bool Step(uint64_t, Regs*, Memory*, bool*) override; Loading