Merge "Fix static GetLoadBias function."
This commit is contained in:
commit
45b570530b
|
@ -187,8 +187,13 @@ uint64_t ElfInterface::GetLoadBias(Memory* memory) {
|
|||
if (!memory->ReadFully(offset, &phdr, sizeof(phdr))) {
|
||||
return 0;
|
||||
}
|
||||
if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
|
||||
return phdr.p_vaddr;
|
||||
|
||||
// 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 0;
|
||||
|
|
|
@ -131,6 +131,12 @@ class ElfInterfaceTest : public ::testing::Test {
|
|||
template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
|
||||
void BuildIDSectionTooSmallForHeader();
|
||||
|
||||
template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
|
||||
void CheckLoadBiasInFirstPhdr(uint64_t load_bias);
|
||||
|
||||
template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
|
||||
void CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr, uint64_t load_bias);
|
||||
|
||||
MemoryFake memory_;
|
||||
};
|
||||
|
||||
|
@ -1495,4 +1501,122 @@ TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header64) {
|
|||
BuildIDSectionTooSmallForHeader<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
|
||||
}
|
||||
|
||||
template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
|
||||
void ElfInterfaceTest::CheckLoadBiasInFirstPhdr(uint64_t load_bias) {
|
||||
Ehdr ehdr = {};
|
||||
ehdr.e_phoff = 0x100;
|
||||
ehdr.e_phnum = 2;
|
||||
ehdr.e_phentsize = sizeof(Phdr);
|
||||
memory_.SetMemory(0, &ehdr, sizeof(ehdr));
|
||||
|
||||
Phdr phdr = {};
|
||||
phdr.p_type = PT_LOAD;
|
||||
phdr.p_offset = 0;
|
||||
phdr.p_vaddr = load_bias;
|
||||
phdr.p_memsz = 0x10000;
|
||||
phdr.p_flags = PF_R | PF_X;
|
||||
phdr.p_align = 0x1000;
|
||||
memory_.SetMemory(0x100, &phdr, sizeof(phdr));
|
||||
|
||||
memset(&phdr, 0, sizeof(phdr));
|
||||
phdr.p_type = PT_LOAD;
|
||||
phdr.p_offset = 0x1000;
|
||||
phdr.p_memsz = 0x2000;
|
||||
phdr.p_flags = PF_R | PF_X;
|
||||
phdr.p_align = 0x1000;
|
||||
memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
|
||||
|
||||
uint64_t static_load_bias = ElfInterface::GetLoadBias<Ehdr, Phdr>(&memory_);
|
||||
ASSERT_EQ(load_bias, static_load_bias);
|
||||
|
||||
std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
|
||||
uint64_t init_load_bias = 0;
|
||||
ASSERT_TRUE(elf->Init(&init_load_bias));
|
||||
ASSERT_EQ(init_load_bias, static_load_bias);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_zero_32) {
|
||||
CheckLoadBiasInFirstPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_zero_64) {
|
||||
CheckLoadBiasInFirstPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_non_zero_32) {
|
||||
CheckLoadBiasInFirstPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x1000);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_non_zero_64) {
|
||||
CheckLoadBiasInFirstPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x1000);
|
||||
}
|
||||
|
||||
template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
|
||||
void ElfInterfaceTest::CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr,
|
||||
uint64_t load_bias) {
|
||||
Ehdr ehdr = {};
|
||||
ehdr.e_phoff = 0x100;
|
||||
ehdr.e_phnum = 3;
|
||||
ehdr.e_phentsize = sizeof(Phdr);
|
||||
memory_.SetMemory(0, &ehdr, sizeof(ehdr));
|
||||
|
||||
Phdr phdr = {};
|
||||
phdr.p_type = PT_LOAD;
|
||||
phdr.p_memsz = 0x10000;
|
||||
phdr.p_flags = PF_R;
|
||||
phdr.p_align = 0x1000;
|
||||
memory_.SetMemory(0x100, &phdr, sizeof(phdr));
|
||||
|
||||
memset(&phdr, 0, sizeof(phdr));
|
||||
phdr.p_type = PT_LOAD;
|
||||
phdr.p_offset = offset;
|
||||
phdr.p_vaddr = vaddr;
|
||||
phdr.p_memsz = 0x2000;
|
||||
phdr.p_flags = PF_R | PF_X;
|
||||
phdr.p_align = 0x1000;
|
||||
memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
|
||||
|
||||
// Second executable load should be ignored for load bias computation.
|
||||
memset(&phdr, 0, sizeof(phdr));
|
||||
phdr.p_type = PT_LOAD;
|
||||
phdr.p_offset = 0x1234;
|
||||
phdr.p_vaddr = 0x2000;
|
||||
phdr.p_memsz = 0x2000;
|
||||
phdr.p_flags = PF_R | PF_X;
|
||||
phdr.p_align = 0x1000;
|
||||
memory_.SetMemory(0x200 + sizeof(phdr), &phdr, sizeof(phdr));
|
||||
|
||||
uint64_t static_load_bias = ElfInterface::GetLoadBias<Ehdr, Phdr>(&memory_);
|
||||
ASSERT_EQ(load_bias, static_load_bias);
|
||||
|
||||
std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
|
||||
uint64_t init_load_bias = 0;
|
||||
ASSERT_TRUE(elf->Init(&init_load_bias));
|
||||
ASSERT_EQ(init_load_bias, static_load_bias);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_32) {
|
||||
CheckLoadBiasInFirstExecPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x1000, 0x1000, 0);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_64) {
|
||||
CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x1000, 0x1000, 0);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_exec_non_zero_32) {
|
||||
CheckLoadBiasInFirstExecPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x1000, 0x4000, 0x3000);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_exec_non_zero_64) {
|
||||
CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x1000, 0x4000, 0x3000);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_from_error_32) {
|
||||
CheckLoadBiasInFirstExecPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x5000, 0x1000, 0);
|
||||
}
|
||||
|
||||
TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_from_error_64) {
|
||||
CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x5000, 0x1000, 0);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -141,6 +141,7 @@ static void InitElfData(MemoryFake* memory, uint64_t offset) {
|
|||
phdr.p_type = PT_NULL;
|
||||
memory->SetMemory(offset + 0x5000, &phdr, sizeof(phdr));
|
||||
phdr.p_type = PT_LOAD;
|
||||
phdr.p_flags = PF_X;
|
||||
phdr.p_offset = 0;
|
||||
phdr.p_vaddr = 0xe000;
|
||||
memory->SetMemory(offset + 0x5000 + sizeof(phdr), &phdr, sizeof(phdr));
|
||||
|
|
Loading…
Reference in New Issue