svn commit: r278997 - in head/sys: cddl/dev/dtrace/arm conf
Andrew Turner
andrew at FreeBSD.org
Thu Feb 19 12:20:22 UTC 2015
Author: andrew
Date: Thu Feb 19 12:20:21 2015
New Revision: 278997
URL: https://svnweb.freebsd.org/changeset/base/278997
Log:
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
Modified:
head/sys/cddl/dev/dtrace/arm/dtrace_isa.c
head/sys/conf/files.arm
Modified: head/sys/cddl/dev/dtrace/arm/dtrace_isa.c
==============================================================================
--- head/sys/cddl/dev/dtrace/arm/dtrace_isa.c Thu Feb 19 12:06:57 2015 (r278996)
+++ head/sys/cddl/dev/dtrace/arm/dtrace_isa.c Thu Feb 19 12:20:21 2015 (r278997)
@@ -69,9 +69,10 @@ void
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
uint32_t *intrpc)
{
- u_int32_t *frame, *lastframe;
- int scp_offset;
- int depth = 0;
+ struct unwind_state state;
+ register_t sp;
+ int scp_offset;
+ int depth = 0;
pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
if (intrpc != 0)
@@ -79,23 +80,17 @@ dtrace_getpcstack(pc_t *pcstack, int pcs
aframes++;
- frame = (u_int32_t *)__builtin_frame_address(0);;
- lastframe = NULL;
- scp_offset = -(get_pc_str_offset() >> 2);
-
- while ((frame != NULL) && (depth < pcstack_limit)) {
- db_addr_t scp;
-#if 0
- u_int32_t savecode;
- 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];
+ __asm __volatile("mov %0, sp" : "=&r" (sp));
+
+ state.registers[FP] = (uint32_t)__builtin_frame_address(0);
+ state.registers[SP] = sp;
+ state.registers[LR] = (uint32_t)__builtin_return_address(0);
+ state.registers[PC] = (uint32_t)dtrace_getpcstack;
+
+ while (depth < pcstack_limit) {
+ int done;
+
+ done = unwind_stack_one(&state, 1);
if (aframes > 0) {
aframes--;
@@ -104,39 +99,10 @@ dtrace_getpcstack(pc_t *pcstack, int pcs
}
}
else {
- pcstack[depth++] = scp;
+ pcstack[depth++] = state.registers[PC];
}
-#if 0
- 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
+ if (done)
break;
}
@@ -176,55 +142,28 @@ dtrace_getarg(int arg, int aframes)
int
dtrace_getstackdepth(int aframes)
{
- u_int32_t *frame, *lastframe;
- int scp_offset;
- int depth = 1;
-
- frame = (u_int32_t *)__builtin_frame_address(0);;
- lastframe = NULL;
- scp_offset = -(get_pc_str_offset() >> 2);
-
- while (frame != NULL) {
- db_addr_t scp;
-#if 0
- u_int32_t savecode;
- 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];
+ struct unwind_state state;
+ register_t sp;
+ int scp_offset;
+ int done = 0;
+ int depth = 1;
+
+ __asm __volatile("mov %0, sp" : "=&r" (sp));
+
+ state.registers[FP] = (uint32_t)__builtin_frame_address(0);
+ state.registers[SP] = sp;
+ state.registers[LR] = (uint32_t)__builtin_return_address(0);
+ state.registers[PC] = (uint32_t)dtrace_getstackdepth;
+ do {
+ done = unwind_stack_one(&state, 1);
depth++;
-
- /*
- * 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;
- }
+ } while (!done);
if (depth < aframes)
return 0;
else
return depth - aframes;
-
}
ulong_t
Modified: head/sys/conf/files.arm
==============================================================================
--- head/sys/conf/files.arm Thu Feb 19 12:06:57 2015 (r278996)
+++ head/sys/conf/files.arm Thu Feb 19 12:20:21 2015 (r278997)
@@ -57,7 +57,7 @@ arm/arm/trap.c optional !armv6
arm/arm/trap-v6.c optional armv6
arm/arm/uio_machdep.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/vfp.c standard
board_id.h standard \
More information about the svn-src-all
mailing list