Loading libunwindstack/DwarfSection.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading libunwindstack/ElfInterfaceArm.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading libunwindstack/tests/DwarfSectionImplTest.cpp +18 −1 Original line number Diff line number Diff line Loading @@ -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, ®s, &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); Loading Loading @@ -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, Loading libunwindstack/tests/ElfInterfaceArmTest.cpp +36 −0 Original line number Diff line number Diff line Loading @@ -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, ®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 Loading
libunwindstack/DwarfSection.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading
libunwindstack/ElfInterfaceArm.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading
libunwindstack/tests/DwarfSectionImplTest.cpp +18 −1 Original line number Diff line number Diff line Loading @@ -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, ®s, &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); Loading Loading @@ -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, Loading
libunwindstack/tests/ElfInterfaceArmTest.cpp +36 −0 Original line number Diff line number Diff line Loading @@ -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, ®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