Merge "If the pc is set to zero, the unwind is done."
This commit is contained in:
commit
09123383cb
4 changed files with 61 additions and 4 deletions
|
|
@ -225,11 +225,13 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
|
||||||
// Find the return address location.
|
// Find the return address location.
|
||||||
if (return_address_undefined) {
|
if (return_address_undefined) {
|
||||||
cur_regs->set_pc(0);
|
cur_regs->set_pc(0);
|
||||||
*finished = true;
|
|
||||||
} else {
|
} else {
|
||||||
cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
|
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);
|
cur_regs->set_sp(cfa);
|
||||||
// Return false if the unwind is not finished or the cfa and pc didn't change.
|
// 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();
|
return *finished || prev_cfa != cfa || prev_pc != cur_regs->pc();
|
||||||
|
|
|
||||||
|
|
@ -121,8 +121,10 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory,
|
||||||
}
|
}
|
||||||
regs_arm->set_sp(arm.cfa());
|
regs_arm->set_sp(arm.cfa());
|
||||||
(*regs_arm)[ARM_REG_SP] = regs_arm->sp();
|
(*regs_arm)[ARM_REG_SP] = regs_arm->sp();
|
||||||
*finished = false;
|
|
||||||
return_value = true;
|
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) {
|
if (arm.status() == ARM_STATUS_NO_UNWIND) {
|
||||||
|
|
|
||||||
|
|
@ -340,6 +340,23 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
|
||||||
EXPECT_EQ(0x10U, regs.sp());
|
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, ®s, &finished));
|
||||||
|
EXPECT_TRUE(finished);
|
||||||
|
EXPECT_EQ(0U, regs.pc());
|
||||||
|
EXPECT_EQ(0x10U, regs.sp());
|
||||||
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
|
TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
|
||||||
DwarfCie cie{.return_address_register = 5};
|
DwarfCie cie{.return_address_register = 5};
|
||||||
RegsImplFake<TypeParam> regs(10, 9);
|
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_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_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_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,
|
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_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,
|
GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment,
|
||||||
|
|
|
||||||
|
|
@ -401,4 +401,40 @@ TEST_F(ElfInterfaceArmTest, StepExidx_refuse_unwind) {
|
||||||
ASSERT_EQ(0x1234U, regs.pc());
|
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, ®s, &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, ®s, &process_memory_, &finished));
|
||||||
|
ASSERT_TRUE(finished);
|
||||||
|
ASSERT_EQ(0U, regs.pc());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace unwindstack
|
} // namespace unwindstack
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue