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

Commit d49499d5 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Set elf_start_offset for invalid elf maps.

Add new unit tests to cover this case.

Bug: 133495043

Test: New unit tests pass.
Change-Id: I9ded5732c3c40197ebfddee3dcacc4aa07541ac0
parent 2184ecb8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -241,6 +241,7 @@ cc_test {
        "tests/files/offline/debug_frame_first_x86/*",
        "tests/files/offline/debug_frame_load_bias_arm/*",
        "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
        "tests/files/offline/invalid_elf_offset_arm/*",
        "tests/files/offline/jit_debug_arm/*",
        "tests/files/offline/jit_debug_x86/*",
        "tests/files/offline/jit_map_arm/*",
+7 −5
Original line number Diff line number Diff line
@@ -231,11 +231,13 @@ Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum exp
    }
  }

  if (!elf->valid()) {
    elf_start_offset = offset;
  } else if (prev_map != nullptr && elf_start_offset != offset &&
             prev_map->offset == elf_start_offset && prev_map->name == name) {
    // If there is a read-only map then a read-execute map that represents the
    // same elf object, make sure the previous map is using the same elf
    // object if it hasn't already been set.
  if (prev_map != nullptr && elf_start_offset != offset && prev_map->offset == elf_start_offset &&
      prev_map->name == name) {
    std::lock_guard<std::mutex> guard(prev_map->mutex_);
    if (prev_map->elf.get() == nullptr) {
      prev_map->elf = elf;
+31 −16
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ class UnwindOfflineTest : public ::testing::Test {
    free(cwd_);
  }

  void Init(const char* file_dir, ArchEnum arch) {
  void Init(const char* file_dir, ArchEnum arch, bool add_stack = true) {
    dir_ = TestGetFileDirectory() + "offline/" + file_dir;

    std::string data;
@@ -71,6 +71,7 @@ class UnwindOfflineTest : public ::testing::Test {
    maps_.reset(new BufferMaps(data.c_str()));
    ASSERT_TRUE(maps_->Parse());

    if (add_stack) {
      std::string stack_name(dir_ + "stack.data");
      struct stat st;
      if (stat(stack_name.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
@@ -89,6 +90,7 @@ class UnwindOfflineTest : public ::testing::Test {
        }
        process_memory_.reset(stack_memory.release());
      }
    }

    switch (arch) {
      case ARCH_ARM: {
@@ -1442,4 +1444,17 @@ TEST_F(UnwindOfflineTest, shared_lib_in_apk_single_map_arm64) {
  EXPECT_EQ(0x7be4f07d20ULL, unwinder.frames()[12].sp);
}

TEST_F(UnwindOfflineTest, invalid_elf_offset_arm) {
  ASSERT_NO_FATAL_FAILURE(Init("invalid_elf_offset_arm/", ARCH_ARM, false));

  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
  unwinder.Unwind();

  std::string frame_info(DumpFrames(unwinder));
  ASSERT_EQ(1U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
  EXPECT_EQ("  #00 pc 00aa7508  invalid.apk (offset 0x12e4000)\n", frame_info);
  EXPECT_EQ(0xc898f508, unwinder.frames()[0].pc);
  EXPECT_EQ(0xc2044218, unwinder.frames()[0].sp);
}

}  // namespace unwindstack
+1 −0
Original line number Diff line number Diff line
c7ee8000-c8c52fff r-xp  12e4000    00:00 0  invalid.apk
+16 −0
Original line number Diff line number Diff line
r0: c0434c00
r1: 2a4c9fbc
r2: 00000000
r3: c83ef1f9
r4: 00000004
r5: c2044904
r6: 00000000
r7: c20443b8
r8: 000b33ff
r9: c20444b0
r10: cac90740
r11: 00000000
ip: ed891ca4
sp: c2044218
lr: ed807265
pc: c898f508