dtrace: dtrace_getpcstack() tweaks for riscv

Backtraces for fbt probes are missing the caller's frame. Despite what
the inherited comment claims, we do need to insert this manually on
riscv. In fbt_invop(), set cpu_dtrace_caller to be the return address,
not addr.

We should not increment aframes within this function, since we begin the
main loop by unwinding past the current frame.

Plus some very small comment/style tweaks.

MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D37661
This commit is contained in:
Mitchell Horne 2023-01-11 14:06:02 -04:00
parent 756a67e15e
commit cdfa49f258
2 changed files with 21 additions and 13 deletions

View file

@ -64,42 +64,50 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
uint32_t *intrpc)
{
struct unwind_state state;
int scp_offset;
uintptr_t caller;
register_t sp;
int scp_offset;
int depth;
depth = 0;
caller = solaris_cpu[curcpu].cpu_dtrace_caller;
if (intrpc != 0) {
pcstack[depth++] = (pc_t) intrpc;
pcstack[depth++] = (pc_t)intrpc;
}
aframes++;
/*
* Construct the unwind state, starting from this function. This frame,
* and 'aframes' others will be skipped.
*/
__asm __volatile("mv %0, sp" : "=&r" (sp));
state.fp = (uintptr_t)__builtin_frame_address(0);
state.sp = sp;
state.sp = (uintptr_t)sp;
state.pc = (uintptr_t)dtrace_getpcstack;
while (depth < pcstack_limit) {
if (!unwind_frame(curthread, &state))
break;
if (!INKERNEL(state.pc) || !INKERNEL(state.fp))
if (!INKERNEL(state.pc) || !kstack_contains(curthread,
(vm_offset_t)state.fp, sizeof(uintptr_t)))
break;
/*
* NB: Unlike some other architectures, we don't need to
* explicitly insert cpu_dtrace_caller as it appears in the
* normal kernel stack trace rather than a special trap frame.
*/
if (aframes > 0) {
aframes--;
/*
* fbt_invop() records the return address at the time
* the FBT probe fires. We need to insert this into the
* backtrace manually, since the stack frame state at
* the time of the probe does not capture it.
*/
if (aframes == 0 && caller != 0)
pcstack[depth++] = caller;
} else {
pcstack[depth++] = state.pc;
}
}
for (; depth < pcstack_limit; depth++) {

View file

@ -57,7 +57,7 @@ fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval)
for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
cpu->cpu_dtrace_caller = addr;
cpu->cpu_dtrace_caller = frame->tf_ra - INSN_SIZE;
if (fbt->fbtp_roffset == 0) {
dtrace_probe(fbt->fbtp_id, frame->tf_a[0],