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

Commit fbca3000 authored by Yong Li's avatar Yong Li
Browse files

Fix GetGlobalVariableOffset with tagged pointer in aarch64



Tagged pointer for aarch64 since Android R would lead top byte to have
random values. For example of a symbol from libart.so in a hwasan
enabled device in Android R:

1490: 8800000000b094a0   144 OBJECT  GLOBAL 24 __dex_debug_descriptor

We need to mask off the top byte so that the address range comparison
would work as intended.

Test: Ran new unit test

Signed-off-by: default avatarYong Li <yongl0722@gmail.com>
Change-Id: Ia8c638e16baff57740c569e9eaf9cfd1f5bd3fad
parent 451197cb
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -124,6 +124,12 @@ bool Elf::GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offs
    return false;
  }

  if (arch() == ARCH_ARM64) {
    // Tagged pointer after Android R would lead top byte to have random values
    // https://source.android.com/devices/tech/debug/tagged-pointers
    vaddr &= (1ULL << 56) - 1;
  }

  // Check the .data section.
  uint64_t vaddr_start = interface_->data_vaddr_start();
  if (vaddr >= vaddr_start && vaddr < interface_->data_vaddr_end()) {
+2 −0
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ class ElfFake : public Elf {

  void FakeSetLoadBias(uint64_t load_bias) { load_bias_ = load_bias; }

  void FakeSetArch(ArchEnum arch) { arch_ = arch; }

  void FakeSetInterface(ElfInterface* interface) { interface_.reset(interface); }
  void FakeSetGnuDebugdataInterface(ElfInterface* interface) {
    gnu_debugdata_interface_.reset(interface);
+42 −0
Original line number Diff line number Diff line
@@ -438,6 +438,48 @@ TEST_F(ElfTest, get_global_vaddr_in_dynamic_section) {
  EXPECT_EQ(0xc080U, offset);
}

TEST_F(ElfTest, get_global_vaddr_with_tagged_pointer) {
  ElfFake elf(memory_);
  elf.FakeSetValid(true);
  elf.FakeSetArch(ARCH_ARM64);

  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
  elf.FakeSetInterface(interface);
  interface->MockSetDataVaddrStart(0x500);
  interface->MockSetDataVaddrEnd(0x600);
  interface->MockSetDataOffset(0xa000);

  std::string global("something");
  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x8800000000000580),
                                 ::testing::Return(true)));

  uint64_t offset;
  ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
  EXPECT_EQ(0xa080U, offset);
}

TEST_F(ElfTest, get_global_vaddr_without_tagged_pointer) {
  ElfFake elf(memory_);
  elf.FakeSetValid(true);
  elf.FakeSetArch(ARCH_X86_64);

  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
  elf.FakeSetInterface(interface);
  interface->MockSetDataVaddrStart(0x8800000000000500);
  interface->MockSetDataVaddrEnd(0x8800000000000600);
  interface->MockSetDataOffset(0x880000000000a000);

  std::string global("something");
  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x8800000000000580),
                                 ::testing::Return(true)));

  uint64_t offset;
  ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
  EXPECT_EQ(0x880000000000a080U, offset);
}

TEST_F(ElfTest, is_valid_pc_elf_invalid) {
  ElfFake elf(memory_);
  elf.FakeSetValid(false);