Loading libunwindstack/DwarfSection.cpp +12 −12 Original line number Diff line number Diff line Loading @@ -465,13 +465,9 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3 eval_info->return_address_undefined = true; } break; case DWARF_LOCATION_PSEUDO_REGISTER: { if (!eval_info->regs_info.regs->SetPseudoRegister(reg, loc->values[0])) { case DWARF_LOCATION_PSEUDO_REGISTER: last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; return false; } break; } default: break; } Loading Loading @@ -543,13 +539,17 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me // Skip this unknown register. continue; } if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) { last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; return false; } } else { reg_ptr = eval_info.regs_info.Save(reg); if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { return false; } } } // Find the return address location. if (eval_info.return_address_undefined) { Loading libunwindstack/tests/DwarfSectionImplTest.cpp +35 −0 Original line number Diff line number Diff line Loading @@ -492,6 +492,40 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) { 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) { DwarfCie cie{}; cie.cfa_instructions_offset = 0x3000; Loading Loading @@ -581,6 +615,7 @@ REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_n 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_pseudo_register_invalid, Eval_pseudo_register, GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log); typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes; Loading libunwindstack/tests/RegsFake.h +18 −0 Original line number Diff line number Diff line Loading @@ -83,15 +83,33 @@ class RegsImplFake : public RegsImpl<TypeParam> { uint64_t sp() override { return fake_sp_; } void set_pc(uint64_t pc) override { fake_pc_ = pc; } 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 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; } private: uint64_t fake_pc_ = 0; uint64_t fake_sp_ = 0; uint16_t fake_pseudo_reg_ = 0; uint64_t fake_pseudo_reg_value_ = 0; }; } // namespace unwindstack Loading Loading
libunwindstack/DwarfSection.cpp +12 −12 Original line number Diff line number Diff line Loading @@ -465,13 +465,9 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3 eval_info->return_address_undefined = true; } break; case DWARF_LOCATION_PSEUDO_REGISTER: { if (!eval_info->regs_info.regs->SetPseudoRegister(reg, loc->values[0])) { case DWARF_LOCATION_PSEUDO_REGISTER: last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; return false; } break; } default: break; } Loading Loading @@ -543,13 +539,17 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me // Skip this unknown register. continue; } if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) { last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; return false; } } else { reg_ptr = eval_info.regs_info.Save(reg); if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { return false; } } } // Find the return address location. if (eval_info.return_address_undefined) { Loading
libunwindstack/tests/DwarfSectionImplTest.cpp +35 −0 Original line number Diff line number Diff line Loading @@ -492,6 +492,40 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) { 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) { DwarfCie cie{}; cie.cfa_instructions_offset = 0x3000; Loading Loading @@ -581,6 +615,7 @@ REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_n 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_pseudo_register_invalid, Eval_pseudo_register, GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log); typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes; Loading
libunwindstack/tests/RegsFake.h +18 −0 Original line number Diff line number Diff line Loading @@ -83,15 +83,33 @@ class RegsImplFake : public RegsImpl<TypeParam> { uint64_t sp() override { return fake_sp_; } void set_pc(uint64_t pc) override { fake_pc_ = pc; } 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 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; } private: uint64_t fake_pc_ = 0; uint64_t fake_sp_ = 0; uint16_t fake_pseudo_reg_ = 0; uint64_t fake_pseudo_reg_value_ = 0; }; } // namespace unwindstack Loading