svn commit: r195984 - projects/mips/sys/mips/mips
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Thu Jul 30 23:48:30 UTC 2009
Author: gonzo
Date: Thu Jul 30 23:48:29 2009
New Revision: 195984
URL: http://svn.freebsd.org/changeset/base/195984
Log:
- Properly unwind stack for functions with __noreturn__ attribute
Submitted by: Neelkanth Natu <neelnatu at yahoo.com>
Modified:
projects/mips/sys/mips/mips/trap.c
Modified: projects/mips/sys/mips/mips/trap.c
==============================================================================
--- projects/mips/sys/mips/mips/trap.c Thu Jul 30 23:29:59 2009 (r195983)
+++ projects/mips/sys/mips/mips/trap.c Thu Jul 30 23:48:29 2009 (r195984)
@@ -1229,8 +1229,25 @@ MipsEmulateBranch(struct trapframe *fram
#if defined(DDB) || defined(DEBUG)
-#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
+/*
+ * A function using a stack frame has the following instruction as the first
+ * one: addiu sp,sp,-<frame_size>
+ *
+ * We make use of this to detect starting address of a function. This works
+ * better than using 'j ra' instruction to signify end of the previous
+ * function (for e.g. functions like boot() or panic() do not actually
+ * emit a 'j ra' instruction).
+ *
+ * XXX the abi does not require that the addiu instruction be the first one.
+ */
+#define MIPS_START_OF_FUNCTION(ins) (((ins) & 0xffff8000) == 0x27bd8000)
+/*
+ * MIPS ABI 3.0 requires that all functions return using the 'j ra' instruction
+ *
+ * XXX gcc doesn't do this true for functions with __noreturn__ attribute.
+ */
+#define MIPS_END_OF_FUNCTION(ins) ((ins) == 0x03e00008)
/* forward */
char *fn_name(unsigned addr);
@@ -1326,9 +1343,21 @@ loop:
*/
if (!subr) {
va = pc - sizeof(int);
- while ((instr = kdbpeek((int *)va)) != MIPS_JR_RA)
- va -= sizeof(int);
- va += 2 * sizeof(int); /* skip back over branch & delay slot */
+ while (1) {
+ instr = kdbpeek((int *)va);
+
+ if (MIPS_START_OF_FUNCTION(instr))
+ break;
+
+ if (MIPS_END_OF_FUNCTION(instr)) {
+ /* skip over branch-delay slot instruction */
+ va += 2 * sizeof(int);
+ break;
+ }
+
+ va -= sizeof(int);
+ }
+
/* skip over nulls which might separate .o files */
while ((instr = kdbpeek((int *)va)) == 0)
va += sizeof(int);
More information about the svn-src-projects
mailing list