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

Reply via email to