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

Commit 239425b9 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Fix bug when doing signal handler lookup.

The new lld linker uses all non-zero offset executable maps. There was
a bug when trying to find if the stack is in a signal handler that caused
the code to read the wrong place in the elf. Fixed by not adding the elf
offset to the relative pc.

Also fixed the unwind_for_offline tool to dump multiple stacks if necessary.

Added new offline unit test that would have failed with the old code.

Bug: 79936827

Test: Ran unit tests and libbacktrace unit tests.
Test: Dumped backtraces of system pids.
Test: Ran 137-cfi art test.
Change-Id: Iaca8c18c2a314902e64c3f72831234297e8dcb1b
parent 3464bc4b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -202,6 +202,7 @@ cc_test {
        "tests/files/offline/jit_debug_x86/*",
        "tests/files/offline/jit_map_arm/*",
        "tests/files/offline/gnu_debugdata_arm/*",
        "tests/files/offline/offset_arm/*",
        "tests/files/offline/straddle_arm/*",
        "tests/files/offline/straddle_arm64/*",
    ],
+3 −3
Original line number Diff line number Diff line
@@ -160,14 +160,14 @@ uint64_t Elf::GetLastErrorAddress() {
}

// The relative pc is always relative to the start of the map from which it comes.
bool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, uint64_t elf_offset, Regs* regs,
               Memory* process_memory, bool* finished) {
bool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory,
               bool* finished) {
  if (!valid_) {
    return false;
  }

  // The relative pc expectd by StepIfSignalHandler is relative to the start of the elf.
  if (regs->StepIfSignalHandler(rel_pc + elf_offset, this, process_memory)) {
  if (regs->StepIfSignalHandler(rel_pc, this, process_memory)) {
    *finished = false;
    return true;
  }
+1 −2
Original line number Diff line number Diff line
@@ -220,8 +220,7 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
          in_device_map = true;
        } else {
          bool finished;
          stepped = elf->Step(rel_pc, step_pc, map_info->elf_offset, regs_, process_memory_.get(),
                              &finished);
          stepped = elf->Step(rel_pc, step_pc, regs_, process_memory_.get(), &finished);
          elf->GetLastError(&last_error_);
          if (stepped && finished) {
            break;
+2 −2
Original line number Diff line number Diff line
@@ -65,8 +65,8 @@ class Elf {

  uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);

  bool Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, uint64_t elf_offset, Regs* regs,
            Memory* process_memory, bool* finished);
  bool Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory,
            bool* finished);

  ElfInterface* CreateInterfaceFromMemory(Memory* memory);

+4 −4
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ TEST_F(ElfTest, elf_invalid) {
  ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset));

  bool finished;
  ASSERT_FALSE(elf.Step(0, 0, 0, nullptr, nullptr, &finished));
  ASSERT_FALSE(elf.Step(0, 0, nullptr, nullptr, &finished));
}

TEST_F(ElfTest, elf32_invalid_machine) {
@@ -330,7 +330,7 @@ TEST_F(ElfTest, step_in_signal_map) {
  elf.FakeSetValid(true);
  elf.FakeSetLoadBias(0);
  bool finished;
  ASSERT_TRUE(elf.Step(0x1000, 0x1000, 0x2000, &regs, &process_memory, &finished));
  ASSERT_TRUE(elf.Step(0x3000, 0x1000, &regs, &process_memory, &finished));
  EXPECT_FALSE(finished);
  EXPECT_EQ(15U, regs.pc());
  EXPECT_EQ(13U, regs.sp());
@@ -370,7 +370,7 @@ TEST_F(ElfTest, step_in_interface) {
  EXPECT_CALL(*interface, Step(0x1000, 0, &regs, &process_memory, &finished))
      .WillOnce(::testing::Return(true));

  ASSERT_TRUE(elf.Step(0x1004, 0x1000, 0x2000, &regs, &process_memory, &finished));
  ASSERT_TRUE(elf.Step(0x1004, 0x1000, &regs, &process_memory, &finished));
}

TEST_F(ElfTest, step_in_interface_non_zero_load_bias) {
@@ -388,7 +388,7 @@ TEST_F(ElfTest, step_in_interface_non_zero_load_bias) {
  EXPECT_CALL(*interface, Step(0x7300, 0x4000, &regs, &process_memory, &finished))
      .WillOnce(::testing::Return(true));

  ASSERT_TRUE(elf.Step(0x7304, 0x7300, 0x2000, &regs, &process_memory, &finished));
  ASSERT_TRUE(elf.Step(0x7304, 0x7300, &regs, &process_memory, &finished));
}

TEST_F(ElfTest, get_global_invalid_elf) {
Loading