Use the ARM unwinder with dtrace to extract the stack when asked. With this

dtrace is able to display a stack trace similar to the one below.

# dtrace -p 603 -n 'tcp:kernel::receive { stack(); }'
  0     70                         :receive
              kernel`ip_input+0x140
              kernel`netisr_dispatch_src+0xb8
              kernel`ether_demux+0x1c4
              kernel`ether_nh_input+0x3a8
              kernel`netisr_dispatch_src+0xb8
              kernel`ether_input+0x60
              kernel`cpsw_intr_rx+0xac
              kernel`intr_event_execute_handlers+0x128
              kernel`ithread_loop+0xb4
              kernel`fork_exit+0x84
              kernel`swi_exit
              kernel`swi_exit

Tested by:	gnn
Sponsored by:	ABT Systems Ltd
This commit is contained in:
Andrew Turner 2015-02-19 12:20:21 +00:00
parent 1b23f9b9c3
commit aeca5b8bc9
2 changed files with 29 additions and 90 deletions

View File

@ -69,9 +69,10 @@ void
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
uint32_t *intrpc) uint32_t *intrpc)
{ {
u_int32_t *frame, *lastframe; struct unwind_state state;
int scp_offset; register_t sp;
int depth = 0; int scp_offset;
int depth = 0;
pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller; pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
if (intrpc != 0) if (intrpc != 0)
@ -79,23 +80,17 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
aframes++; aframes++;
frame = (u_int32_t *)__builtin_frame_address(0);; __asm __volatile("mov %0, sp" : "=&r" (sp));
lastframe = NULL;
scp_offset = -(get_pc_str_offset() >> 2);
while ((frame != NULL) && (depth < pcstack_limit)) { state.registers[FP] = (uint32_t)__builtin_frame_address(0);
db_addr_t scp; state.registers[SP] = sp;
#if 0 state.registers[LR] = (uint32_t)__builtin_return_address(0);
u_int32_t savecode; state.registers[PC] = (uint32_t)dtrace_getpcstack;
int r;
u_int32_t *rp;
#endif
/* while (depth < pcstack_limit) {
* In theory, the SCP isn't guaranteed to be in the function int done;
* that generated the stack frame. We hope for the best.
*/ done = unwind_stack_one(&state, 1);
scp = frame[FR_SCP];
if (aframes > 0) { if (aframes > 0) {
aframes--; aframes--;
@ -104,39 +99,10 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
} }
} }
else { else {
pcstack[depth++] = scp; pcstack[depth++] = state.registers[PC];
} }
#if 0 if (done)
savecode = ((u_int32_t *)scp)[scp_offset];
if ((savecode & 0x0e100000) == 0x08000000) {
/* Looks like an STM */
rp = frame - 4;
for (r = 10; r >= 0; r--) {
if (savecode & (1 << r)) {
/* register r == *rp-- */
}
}
}
#endif
/*
* Switch to next frame up
*/
if (frame[FR_RFP] == 0)
break; /* Top of stack */
lastframe = frame;
frame = (u_int32_t *)(frame[FR_RFP]);
if (INKERNEL((int)frame)) {
/* staying in kernel */
if (frame <= lastframe) {
/* bad frame pointer */
break;
}
}
else
break; break;
} }
@ -176,55 +142,28 @@ dtrace_getarg(int arg, int aframes)
int int
dtrace_getstackdepth(int aframes) dtrace_getstackdepth(int aframes)
{ {
u_int32_t *frame, *lastframe; struct unwind_state state;
int scp_offset; register_t sp;
int depth = 1; int scp_offset;
int done = 0;
int depth = 1;
frame = (u_int32_t *)__builtin_frame_address(0);; __asm __volatile("mov %0, sp" : "=&r" (sp));
lastframe = NULL;
scp_offset = -(get_pc_str_offset() >> 2);
while (frame != NULL) { state.registers[FP] = (uint32_t)__builtin_frame_address(0);
db_addr_t scp; state.registers[SP] = sp;
#if 0 state.registers[LR] = (uint32_t)__builtin_return_address(0);
u_int32_t savecode; state.registers[PC] = (uint32_t)dtrace_getstackdepth;
int r;
u_int32_t *rp;
#endif
/*
* In theory, the SCP isn't guaranteed to be in the function
* that generated the stack frame. We hope for the best.
*/
scp = frame[FR_SCP];
do {
done = unwind_stack_one(&state, 1);
depth++; depth++;
} while (!done);
/*
* Switch to next frame up
*/
if (frame[FR_RFP] == 0)
break; /* Top of stack */
lastframe = frame;
frame = (u_int32_t *)(frame[FR_RFP]);
if (INKERNEL((int)frame)) {
/* staying in kernel */
if (frame <= lastframe) {
/* bad frame pointer */
break;
}
}
else
break;
}
if (depth < aframes) if (depth < aframes)
return 0; return 0;
else else
return depth - aframes; return depth - aframes;
} }
ulong_t ulong_t

View File

@ -57,7 +57,7 @@ arm/arm/trap.c optional !armv6
arm/arm/trap-v6.c optional armv6 arm/arm/trap-v6.c optional armv6
arm/arm/uio_machdep.c standard arm/arm/uio_machdep.c standard
arm/arm/undefined.c standard arm/arm/undefined.c standard
arm/arm/unwind.c optional ddb arm/arm/unwind.c optional ddb | kdtrace_hooks
arm/arm/vm_machdep.c standard arm/arm/vm_machdep.c standard
arm/arm/vfp.c standard arm/arm/vfp.c standard
board_id.h standard \ board_id.h standard \