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:
parent
1b23f9b9c3
commit
aeca5b8bc9
@ -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
|
||||||
|
@ -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 \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user