Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Jul 2009 23:48:29 +0000 (UTC)
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r195984 - projects/mips/sys/mips/mips
Message-ID:  <200907302348.n6UNmTWi049536@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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@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);



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