svn commit: r310445 - in head/sys/mips: include mips
John Baldwin
jhb at FreeBSD.org
Fri Dec 23 03:27:12 UTC 2016
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
More information about the svn-src-head
mailing list