[vm] Fix more cases of the profiler failing to identify the entry frame.
TEST=dart-fuzz Bug: https://github.com/dart-lang/sdk/issues/63105 Change-Id: I081a719a1d91c0e003a45ce1249e7856aa46a530 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/495784 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
9c90b215c9
commit
3e05df3856
@@ -5268,8 +5268,10 @@ void Assembler::LeaveDartFrame(intptr_t fp_sp_dist) {
|
||||
subi(PP, PP, kHeapObjectTag);
|
||||
}
|
||||
set_constant_pool_allowed(false);
|
||||
lx(FP, Address(SP, fp_offset));
|
||||
// Update RA first so the profiler can identify the frame as the entry frame
|
||||
// after FP is updated but before the return instruction.
|
||||
lx(RA, Address(SP, ra_offset));
|
||||
lx(FP, Address(SP, fp_offset));
|
||||
addi(SP, SP, -fp_sp_dist);
|
||||
}
|
||||
|
||||
|
||||
@@ -1349,18 +1349,27 @@ void Simulator::HandleRList(Instr* instr, bool load) {
|
||||
set_register(rn, rn_val);
|
||||
}
|
||||
|
||||
if (rlist == ((1 << FP) | (1 << PC))) {
|
||||
// Special case `ldmia {fp, pc}` for LeaveDartFrame so that the profiler
|
||||
// does not get confused by observing the update to fp before pc when our
|
||||
// caller is the entry stub, i.e., failing to identify the entry frame. On
|
||||
// real hardware, the profiler's signal handler cannot observe a partially
|
||||
// executued load-multiple instruction.
|
||||
// Special case `ldmia {fp, lr/pc}` for LeaveDartFrame[AndReturn] so that
|
||||
// the profiler does not get confused by observing the update to fp before
|
||||
// lr/pc when our caller is the entry stub, i.e., failing to identify the
|
||||
// entry frame. On real hardware, the profiler's signal handler cannot
|
||||
// observe a partially executued load-multiple instruction.
|
||||
if (load && rlist == ((1 << FP) | (1 << PC))) {
|
||||
COMPILE_ASSERT(FP < PC);
|
||||
int32_t new_fp = ReadW(address, instr);
|
||||
address += 4;
|
||||
int32_t new_pc = ReadW(address, instr);
|
||||
address += 4;
|
||||
set_register(PC, new_pc);
|
||||
set_register(FP, new_fp);
|
||||
} else if (load && rlist == ((1 << FP) | (1 << LR))) {
|
||||
COMPILE_ASSERT(FP < LR);
|
||||
int32_t new_fp = ReadW(address, instr);
|
||||
address += 4;
|
||||
int32_t new_lr = ReadW(address, instr);
|
||||
address += 4;
|
||||
set_register(LR, new_lr);
|
||||
set_register(FP, new_fp);
|
||||
} else {
|
||||
int reg = 0;
|
||||
while (rlist != 0) {
|
||||
@@ -1592,6 +1601,11 @@ DART_FORCE_INLINE void Simulator::DecodeType01(Instr* instr) {
|
||||
Register rm = instr->RmField();
|
||||
int32_t rm_val = get_register(rm);
|
||||
intptr_t pc = get_pc();
|
||||
// Set LR first so that the profiler does not get confused by
|
||||
// observing the update to PC without the update to LR when we are
|
||||
// calling out of the entry stub, i.e., failing to indentify the entry
|
||||
// stub. On real hardware, the profiler's signal handler cannot
|
||||
// observe a partially execute BLR.
|
||||
set_register(LR, pc + Instr::kInstrSize);
|
||||
set_pc(rm_val);
|
||||
break;
|
||||
|
||||
@@ -2052,8 +2052,13 @@ void Simulator::DecodeUnconditionalBranchReg(Instr* instr) {
|
||||
const Register rn = instr->RnField();
|
||||
const int64_t dest = get_register(rn, instr->RnMode());
|
||||
const int64_t ret = get_pc() + Instr::kInstrSize;
|
||||
set_pc(dest);
|
||||
// Set LR first so that the profiler does not get confused by
|
||||
// observing the update to PC without the update to LR when we are
|
||||
// calling out of the entry stub, i.e., failing to indentify the entry
|
||||
// stub. On real hardware, the profiler's signal handler cannot
|
||||
// observe a partially execute BLR.
|
||||
set_register(instr, LR, ret);
|
||||
set_pc(dest);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
|
||||
@@ -1047,6 +1047,11 @@ void Simulator::Interpret(CInstr instr) {
|
||||
} else if (instr.rs2() == ZR) {
|
||||
// JALR
|
||||
uintx_t target = get_xreg(instr.rs1());
|
||||
// Set RA first so that the profiler does not get confused by
|
||||
// observing the update to PC without the update to RA when we are
|
||||
// calling out of the entry stub, i.e., failing to indentify the entry
|
||||
// stub. On real hardware, the profiler's signal handler cannot
|
||||
// observe a partially execute JALR.
|
||||
set_xreg(RA, pc_ + instr.length());
|
||||
pc_ = target;
|
||||
CheckLandingPad(instr.rs1());
|
||||
@@ -1295,6 +1300,11 @@ DART_FORCE_INLINE
|
||||
void Simulator::InterpretJALR(Instr instr) {
|
||||
uintx_t base = get_xreg(instr.rs1());
|
||||
uintx_t offset = static_cast<uintx_t>(instr.itype_imm());
|
||||
// Set RA first so that the profiler does not get confused by
|
||||
// observing the update to PC without the update to RA when we are
|
||||
// calling out of the entry stub, i.e., failing to indentify the entry
|
||||
// stub. On real hardware, the profiler's signal handler cannot
|
||||
// observe a partially execute JALR.
|
||||
set_xreg(instr.rd(), pc_ + instr.length());
|
||||
pc_ = base + offset;
|
||||
CheckLandingPad(instr.rs1());
|
||||
|
||||
Reference in New Issue
Block a user