Merge "Fix soname reading code."
This commit is contained in:
commit
76eda07ff6
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <7zCrc.h>
|
||||
#include <Xz.h>
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -445,16 +422,22 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
|
|||
}
|
||||
}
|
||||
|
||||
soname_offset += strtab_offset;
|
||||
if (soname_offset >= strtab_offset + strtab_size) {
|
||||
return false;
|
||||
// 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_)) {
|
||||
return false;
|
||||
}
|
||||
soname_type_ = SONAME_VALID;
|
||||
*soname = soname_;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!memory_->ReadString(soname_offset, &soname_)) {
|
||||
return false;
|
||||
}
|
||||
soname_type_ = SONAME_VALID;
|
||||
*soname = soname_;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename SymType>
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -487,15 +512,25 @@ 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;
|
||||
dyn.d_un.d_val = 0x1000;
|
||||
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;
|
||||
memory_.SetMemory(offset, &dyn, sizeof(dyn));
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -574,54 +578,19 @@ 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);
|
||||
|
||||
dyn.d_tag = DT_STRSZ;
|
||||
dyn.d_un.d_val = 0x10;
|
||||
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);
|
||||
|
||||
dyn.d_tag = DT_NULL;
|
||||
memory_.SetMemory(offset, &dyn, sizeof(dyn));
|
||||
|
||||
SetStringMemory(0x10010, "fake_soname.so");
|
||||
|
||||
uint64_t load_bias = 0;
|
||||
ASSERT_TRUE(elf->Init(&load_bias));
|
||||
EXPECT_EQ(0U, load_bias);
|
||||
|
@ -631,11 +600,37 @@ void ElfInterfaceTest::SonameSize() {
|
|||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, elf32_soname_size) {
|
||||
SonameSize<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
|
||||
SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTSIZE_SMALL);
|
||||
SonameSize<ElfInterface32>();
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, elf64_soname_size) {
|
||||
SonameSize<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
|
||||
SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTSIZE_SMALL);
|
||||
SonameSize<ElfInterface64>();
|
||||
}
|
||||
|
||||
// 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));
|
||||
EXPECT_EQ(0U, load_bias);
|
||||
|
||||
std::string name;
|
||||
ASSERT_FALSE(elf->GetSoname(&name));
|
||||
}
|
||||
|
||||
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_missing_map) {
|
||||
SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_MISSING_MAP);
|
||||
SonameMissingMap<ElfInterface64>();
|
||||
}
|
||||
|
||||
template <typename ElfType>
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -71,6 +71,11 @@ int main(int argc, char** argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
std::string soname;
|
||||
if (elf.GetSoname(&soname)) {
|
||||
printf("Soname: %s\n\n", soname.c_str());
|
||||
}
|
||||
|
||||
switch (elf.machine_type()) {
|
||||
case EM_ARM:
|
||||
printf("ABI: arm\n");
|
||||
|
|
Loading…
Reference in New Issue