Author: jhb
Date: Fri Dec 23 03:27:11 2016
New Revision: 310445
URL: https://svnweb.freebsd.org/changeset/base/310445

Log:
  Teach DDB how to unwind across a kernel stack overflow.
  
  Kernel stack overflows in MIPS call panic() directly from an assembly
  handler after storing the interrupted context's registers in a
  trapframe.  Rather than inferring the location of ra, sp, and pc from
  the instruction stream, recognize the pc of a kernel stack overflow
  and pull the registers from the trapframe.
  
  Sponsored by: DARPA / AFRL

Modified:
  head/sys/mips/include/trap.h
  head/sys/mips/mips/db_trace.c
  head/sys/mips/mips/exception.S

Modified: head/sys/mips/include/trap.h
==============================================================================
--- head/sys/mips/include/trap.h        Fri Dec 23 03:23:14 2016        
(r310444)
+++ head/sys/mips/include/trap.h        Fri Dec 23 03:27:11 2016        
(r310445)
@@ -111,6 +111,7 @@ void trapDump(char *msg);
 void MipsFPTrap(u_int, u_int, u_int);
 void MipsKernGenException(void);
 void MipsKernIntr(void);
+void MipsKStackOverflow(void);
 void MipsTLBInvalidException(void);
 void MipsTLBMissException(void);
 void MipsUserGenException(void);

Modified: head/sys/mips/mips/db_trace.c
==============================================================================
--- head/sys/mips/mips/db_trace.c       Fri Dec 23 03:23:14 2016        
(r310444)
+++ head/sys/mips/mips/db_trace.c       Fri Dec 23 03:27:11 2016        
(r310445)
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/stack.h>
 #include <sys/sysent.h>
 
+#include <machine/asm.h>
 #include <machine/db_machdep.h>
 #include <machine/md_var.h>
 #include <machine/mips_opcode.h>
@@ -157,7 +158,6 @@ loop:
        valid_args[2] = 0;
        valid_args[3] = 0;
        next_ra = 0;
-/* Jump here after a nonstandard (interrupt handler) frame */
        stksize = 0;
        subr = 0;
        if (frames++ > 100) {
@@ -213,6 +213,15 @@ loop:
                ra = 0;
                goto done;
        }
+
+       /*
+        * For a kernel stack overflow, skip to the output and
+        * afterwards pull the previous registers out of the trapframe
+        * instead of decoding the function prologue.
+        */
+       if (pc == (uintptr_t)MipsKStackOverflow)
+               goto done;
+
        /*
         * Find the beginning of the current subroutine by scanning
         * backwards from the current PC for the end of the previous
@@ -389,7 +398,21 @@ done:
            (uintmax_t)(u_register_t) sp,
            stksize);
 
-       if (ra) {
+       if (pc == (uintptr_t)MipsKStackOverflow) {
+#define        TF_REG(base, reg)       ((base) + CALLFRAME_SIZ + ((reg) * 
SZREG))
+#if defined(__mips_n64) || defined(__mips_n32)
+               pc = kdbpeekd((int *)TF_REG(sp, PC));
+               ra = kdbpeekd((int *)TF_REG(sp, RA));
+               sp = kdbpeekd((int *)TF_REG(sp, SP));
+#else
+               pc = kdbpeek((int *)TF_REG(sp, PC));
+               ra = kdbpeek((int *)TF_REG(sp, RA));
+               sp = kdbpeek((int *)TF_REG(sp, SP));
+#endif
+#undef TF_REG
+               (*printfn) ("--- Kernel Stack Overflow ---\n");
+               goto loop;
+       } else if (ra) {
                if (pc == ra && stksize == 0)
                        (*printfn) ("stacktrace: loop!\n");
                else {

Modified: head/sys/mips/mips/exception.S
==============================================================================
--- head/sys/mips/mips/exception.S      Fri Dec 23 03:23:14 2016        
(r310444)
+++ head/sys/mips/mips/exception.S      Fri Dec 23 03:27:11 2016        
(r310445)
@@ -1019,6 +1019,8 @@ tlb_insert_random:
         * of this handler. Otherwise the ddb backtrace code will think that
         * the panic() was called from MipsTLBMissException.
         */
+       .globl  MipsKStackOverflow
+MipsKStackOverflow:
        nop
 
        .set pop
_______________________________________________
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