Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45b57053 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Fix static GetLoadBias function."

parents 685949da 6c8ac562
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -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;
+124 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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));