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                                   \
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to