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>