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

Commit 05c57129 authored by Christopher Ferris's avatar Christopher Ferris Committed by android-build-merger
Browse files

Merge "Fix static GetLoadBias function." am: 45b57053 am: 009a10db

am: 3bc3da2d

Change-Id: I9b89b69370786ee293d175b19abbdbaf3a7f8b11
parents 549bcc9b 3bc3da2d
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));