Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Nov 2019 15:56:27 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r354647 - in head/sys/i386: i386 include
Message-ID:  <201911121556.xACFuR79010070@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Tue Nov 12 15:56:27 2019
New Revision: 354647
URL: https://svnweb.freebsd.org/changeset/base/354647

Log:
  i386: stop guessing the address of the trap frame in ddb backtrace.
  
  Save the address of the trap frame in %ebp on kernel entry.  This
  automatically provides it in struct i386_frame.f_frame to unwinder.
  
  While there, more accurately handle the terminating frames,
  
  Reviewed by:	avg, markj
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week
  Differential revision:	https://reviews.freebsd.org/D22321

Modified:
  head/sys/i386/i386/db_trace.c
  head/sys/i386/include/asmacros.h

Modified: head/sys/i386/i386/db_trace.c
==============================================================================
--- head/sys/i386/i386/db_trace.c	Tue Nov 12 15:51:47 2019	(r354646)
+++ head/sys/i386/i386/db_trace.c	Tue Nov 12 15:56:27 2019	(r354647)
@@ -297,7 +297,6 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, st
 {
 	struct trapframe *tf;
 	int frame_type;
-	int narg;
 	int eip, esp, ebp;
 	db_expr_t offset;
 	c_db_sym_t sym;
@@ -317,14 +316,6 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, st
 	 */
 	frame_type = NORMAL;
 
-	/*
-	 * This is the number of arguments that a syscall / trap / interrupt
-	 * service routine passes to its callee.  This number is used only for
-	 * special frame types.  In most cases there is one argument: the trap
-	 * frame address.
-	 */
-	narg = 1;
-
 	if (eip >= PMAP_TRM_MIN_ADDRESS) {
 		sym = db_search_symbol(eip - 1 - setidt_disp, DB_STGY_ANY,
 		    &offset);
@@ -338,8 +329,6 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, st
 			frame_type = TRAP;
 		else if (strncmp(name, "Xatpic_intr", 11) == 0 ||
 		    strncmp(name, "Xapic_isr", 9) == 0) {
-			/* Additional argument: vector number. */
-			narg = 2;
 			frame_type = INTERRUPT;
 		} else if (strcmp(name, "Xlcall_syscall") == 0 ||
 		    strcmp(name, "Xint0x80_syscall") == 0)
@@ -353,7 +342,6 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, st
 		    strcmp(name, "Xrendezvous") == 0 ||
 		    strcmp(name, "Xipi_intr_bitmap_handler") == 0) {
 			/* No arguments. */
-			narg = 0;
 			frame_type = INTERRUPT;
 		}
 	}
@@ -387,13 +375,23 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, st
 	}
 
 	/*
-	 * Point to base of trapframe which is just above the
-	 * current frame.  Note that struct i386_frame already accounts for one
-	 * argument.
+	 * Point to base of trapframe which is just above the current
+	 * frame.  Pointer to it was put into %ebp by the kernel entry
+	 * code.
 	 */
-	tf = (struct trapframe *)((char *)*fp + sizeof(struct i386_frame) +
-	    4 * (narg - 1));
+	tf = (struct trapframe *)(*fp)->f_frame;
 
+	/*
+	 * This can be the case for e.g. fork_trampoline, last frame
+	 * of a kernel thread stack.
+	 */
+	if (tf == NULL) {
+		*ip = 0;
+		*fp = 0;
+		db_printf("--- kthread start\n");
+		return;
+	}
+
 	esp = get_esp(tf);
 	eip = tf->tf_eip;
 	ebp = tf->tf_ebp;
@@ -413,15 +411,20 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, st
 	}
 	db_printf(", eip = %#r, esp = %#r, ebp = %#r ---\n", eip, esp, ebp);
 
+	/*
+	 * Detect the last (trap) frame on the kernel stack, where we
+	 * entered kernel from usermode.  Terminate tracing in this
+	 * case.
+	 */
 	switch (frame_type) {
 	case TRAP:
 	case INTERRUPT:
-		if ((tf->tf_eflags & PSL_VM) != 0 ||
-		    (tf->tf_cs & SEL_RPL_MASK) != 0)
-			ebp = 0;
-		break;
+		if (!TRAPF_USERMODE(tf))
+			break;
+		/* FALLTHROUGH */
 	case SYSCALL:
 		ebp = 0;
+		eip = 0;
 		break;
 	}
 
@@ -575,9 +578,12 @@ out:
 		 * after printing the pc if it is the kernel.
 		 */
 		if (frame == NULL || frame <= actframe) {
-			sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
-			db_symbol_values(sym, &name, NULL);
-			db_print_stack_entry(name, 0, 0, 0, pc, frame);
+			if (pc != 0) {
+				sym = db_search_symbol(pc, DB_STGY_ANY,
+				    &offset);
+				db_symbol_values(sym, &name, NULL);
+				db_print_stack_entry(name, 0, 0, 0, pc, frame);
+			}
 			break;
 		}
 	}

Modified: head/sys/i386/include/asmacros.h
==============================================================================
--- head/sys/i386/include/asmacros.h	Tue Nov 12 15:51:47 2019	(r354646)
+++ head/sys/i386/include/asmacros.h	Tue Nov 12 15:56:27 2019	(r354647)
@@ -157,6 +157,7 @@
 	movw	%es,(%esp)
 	pushl	$0
 	movw	%fs,(%esp)
+	movl	%esp,%ebp
 	.endm
 
 	.macro	PUSH_FRAME



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