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

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

Merge "Fix ARM program header values used for exidx."

parents 409465a2 f882a388
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -211,7 +211,7 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
      return false;
    }

    if (HandleType(offset, phdr.p_type, *load_bias)) {
    if (HandleType(offset, phdr.p_type)) {
      continue;
    }

+9 −7
Original line number Diff line number Diff line
@@ -87,20 +87,22 @@ bool ElfInterfaceArm::GetPrel31Addr(uint32_t offset, uint32_t* addr) {
#define PT_ARM_EXIDX 0x70000001
#endif

bool ElfInterfaceArm::HandleType(uint64_t offset, uint32_t type, uint64_t load_bias) {
bool ElfInterfaceArm::HandleType(uint64_t offset, uint32_t type) {
  if (type != PT_ARM_EXIDX) {
    return false;
  }

  Elf32_Phdr phdr;
  if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
  if (!memory_->ReadFully(offset, &phdr, sizeof(phdr))) {
    return true;
  }
  if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
    return true;
  }
  start_offset_ = phdr.p_vaddr - load_bias;
  total_entries_ = phdr.p_memsz / 8;

  // The offset already takes into account the load bias.
  start_offset_ = phdr.p_offset;

  // Always use filesz instead of memsz. In most cases they are the same,
  // but some shared libraries wind up setting one correctly and not the other.
  total_entries_ = phdr.p_filesz / 8;
  return true;
}

+1 −1
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ class ElfInterfaceArm : public ElfInterface32 {

  bool FindEntry(uint32_t pc, uint64_t* entry_offset);

  bool HandleType(uint64_t offset, uint32_t type, uint64_t load_bias) override;
  bool HandleType(uint64_t offset, uint32_t type) override;

  bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) override;

+1 −1
Original line number Diff line number Diff line
@@ -118,7 +118,7 @@ class ElfInterface {
  template <typename SymType>
  bool GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address);

  virtual bool HandleType(uint64_t, uint32_t, uint64_t) { return false; }
  virtual bool HandleType(uint64_t, uint32_t) { return false; }

  template <typename EhdrType>
  static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size);
+20 −35
Original line number Diff line number Diff line
@@ -245,56 +245,41 @@ TEST_F(ElfInterfaceArmTest, iterate) {
TEST_F(ElfInterfaceArmTest, HandleType_not_arm_exidx) {
  ElfInterfaceArmFake interface(&memory_);

  ASSERT_FALSE(interface.HandleType(0x1000, PT_NULL, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOAD, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_DYNAMIC, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_INTERP, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_NOTE, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_SHLIB, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_PHDR, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_TLS, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOOS, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIOS, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOPROC, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIPROC, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_EH_FRAME, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_STACK, 0));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_NULL));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOAD));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_DYNAMIC));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_INTERP));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_NOTE));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_SHLIB));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_PHDR));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_TLS));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOOS));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIOS));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOPROC));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIPROC));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_EH_FRAME));
  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_STACK));
}

TEST_F(ElfInterfaceArmTest, HandleType_arm_exidx) {
  ElfInterfaceArmFake interface(&memory_);

  Elf32_Phdr phdr;
  Elf32_Phdr phdr = {};
  interface.FakeSetStartOffset(0x1000);
  interface.FakeSetTotalEntries(100);
  phdr.p_vaddr = 0x2000;
  phdr.p_memsz = 0xa00;
  phdr.p_offset = 0x2000;
  phdr.p_filesz = 0xa00;

  // Verify that if reads fail, we don't set the values but still get true.
  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001, 0));
  ASSERT_EQ(0x1000U, interface.start_offset());
  ASSERT_EQ(100U, interface.total_entries());

  // Verify that if the second read fails, we still don't set the values.
  memory_.SetData32(
      0x1000 + reinterpret_cast<uint64_t>(&phdr.p_vaddr) - reinterpret_cast<uint64_t>(&phdr),
      phdr.p_vaddr);
  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001, 0));
  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001));
  ASSERT_EQ(0x1000U, interface.start_offset());
  ASSERT_EQ(100U, interface.total_entries());

  // Everything is correct and present.
  memory_.SetData32(
      0x1000 + reinterpret_cast<uint64_t>(&phdr.p_memsz) - reinterpret_cast<uint64_t>(&phdr),
      phdr.p_memsz);
  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001, 0));
  memory_.SetMemory(0x1000, &phdr, sizeof(phdr));
  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001));
  ASSERT_EQ(0x2000U, interface.start_offset());
  ASSERT_EQ(320U, interface.total_entries());

  // Non-zero load bias.
  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001, 0x1000));
  ASSERT_EQ(0x1000U, interface.start_offset());
  ASSERT_EQ(320U, interface.total_entries());
}

TEST_F(ElfInterfaceArmTest, StepExidx) {
Loading