Merge "libunwindstack: don't save pseudoregisters while evaluating Dwarf"
This commit is contained in:
commit
e5c9bbd453
3 changed files with 65 additions and 12 deletions
|
|
@ -465,13 +465,9 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3
|
||||||
eval_info->return_address_undefined = true;
|
eval_info->return_address_undefined = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DWARF_LOCATION_PSEUDO_REGISTER: {
|
case DWARF_LOCATION_PSEUDO_REGISTER:
|
||||||
if (!eval_info->regs_info.regs->SetPseudoRegister(reg, loc->values[0])) {
|
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
|
||||||
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -543,11 +539,15 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
|
||||||
// Skip this unknown register.
|
// Skip this unknown register.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) {
|
||||||
|
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
|
||||||
reg_ptr = eval_info.regs_info.Save(reg);
|
return false;
|
||||||
if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
|
}
|
||||||
return false;
|
} else {
|
||||||
|
reg_ptr = eval_info.regs_info.Save(reg);
|
||||||
|
if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -492,6 +492,40 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
|
||||||
EXPECT_EQ(0x80000000U, regs.pc());
|
EXPECT_EQ(0x80000000U, regs.pc());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register_invalid) {
|
||||||
|
DwarfCie cie{.return_address_register = 5};
|
||||||
|
RegsImplFake<TypeParam> regs(10);
|
||||||
|
regs.set_pseudo_reg(11);
|
||||||
|
dwarf_loc_regs_t loc_regs;
|
||||||
|
|
||||||
|
loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
|
||||||
|
loc_regs[1] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
|
||||||
|
bool finished;
|
||||||
|
ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
|
||||||
|
EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
|
||||||
|
|
||||||
|
loc_regs.clear();
|
||||||
|
loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
|
||||||
|
loc_regs[12] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
|
||||||
|
ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
|
||||||
|
EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register) {
|
||||||
|
DwarfCie cie{.return_address_register = 5};
|
||||||
|
RegsImplFake<TypeParam> regs(10);
|
||||||
|
regs.set_pseudo_reg(11);
|
||||||
|
dwarf_loc_regs_t loc_regs;
|
||||||
|
|
||||||
|
loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
|
||||||
|
loc_regs[11] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
|
||||||
|
bool finished;
|
||||||
|
ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
|
||||||
|
uint64_t pseudo_value = 0;
|
||||||
|
ASSERT_TRUE(regs.GetPseudoRegister(11, &pseudo_value));
|
||||||
|
EXPECT_EQ(20U, pseudo_value);
|
||||||
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
|
TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
|
||||||
DwarfCie cie{};
|
DwarfCie cie{};
|
||||||
cie.cfa_instructions_offset = 0x3000;
|
cie.cfa_instructions_offset = 0x3000;
|
||||||
|
|
@ -581,6 +615,7 @@ REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_n
|
||||||
Eval_invalid_register, Eval_different_reg_locations,
|
Eval_invalid_register, Eval_different_reg_locations,
|
||||||
Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
|
Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
|
||||||
Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
|
Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
|
||||||
|
Eval_pseudo_register_invalid, Eval_pseudo_register,
|
||||||
GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
|
GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
|
||||||
|
|
||||||
typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
|
typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
|
||||||
|
|
|
||||||
|
|
@ -83,15 +83,33 @@ class RegsImplFake : public RegsImpl<TypeParam> {
|
||||||
uint64_t sp() override { return fake_sp_; }
|
uint64_t sp() override { return fake_sp_; }
|
||||||
void set_pc(uint64_t pc) override { fake_pc_ = pc; }
|
void set_pc(uint64_t pc) override { fake_pc_ = pc; }
|
||||||
void set_sp(uint64_t sp) override { fake_sp_ = sp; }
|
void set_sp(uint64_t sp) override { fake_sp_ = sp; }
|
||||||
|
void set_pseudo_reg(uint64_t reg) { fake_pseudo_reg_ = reg; }
|
||||||
|
|
||||||
bool SetPcFromReturnAddress(Memory*) override { return false; }
|
bool SetPcFromReturnAddress(Memory*) override { return false; }
|
||||||
bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
|
bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
|
||||||
|
|
||||||
|
bool SetPseudoRegister(uint16_t reg, uint64_t value) override {
|
||||||
|
if (fake_pseudo_reg_ != reg) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fake_pseudo_reg_value_ = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool GetPseudoRegister(uint16_t reg, uint64_t* value) override {
|
||||||
|
if (fake_pseudo_reg_ != reg) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*value = fake_pseudo_reg_value_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Regs* Clone() override { return nullptr; }
|
Regs* Clone() override { return nullptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t fake_pc_ = 0;
|
uint64_t fake_pc_ = 0;
|
||||||
uint64_t fake_sp_ = 0;
|
uint64_t fake_sp_ = 0;
|
||||||
|
uint16_t fake_pseudo_reg_ = 0;
|
||||||
|
uint64_t fake_pseudo_reg_value_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace unwindstack
|
} // namespace unwindstack
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue