mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
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:
parent
756a67e15e
commit
cdfa49f258
2 changed files with 21 additions and 13 deletions
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
|
|
|
|||
Loading…
Reference in a new issue