Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7efed535 authored by Christopher Ferris's avatar Christopher Ferris Committed by Automerger Merge Worker
Browse files

Merge "libunwindstack: don't save pseudoregisters while evaluating Dwarf" am: e5c9bbd4

Original change: https://android-review.googlesource.com/c/platform/system/core/+/1403667

Change-Id: I8b25673da5b71fd3f40f34acaa6a78cae2bbe14f
parents 6eab53e0 e5c9bbd4
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -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;
  }
@@ -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) {
+35 −0
Original line number Diff line number Diff line
@@ -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, &regs, &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, &regs, &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, &regs, &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;
@@ -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;
+18 −0
Original line number Diff line number Diff line
@@ -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