Loading libunwindstack/ElfInterface.cpp +27 −44 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <memory> #include <string> #include <utility> #include <7zCrc.h> #include <Xz.h> Loading Loading @@ -322,19 +323,13 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { // Skip the first header, it's always going to be NULL. offset += ehdr.e_shentsize; for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) { if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) { if (!memory_->Read(offset, &shdr, sizeof(shdr))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = offset + reinterpret_cast<uintptr_t>(&shdr.sh_type) - reinterpret_cast<uintptr_t>(&shdr); last_error_.address = offset; return false; } if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = offset; return false; } // Need to go get the information about the section that contains // the string terminated names. ShdrType str_shdr; Loading @@ -343,39 +338,19 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { return false; } uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize; if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) { if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_type) - reinterpret_cast<uintptr_t>(&str_shdr); last_error_.address = str_offset; return false; } if (str_shdr.sh_type != SHT_STRTAB) { last_error_.code = ERROR_UNWIND_INFO; return false; } if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset, sizeof(str_shdr.sh_offset))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_offset) - reinterpret_cast<uintptr_t>(&str_shdr); return false; } if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_size) - reinterpret_cast<uintptr_t>(&str_shdr); return false; } symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize, str_shdr.sh_offset, str_shdr.sh_size)); } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) { // Look for the .debug_frame and .gnu_debugdata. if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = offset + reinterpret_cast<uintptr_t>(&shdr.sh_name) - reinterpret_cast<uintptr_t>(&shdr); return false; } if (shdr.sh_name < sec_size) { std::string name; if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) { Loading @@ -394,14 +369,16 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { offset_ptr = &eh_frame_hdr_offset_; size_ptr = &eh_frame_hdr_size_; } if (offset_ptr != nullptr && memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) && memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) { if (offset_ptr != nullptr) { *offset_ptr = shdr.sh_offset; *size_ptr = shdr.sh_size; } } } } else if (shdr.sh_type == SHT_STRTAB) { // 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))); } } return true; Loading @@ -420,7 +397,7 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { soname_type_ = SONAME_INVALID; uint64_t soname_offset = 0; uint64_t strtab_offset = 0; uint64_t strtab_addr = 0; uint64_t strtab_size = 0; // Find the soname location from the dynamic headers section. Loading @@ -435,7 +412,7 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { } if (dyn.d_tag == DT_STRTAB) { strtab_offset = dyn.d_un.d_ptr; strtab_addr = dyn.d_un.d_ptr; } else if (dyn.d_tag == DT_STRSZ) { strtab_size = dyn.d_un.d_val; } else if (dyn.d_tag == DT_SONAME) { Loading @@ -445,8 +422,11 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { } } soname_offset += strtab_offset; if (soname_offset >= strtab_offset + strtab_size) { // Need to map the strtab address to the real offset. for (const auto& entry : strtabs_) { if (entry.first == strtab_addr) { soname_offset = entry.second + soname_offset; if (soname_offset >= entry.second + strtab_size) { return false; } if (!memory_->ReadString(soname_offset, &soname_)) { Loading @@ -456,6 +436,9 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { *soname = soname_; return true; } } return false; } template <typename SymType> bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name, Loading libunwindstack/include/unwindstack/ElfInterface.h +1 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,7 @@ class ElfInterface { ElfInterface* gnu_debugdata_interface_ = nullptr; std::vector<Symbols*> symbols_; std::vector<std::pair<uint64_t, uint64_t>> strtabs_; }; class ElfInterface32 : public ElfInterface { Loading libunwindstack/tests/ElfInterfaceTest.cpp +84 −89 Original line number Diff line number Diff line Loading @@ -63,15 +63,28 @@ class ElfInterfaceTest : public ::testing::Test { template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> void ManyPhdrs(); template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> enum SonameTestEnum : uint8_t { SONAME_NORMAL, SONAME_DTNULL_AFTER, SONAME_DTSIZE_SMALL, SONAME_MISSING_MAP, }; template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn> void SonameInit(SonameTestEnum test_type = SONAME_NORMAL); template <typename ElfInterfaceType> void Soname(); template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> template <typename ElfInterfaceType> void SonameAfterDtNull(); template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> template <typename ElfInterfaceType> void SonameSize(); template <typename ElfInterfaceType> void SonameMissingMap(); template <typename ElfType> void InitHeadersEhFrameTest(); Loading Loading @@ -465,17 +478,29 @@ TEST_F(ElfInterfaceTest, elf32_arm) { ASSERT_EQ(2U, elf_arm.total_entries()); } template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> void ElfInterfaceTest::Soname() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn> void ElfInterfaceTest::SonameInit(SonameTestEnum test_type) { Ehdr ehdr; memset(&ehdr, 0, sizeof(ehdr)); ehdr.e_shoff = 0x200; ehdr.e_shnum = 2; ehdr.e_shentsize = sizeof(Shdr); ehdr.e_phoff = 0x100; ehdr.e_phnum = 1; ehdr.e_phentsize = sizeof(Phdr); memory_.SetMemory(0, &ehdr, sizeof(ehdr)); Shdr shdr; memset(&shdr, 0, sizeof(shdr)); shdr.sh_type = SHT_STRTAB; if (test_type == SONAME_MISSING_MAP) { shdr.sh_addr = 0x20100; } else { shdr.sh_addr = 0x10100; } shdr.sh_offset = 0x10000; memory_.SetMemory(0x200 + sizeof(shdr), &shdr, sizeof(shdr)); Phdr phdr; memset(&phdr, 0, sizeof(phdr)); phdr.p_type = PT_DYNAMIC; Loading @@ -487,14 +512,24 @@ void ElfInterfaceTest::Soname() { Dyn dyn; dyn.d_tag = DT_STRTAB; dyn.d_un.d_ptr = 0x10000; dyn.d_un.d_ptr = 0x10100; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); dyn.d_tag = DT_STRSZ; if (test_type == SONAME_DTSIZE_SMALL) { dyn.d_un.d_val = 0x10; } else { dyn.d_un.d_val = 0x1000; } memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); if (test_type == SONAME_DTNULL_AFTER) { dyn.d_tag = DT_NULL; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); } dyn.d_tag = DT_SONAME; dyn.d_un.d_val = 0x10; Loading @@ -505,6 +540,11 @@ void ElfInterfaceTest::Soname() { memory_.SetMemory(offset, &dyn, sizeof(dyn)); SetStringMemory(0x10010, "fake_soname.so"); } template <typename ElfInterfaceType> void ElfInterfaceTest::Soname() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); uint64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); Loading @@ -516,55 +556,19 @@ void ElfInterfaceTest::Soname() { } TEST_F(ElfInterfaceTest, elf32_soname) { Soname<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>(); SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(); Soname<ElfInterface32>(); } TEST_F(ElfInterfaceTest, elf64_soname) { Soname<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>(); SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(); Soname<ElfInterface64>(); } template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> template <typename ElfInterfaceType> void ElfInterfaceTest::SonameAfterDtNull() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); Ehdr ehdr; memset(&ehdr, 0, sizeof(ehdr)); ehdr.e_phoff = 0x100; ehdr.e_phnum = 1; ehdr.e_phentsize = sizeof(Phdr); memory_.SetMemory(0, &ehdr, sizeof(ehdr)); Phdr phdr; memset(&phdr, 0, sizeof(phdr)); phdr.p_type = PT_DYNAMIC; phdr.p_offset = 0x2000; phdr.p_memsz = sizeof(Dyn) * 3; memory_.SetMemory(0x100, &phdr, sizeof(phdr)); Dyn dyn; uint64_t offset = 0x2000; dyn.d_tag = DT_STRTAB; dyn.d_un.d_ptr = 0x10000; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); dyn.d_tag = DT_STRSZ; dyn.d_un.d_val = 0x1000; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); dyn.d_tag = DT_NULL; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); dyn.d_tag = DT_SONAME; dyn.d_un.d_val = 0x10; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); SetStringMemory(0x10010, "fake_soname.so"); uint64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); EXPECT_EQ(0U, load_bias); Loading @@ -574,53 +578,42 @@ void ElfInterfaceTest::SonameAfterDtNull() { } TEST_F(ElfInterfaceTest, elf32_soname_after_dt_null) { SonameAfterDtNull<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>(); SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTNULL_AFTER); SonameAfterDtNull<ElfInterface32>(); } TEST_F(ElfInterfaceTest, elf64_soname_after_dt_null) { SonameAfterDtNull<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>(); SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTNULL_AFTER); SonameAfterDtNull<ElfInterface64>(); } template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> template <typename ElfInterfaceType> void ElfInterfaceTest::SonameSize() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); Ehdr ehdr; memset(&ehdr, 0, sizeof(ehdr)); ehdr.e_phoff = 0x100; ehdr.e_phnum = 1; ehdr.e_phentsize = sizeof(Phdr); memory_.SetMemory(0, &ehdr, sizeof(ehdr)); Phdr phdr; memset(&phdr, 0, sizeof(phdr)); phdr.p_type = PT_DYNAMIC; phdr.p_offset = 0x2000; phdr.p_memsz = sizeof(Dyn); memory_.SetMemory(0x100, &phdr, sizeof(phdr)); Dyn dyn; uint64_t offset = 0x2000; dyn.d_tag = DT_STRTAB; dyn.d_un.d_ptr = 0x10000; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); uint64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); EXPECT_EQ(0U, load_bias); dyn.d_tag = DT_STRSZ; dyn.d_un.d_val = 0x10; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); std::string name; ASSERT_FALSE(elf->GetSoname(&name)); } dyn.d_tag = DT_SONAME; dyn.d_un.d_val = 0x10; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); TEST_F(ElfInterfaceTest, elf32_soname_size) { SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTSIZE_SMALL); SonameSize<ElfInterface32>(); } dyn.d_tag = DT_NULL; memory_.SetMemory(offset, &dyn, sizeof(dyn)); TEST_F(ElfInterfaceTest, elf64_soname_size) { SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTSIZE_SMALL); SonameSize<ElfInterface64>(); } SetStringMemory(0x10010, "fake_soname.so"); // Verify that there is no map from STRTAB in the dynamic section to a // STRTAB entry in the section headers. template <typename ElfInterfaceType> void ElfInterfaceTest::SonameMissingMap() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); uint64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); Loading @@ -630,12 +623,14 @@ void ElfInterfaceTest::SonameSize() { ASSERT_FALSE(elf->GetSoname(&name)); } TEST_F(ElfInterfaceTest, elf32_soname_size) { SonameSize<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>(); TEST_F(ElfInterfaceTest, elf32_soname_missing_map) { SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_MISSING_MAP); SonameMissingMap<ElfInterface32>(); } TEST_F(ElfInterfaceTest, elf64_soname_size) { SonameSize<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>(); TEST_F(ElfInterfaceTest, elf64_soname_missing_map) { SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_MISSING_MAP); SonameMissingMap<ElfInterface64>(); } template <typename ElfType> Loading libunwindstack/tools/unwind_info.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,11 @@ int GetElfInfo(const char* file, uint64_t offset) { return 1; } std::string soname; if (elf.GetSoname(&soname)) { printf("Soname: %s\n", soname.c_str()); } ElfInterface* interface = elf.interface(); if (elf.machine_type() == EM_ARM) { DumpArm(reinterpret_cast<ElfInterfaceArm*>(interface)); Loading libunwindstack/tools/unwind_reg_info.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,11 @@ int GetInfo(const char* file, uint64_t pc) { return 1; } std::string soname; if (elf.GetSoname(&soname)) { printf("Soname: %s\n\n", soname.c_str()); } printf("PC 0x%" PRIx64 ":\n", pc); DwarfSection* section = interface->eh_frame(); Loading Loading
libunwindstack/ElfInterface.cpp +27 −44 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <memory> #include <string> #include <utility> #include <7zCrc.h> #include <Xz.h> Loading Loading @@ -322,19 +323,13 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { // Skip the first header, it's always going to be NULL. offset += ehdr.e_shentsize; for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) { if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) { if (!memory_->Read(offset, &shdr, sizeof(shdr))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = offset + reinterpret_cast<uintptr_t>(&shdr.sh_type) - reinterpret_cast<uintptr_t>(&shdr); last_error_.address = offset; return false; } if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = offset; return false; } // Need to go get the information about the section that contains // the string terminated names. ShdrType str_shdr; Loading @@ -343,39 +338,19 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { return false; } uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize; if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) { if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_type) - reinterpret_cast<uintptr_t>(&str_shdr); last_error_.address = str_offset; return false; } if (str_shdr.sh_type != SHT_STRTAB) { last_error_.code = ERROR_UNWIND_INFO; return false; } if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset, sizeof(str_shdr.sh_offset))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_offset) - reinterpret_cast<uintptr_t>(&str_shdr); return false; } if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_size) - reinterpret_cast<uintptr_t>(&str_shdr); return false; } symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize, str_shdr.sh_offset, str_shdr.sh_size)); } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) { // Look for the .debug_frame and .gnu_debugdata. if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) { last_error_.code = ERROR_MEMORY_INVALID; last_error_.address = offset + reinterpret_cast<uintptr_t>(&shdr.sh_name) - reinterpret_cast<uintptr_t>(&shdr); return false; } if (shdr.sh_name < sec_size) { std::string name; if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) { Loading @@ -394,14 +369,16 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { offset_ptr = &eh_frame_hdr_offset_; size_ptr = &eh_frame_hdr_size_; } if (offset_ptr != nullptr && memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) && memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) { if (offset_ptr != nullptr) { *offset_ptr = shdr.sh_offset; *size_ptr = shdr.sh_size; } } } } else if (shdr.sh_type == SHT_STRTAB) { // 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))); } } return true; Loading @@ -420,7 +397,7 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { soname_type_ = SONAME_INVALID; uint64_t soname_offset = 0; uint64_t strtab_offset = 0; uint64_t strtab_addr = 0; uint64_t strtab_size = 0; // Find the soname location from the dynamic headers section. Loading @@ -435,7 +412,7 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { } if (dyn.d_tag == DT_STRTAB) { strtab_offset = dyn.d_un.d_ptr; strtab_addr = dyn.d_un.d_ptr; } else if (dyn.d_tag == DT_STRSZ) { strtab_size = dyn.d_un.d_val; } else if (dyn.d_tag == DT_SONAME) { Loading @@ -445,8 +422,11 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { } } soname_offset += strtab_offset; if (soname_offset >= strtab_offset + strtab_size) { // Need to map the strtab address to the real offset. for (const auto& entry : strtabs_) { if (entry.first == strtab_addr) { soname_offset = entry.second + soname_offset; if (soname_offset >= entry.second + strtab_size) { return false; } if (!memory_->ReadString(soname_offset, &soname_)) { Loading @@ -456,6 +436,9 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) { *soname = soname_; return true; } } return false; } template <typename SymType> bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name, Loading
libunwindstack/include/unwindstack/ElfInterface.h +1 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,7 @@ class ElfInterface { ElfInterface* gnu_debugdata_interface_ = nullptr; std::vector<Symbols*> symbols_; std::vector<std::pair<uint64_t, uint64_t>> strtabs_; }; class ElfInterface32 : public ElfInterface { Loading
libunwindstack/tests/ElfInterfaceTest.cpp +84 −89 Original line number Diff line number Diff line Loading @@ -63,15 +63,28 @@ class ElfInterfaceTest : public ::testing::Test { template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> void ManyPhdrs(); template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> enum SonameTestEnum : uint8_t { SONAME_NORMAL, SONAME_DTNULL_AFTER, SONAME_DTSIZE_SMALL, SONAME_MISSING_MAP, }; template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn> void SonameInit(SonameTestEnum test_type = SONAME_NORMAL); template <typename ElfInterfaceType> void Soname(); template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> template <typename ElfInterfaceType> void SonameAfterDtNull(); template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> template <typename ElfInterfaceType> void SonameSize(); template <typename ElfInterfaceType> void SonameMissingMap(); template <typename ElfType> void InitHeadersEhFrameTest(); Loading Loading @@ -465,17 +478,29 @@ TEST_F(ElfInterfaceTest, elf32_arm) { ASSERT_EQ(2U, elf_arm.total_entries()); } template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> void ElfInterfaceTest::Soname() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn> void ElfInterfaceTest::SonameInit(SonameTestEnum test_type) { Ehdr ehdr; memset(&ehdr, 0, sizeof(ehdr)); ehdr.e_shoff = 0x200; ehdr.e_shnum = 2; ehdr.e_shentsize = sizeof(Shdr); ehdr.e_phoff = 0x100; ehdr.e_phnum = 1; ehdr.e_phentsize = sizeof(Phdr); memory_.SetMemory(0, &ehdr, sizeof(ehdr)); Shdr shdr; memset(&shdr, 0, sizeof(shdr)); shdr.sh_type = SHT_STRTAB; if (test_type == SONAME_MISSING_MAP) { shdr.sh_addr = 0x20100; } else { shdr.sh_addr = 0x10100; } shdr.sh_offset = 0x10000; memory_.SetMemory(0x200 + sizeof(shdr), &shdr, sizeof(shdr)); Phdr phdr; memset(&phdr, 0, sizeof(phdr)); phdr.p_type = PT_DYNAMIC; Loading @@ -487,14 +512,24 @@ void ElfInterfaceTest::Soname() { Dyn dyn; dyn.d_tag = DT_STRTAB; dyn.d_un.d_ptr = 0x10000; dyn.d_un.d_ptr = 0x10100; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); dyn.d_tag = DT_STRSZ; if (test_type == SONAME_DTSIZE_SMALL) { dyn.d_un.d_val = 0x10; } else { dyn.d_un.d_val = 0x1000; } memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); if (test_type == SONAME_DTNULL_AFTER) { dyn.d_tag = DT_NULL; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); } dyn.d_tag = DT_SONAME; dyn.d_un.d_val = 0x10; Loading @@ -505,6 +540,11 @@ void ElfInterfaceTest::Soname() { memory_.SetMemory(offset, &dyn, sizeof(dyn)); SetStringMemory(0x10010, "fake_soname.so"); } template <typename ElfInterfaceType> void ElfInterfaceTest::Soname() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); uint64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); Loading @@ -516,55 +556,19 @@ void ElfInterfaceTest::Soname() { } TEST_F(ElfInterfaceTest, elf32_soname) { Soname<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>(); SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(); Soname<ElfInterface32>(); } TEST_F(ElfInterfaceTest, elf64_soname) { Soname<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>(); SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(); Soname<ElfInterface64>(); } template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> template <typename ElfInterfaceType> void ElfInterfaceTest::SonameAfterDtNull() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); Ehdr ehdr; memset(&ehdr, 0, sizeof(ehdr)); ehdr.e_phoff = 0x100; ehdr.e_phnum = 1; ehdr.e_phentsize = sizeof(Phdr); memory_.SetMemory(0, &ehdr, sizeof(ehdr)); Phdr phdr; memset(&phdr, 0, sizeof(phdr)); phdr.p_type = PT_DYNAMIC; phdr.p_offset = 0x2000; phdr.p_memsz = sizeof(Dyn) * 3; memory_.SetMemory(0x100, &phdr, sizeof(phdr)); Dyn dyn; uint64_t offset = 0x2000; dyn.d_tag = DT_STRTAB; dyn.d_un.d_ptr = 0x10000; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); dyn.d_tag = DT_STRSZ; dyn.d_un.d_val = 0x1000; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); dyn.d_tag = DT_NULL; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); dyn.d_tag = DT_SONAME; dyn.d_un.d_val = 0x10; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); SetStringMemory(0x10010, "fake_soname.so"); uint64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); EXPECT_EQ(0U, load_bias); Loading @@ -574,53 +578,42 @@ void ElfInterfaceTest::SonameAfterDtNull() { } TEST_F(ElfInterfaceTest, elf32_soname_after_dt_null) { SonameAfterDtNull<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>(); SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTNULL_AFTER); SonameAfterDtNull<ElfInterface32>(); } TEST_F(ElfInterfaceTest, elf64_soname_after_dt_null) { SonameAfterDtNull<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>(); SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTNULL_AFTER); SonameAfterDtNull<ElfInterface64>(); } template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType> template <typename ElfInterfaceType> void ElfInterfaceTest::SonameSize() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); Ehdr ehdr; memset(&ehdr, 0, sizeof(ehdr)); ehdr.e_phoff = 0x100; ehdr.e_phnum = 1; ehdr.e_phentsize = sizeof(Phdr); memory_.SetMemory(0, &ehdr, sizeof(ehdr)); Phdr phdr; memset(&phdr, 0, sizeof(phdr)); phdr.p_type = PT_DYNAMIC; phdr.p_offset = 0x2000; phdr.p_memsz = sizeof(Dyn); memory_.SetMemory(0x100, &phdr, sizeof(phdr)); Dyn dyn; uint64_t offset = 0x2000; dyn.d_tag = DT_STRTAB; dyn.d_un.d_ptr = 0x10000; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); uint64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); EXPECT_EQ(0U, load_bias); dyn.d_tag = DT_STRSZ; dyn.d_un.d_val = 0x10; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); std::string name; ASSERT_FALSE(elf->GetSoname(&name)); } dyn.d_tag = DT_SONAME; dyn.d_un.d_val = 0x10; memory_.SetMemory(offset, &dyn, sizeof(dyn)); offset += sizeof(dyn); TEST_F(ElfInterfaceTest, elf32_soname_size) { SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTSIZE_SMALL); SonameSize<ElfInterface32>(); } dyn.d_tag = DT_NULL; memory_.SetMemory(offset, &dyn, sizeof(dyn)); TEST_F(ElfInterfaceTest, elf64_soname_size) { SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTSIZE_SMALL); SonameSize<ElfInterface64>(); } SetStringMemory(0x10010, "fake_soname.so"); // Verify that there is no map from STRTAB in the dynamic section to a // STRTAB entry in the section headers. template <typename ElfInterfaceType> void ElfInterfaceTest::SonameMissingMap() { std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_)); uint64_t load_bias = 0; ASSERT_TRUE(elf->Init(&load_bias)); Loading @@ -630,12 +623,14 @@ void ElfInterfaceTest::SonameSize() { ASSERT_FALSE(elf->GetSoname(&name)); } TEST_F(ElfInterfaceTest, elf32_soname_size) { SonameSize<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>(); TEST_F(ElfInterfaceTest, elf32_soname_missing_map) { SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_MISSING_MAP); SonameMissingMap<ElfInterface32>(); } TEST_F(ElfInterfaceTest, elf64_soname_size) { SonameSize<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>(); TEST_F(ElfInterfaceTest, elf64_soname_missing_map) { SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_MISSING_MAP); SonameMissingMap<ElfInterface64>(); } template <typename ElfType> Loading
libunwindstack/tools/unwind_info.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,11 @@ int GetElfInfo(const char* file, uint64_t offset) { return 1; } std::string soname; if (elf.GetSoname(&soname)) { printf("Soname: %s\n", soname.c_str()); } ElfInterface* interface = elf.interface(); if (elf.machine_type() == EM_ARM) { DumpArm(reinterpret_cast<ElfInterfaceArm*>(interface)); Loading
libunwindstack/tools/unwind_reg_info.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,11 @@ int GetInfo(const char* file, uint64_t pc) { return 1; } std::string soname; if (elf.GetSoname(&soname)) { printf("Soname: %s\n\n", soname.c_str()); } printf("PC 0x%" PRIx64 ":\n", pc); DwarfSection* section = interface->eh_frame(); Loading