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

Commit 2502a60e authored by Christopher Ferris's avatar Christopher Ferris
Browse files

If the pc is set to zero, the unwind is done.

Bug: 68047085

Test: Ran new unit tests, verified new unwinder does not show an
Test: extra pc zero frame for arm 32 bit processes.
Change-Id: Ic6532e56fbb786a8b7d41638abae777c2d0f1d59
parent 26b614dd
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -225,11 +225,13 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
  // Find the return address location.
  if (return_address_undefined) {
    cur_regs->set_pc(0);
    *finished = true;
  } else {
    cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
    *finished = false;
  }

  // If the pc was set to zero, consider this the final frame.
  *finished = (cur_regs->pc() == 0) ? true : false;

  cur_regs->set_sp(cfa);
  // Return false if the unwind is not finished or the cfa and pc didn't change.
  return *finished || prev_cfa != cfa || prev_pc != cur_regs->pc();
+3 −1
Original line number Diff line number Diff line
@@ -121,8 +121,10 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory,
    }
    regs_arm->set_sp(arm.cfa());
    (*regs_arm)[ARM_REG_SP] = regs_arm->sp();
    *finished = false;
    return_value = true;

    // If the pc was set to zero, consider this the final frame.
    *finished = (regs_arm->pc() == 0) ? true : false;
  }

  if (arm.status() == ARM_STATUS_NO_UNWIND) {
+18 −1
Original line number Diff line number Diff line
@@ -340,6 +340,23 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
  EXPECT_EQ(0x10U, regs.sp());
}

TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
  DwarfCie cie{.return_address_register = 5};
  RegsImplFake<TypeParam> regs(10, 9);
  dwarf_loc_regs_t loc_regs;

  regs.set_pc(0x100);
  regs.set_sp(0x2000);
  regs[5] = 0;
  regs[8] = 0x10;
  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
  bool finished;
  ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
  EXPECT_TRUE(finished);
  EXPECT_EQ(0U, regs.pc());
  EXPECT_EQ(0x10U, regs.sp());
}

TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
  DwarfCie cie{.return_address_register = 5};
  RegsImplFake<TypeParam> regs(10, 9);
@@ -854,7 +871,7 @@ REGISTER_TYPED_TEST_CASE_P(
    Eval_cfa_expr_is_register, Eval_cfa_expr, Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa,
    Eval_cfa_bad, Eval_cfa_register_prev, Eval_cfa_register_from_value, Eval_double_indirection,
    Eval_invalid_register, Eval_different_reg_locations, Eval_return_address_undefined,
    Eval_return_address, Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
    Eval_pc_zero, Eval_return_address, Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
    Eval_same_cfa_same_pc, GetCie_fail_should_not_cache, GetCie_32_version_check,
    GetCie_negative_data_alignment_factor, GetCie_64_no_augment, GetCie_augment, GetCie_version_3,
    GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment,
+36 −0
Original line number Diff line number Diff line
@@ -401,4 +401,40 @@ TEST_F(ElfInterfaceArmTest, StepExidx_refuse_unwind) {
  ASSERT_EQ(0x1234U, regs.pc());
}

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

  interface.FakeSetStartOffset(0x1000);
  interface.FakeSetTotalEntries(1);
  memory_.SetData32(0x1000, 0x6000);
  // Set the pc using a pop r15 command.
  memory_.SetData32(0x1004, 0x808800b0);

  // pc value of zero.
  process_memory_.SetData32(0x10000, 0);

  RegsArm regs;
  regs[ARM_REG_SP] = 0x10000;
  regs[ARM_REG_LR] = 0x20000;
  regs.set_sp(regs[ARM_REG_SP]);
  regs.set_pc(0x1234);

  bool finished;
  ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
  ASSERT_TRUE(finished);
  ASSERT_EQ(0U, regs.pc());

  // Now set the pc from the lr register (pop r14).
  memory_.SetData32(0x1004, 0x808400b0);

  regs[ARM_REG_SP] = 0x10000;
  regs[ARM_REG_LR] = 0x20000;
  regs.set_sp(regs[ARM_REG_SP]);
  regs.set_pc(0x1234);

  ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
  ASSERT_TRUE(finished);
  ASSERT_EQ(0U, regs.pc());
}

}  // namespace unwindstack