dtrace: Fix up %rip for invop probes on x86

When a breakpoint exception is raised, the saved value of %rip points to
the instruction following the breakpoint.  However, when fetching the
value of %rip using regs[], it's more natural to provide the address of
the breakpoint itself, so modify the kinst and fbt providers accordingly.

Reported by:	khng
Reviewed by:	christos, khng
MFC after:	2 months
Differential Revision:	https://reviews.freebsd.org/D37218
This commit is contained in:
Mark Johnston 2022-10-31 19:11:36 -04:00
parent 05e640dc9e
commit 0e69c95915
2 changed files with 15 additions and 1 deletions

View File

@ -84,6 +84,12 @@ fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t scratch __unused)
if ((uintptr_t)fbt->fbtp_patchpoint != addr)
continue;
fbtrval = fbt->fbtp_rval;
/*
* Report the address of the breakpoint for the benefit
* of consumers fetching register values with regs[].
*/
frame->tf_rip--;
for (; fbt != NULL; fbt = fbt->fbtp_tracenext) {
ASSERT(fbt->fbtp_rval == fbtrval);
if (fbt->fbtp_roffset == 0) {
@ -143,6 +149,8 @@ fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t scratch __unused)
cpu->cpu_dtrace_caller = 0;
}
}
/* Advance to the instruction following the breakpoint. */
frame->tf_rip++;
return (fbtrval);
}

View File

@ -139,6 +139,12 @@ kinst_invop(uintptr_t addr, struct trapframe *frame, uintptr_t scratch)
if (kp == NULL)
return (0);
/*
* Report the address of the breakpoint for the benefit of consumers
* fetching register values with regs[].
*/
frame->tf_rip--;
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
cpu->cpu_dtrace_caller = stack[0];
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR);
@ -162,7 +168,7 @@ kinst_invop(uintptr_t addr, struct trapframe *frame, uintptr_t scratch)
if (kpmd->reg1 == -1 && kpmd->reg2 == -1) {
/* rip-relative */
rval = frame->tf_rip - 1 + kpmd->instlen;
rval = frame->tf_rip + kpmd->instlen;
} else {
/* indirect */
rval = kinst_regval(frame, kpmd->reg1) +