Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Feb 2015 12:20:22 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r278997 - in head/sys: cddl/dev/dtrace/arm conf
Message-ID:  <201502191220.t1JCKMRA035789@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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				   \



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502191220.t1JCKMRA035789>