Merge "Move sp/pc not changing check into Unwinder."
This commit is contained in:
commit
15251c24b9
4 changed files with 80 additions and 23 deletions
|
|
@ -107,7 +107,6 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
|
|||
return false;
|
||||
}
|
||||
|
||||
AddressType prev_pc = regs->pc();
|
||||
AddressType prev_cfa = regs->sp();
|
||||
|
||||
AddressType cfa;
|
||||
|
|
@ -233,8 +232,8 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
|
|||
*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();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
|
|
|
|||
|
|
@ -87,8 +87,10 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
|
|||
bool return_address_attempt = false;
|
||||
bool adjust_pc = false;
|
||||
for (; frames_.size() < max_frames_;) {
|
||||
MapInfo* map_info = maps_->Find(regs_->pc());
|
||||
uint64_t cur_pc = regs_->pc();
|
||||
uint64_t cur_sp = regs_->sp();
|
||||
|
||||
MapInfo* map_info = maps_->Find(regs_->pc());
|
||||
uint64_t rel_pc;
|
||||
Elf* elf;
|
||||
if (map_info == nullptr) {
|
||||
|
|
@ -138,6 +140,7 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!stepped) {
|
||||
if (return_address_attempt) {
|
||||
// Remove the speculative frame.
|
||||
|
|
@ -157,6 +160,11 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
|
|||
} else {
|
||||
return_address_attempt = false;
|
||||
}
|
||||
|
||||
// If the pc and sp didn't change, then consider everything stopped.
|
||||
if (cur_pc == regs_->pc() && cur_sp == regs_->sp()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -431,22 +431,6 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
|
|||
EXPECT_EQ(0x80000000U, regs.pc());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_same_cfa_same_pc) {
|
||||
DwarfCie cie{.version = 3, .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] = 0x100;
|
||||
regs[8] = 0x2000;
|
||||
loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
|
||||
bool finished;
|
||||
ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
|
||||
EXPECT_EQ(0x2000U, regs.sp());
|
||||
EXPECT_EQ(0x100U, regs.pc());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) {
|
||||
ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
|
||||
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
|
||||
|
|
@ -872,9 +856,9 @@ REGISTER_TYPED_TEST_CASE_P(
|
|||
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_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,
|
||||
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,
|
||||
GetFdeFromOffset_32_no_augment_non_zero_segment_size, GetFdeFromOffset_32_augment,
|
||||
GetFdeFromOffset_64_no_augment, GetFdeFromOffset_cached, GetCfaLocationInfo_cie_not_cached,
|
||||
GetCfaLocationInfo_cie_cached, Log);
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ class UnwinderTest : public ::testing::Test {
|
|||
void SetUp() override {
|
||||
ElfInterfaceFake::FakeClear();
|
||||
regs_.FakeSetMachineType(EM_ARM);
|
||||
regs_.FakeSetReturnAddressValid(false);
|
||||
}
|
||||
|
||||
static MapsFake maps_;
|
||||
|
|
@ -610,6 +611,71 @@ TEST_F(UnwinderTest, map_ignore_suffixes) {
|
|||
EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
|
||||
}
|
||||
|
||||
// Verify that an unwind stops when the sp and pc don't change.
|
||||
TEST_F(UnwinderTest, sp_pc_do_not_change) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
|
||||
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
||||
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
|
||||
unwinder.Unwind();
|
||||
|
||||
ASSERT_EQ(3U, unwinder.NumFrames());
|
||||
|
||||
auto* frame = &unwinder.frames()[0];
|
||||
EXPECT_EQ(0U, frame->num);
|
||||
EXPECT_EQ(0U, frame->rel_pc);
|
||||
EXPECT_EQ(0x1000U, frame->pc);
|
||||
EXPECT_EQ(0x10000U, frame->sp);
|
||||
EXPECT_EQ("Frame0", frame->function_name);
|
||||
EXPECT_EQ(0U, frame->function_offset);
|
||||
EXPECT_EQ("/system/fake/libc.so", frame->map_name);
|
||||
EXPECT_EQ(0U, frame->map_offset);
|
||||
EXPECT_EQ(0x1000U, frame->map_start);
|
||||
EXPECT_EQ(0x8000U, frame->map_end);
|
||||
EXPECT_EQ(0U, frame->map_load_bias);
|
||||
EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
|
||||
|
||||
frame = &unwinder.frames()[1];
|
||||
EXPECT_EQ(1U, frame->num);
|
||||
EXPECT_EQ(0x400U, frame->rel_pc);
|
||||
EXPECT_EQ(0x33400U, frame->pc);
|
||||
EXPECT_EQ(0x10010U, frame->sp);
|
||||
EXPECT_EQ("Frame1", frame->function_name);
|
||||
EXPECT_EQ(1U, frame->function_offset);
|
||||
EXPECT_EQ("/fake/compressed.so", frame->map_name);
|
||||
EXPECT_EQ(0U, frame->map_offset);
|
||||
EXPECT_EQ(0x33000U, frame->map_start);
|
||||
EXPECT_EQ(0x34000U, frame->map_end);
|
||||
EXPECT_EQ(0U, frame->map_load_bias);
|
||||
EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
|
||||
|
||||
frame = &unwinder.frames()[2];
|
||||
EXPECT_EQ(2U, frame->num);
|
||||
EXPECT_EQ(0x500U, frame->rel_pc);
|
||||
EXPECT_EQ(0x33500U, frame->pc);
|
||||
EXPECT_EQ(0x10020U, frame->sp);
|
||||
EXPECT_EQ("Frame2", frame->function_name);
|
||||
EXPECT_EQ(2U, frame->function_offset);
|
||||
EXPECT_EQ("/fake/compressed.so", frame->map_name);
|
||||
EXPECT_EQ(0U, frame->map_offset);
|
||||
EXPECT_EQ(0x33000U, frame->map_start);
|
||||
EXPECT_EQ(0x34000U, frame->map_end);
|
||||
EXPECT_EQ(0U, frame->map_load_bias);
|
||||
EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
|
||||
}
|
||||
|
||||
// Verify format frame code.
|
||||
TEST_F(UnwinderTest, format_frame_static) {
|
||||
FrameData frame;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue