This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch] MIPS: Fix unwinding through signal frames for n32 and n64 ABIs.
- From: David Daney <ddaney at avtrex dot com>
- To: gcc-patches at gcc dot gnu dot org, Daniel Jacobowitz <drow at false dot org>
- Date: Sun, 08 Jul 2007 23:55:44 -0700
- Subject: [Patch] MIPS: Fix unwinding through signal frames for n32 and n64 ABIs.
As noted by Daniel Jacobowitz, this patch:
http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01337.html
broke unwinding through signal frames on n32 and n64 ABIs. It also
causes 4.3 to emit aliasing warnings.
My new patch fixes both of these problems.
The root of the problem is that the original MD_FALLBACK_FRAME_STATE_FOR
support for MIPS placed the return address in the register slot use by
$hi. This register has the same width as the other general purpose
registers. This was causing the unwinder to assert because the width of
the return address (Pmode) differs from that of the registers in the n32
ABI (32 bits vs. 64).
The fix is to move the SIGNAL_UNWIND_RETURN_COLUMN into an unused column
and give that column the with of Pmode. I also cleaned up and
simplified the return address calculation code in linux-unwind.h to
eliminate the warnings and not use the wrong sized temporary variable.
So far I have tested only gcc.dg/cleanup-9.c on mips64-linux with both
n32 and n64 ABIs. It now works for both! I am fairly confident that it
will work on o32 as well.
Tomorrow I will run the testsuite for c,c++,java on mipsel-linux-gnu. I
think it will be several weeks before I can run the full testsuite on
mips64-linux (all three ABIs) as starting Thursday I will be out of the
office for 10 days. If someone were to test the patch on the 64-bit
ABIs before then I wouldn't mind.
Comments?
OK to commit?
2007-07-08 David Daney <ddaney@avtrex.com>
* config/mips/linux-unwind.h (mips_fallback_frame_state): Rewrite
return address calculation.
* config/mips/mips.h (SIGNAL_UNWIND_RETURN_COLUMN): Rewrite and move.
* config/mips/mips.c (override_options): Set mips_hard_regno_mode_ok
for SIGNAL_UNWIND_RETURN_COLUMN.
Index: gcc/config/mips/linux-unwind.h
===================================================================
--- gcc/config/mips/linux-unwind.h (revision 126478)
+++ gcc/config/mips/linux-unwind.h (working copy)
@@ -1,5 +1,5 @@
/* DWARF2 EH unwinding support for MIPS Linux.
- Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
@@ -51,7 +51,6 @@ mips_fallback_frame_state (struct _Unwin
_Unwind_FrameState *fs)
{
u_int32_t *pc = (u_int32_t *) context->ra;
- u_int32_t t;
struct sigcontext *sc;
_Unwind_Ptr new_cfa;
int i;
@@ -107,9 +106,8 @@ mips_fallback_frame_state (struct _Unwin
expect it point to the following instruction. We compensate by
reporting a return address at the next instruction. */
fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].how = REG_SAVED_VAL_OFFSET;
- t = (*(u_int32_t *)(void *)&sc->sc_pc) + 4;
fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].loc.offset
- = (_Unwind_Ptr)t - new_cfa;
+ = (_Unwind_Ptr)(sc->sc_pc) + 4 - new_cfa;
fs->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN;
return _URC_NO_REASON;
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c (revision 126478)
+++ gcc/config/mips/mips.c (working copy)
@@ -5329,6 +5329,8 @@ override_options (void)
else if (ALL_COP_REG_P (regno))
temp = (class == MODE_INT && size <= UNITS_PER_WORD);
+ else if (SIGNAL_UNWIND_RETURN_P(regno))
+ temp = (mode == Pmode);
else
temp = 0;
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h (revision 126478)
+++ gcc/config/mips/mips.h (working copy)
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler. MIPS version.
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+ Free Software Foundation, Inc.
Contributed by A. Lichnewsky (lich@inria.inria.fr).
Changed by Michael Meissner (meissner@osf.org).
64-bit r4000 support by Ian Lance Taylor (ian@cygnus.com) and
@@ -1008,10 +1009,6 @@ extern const struct mips_rtx_cost_data *
/* The DWARF 2 CFA column which tracks the return address. */
#define DWARF_FRAME_RETURN_COLUMN (GP_REG_FIRST + 31)
-/* The DWARF 2 CFA column which tracks the return address from a
- signal handler context. */
-#define SIGNAL_UNWIND_RETURN_COLUMN (FP_REG_LAST + 1)
-
/* Before the prologue, RA lives in r31. */
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31)
@@ -1355,6 +1352,10 @@ extern const struct mips_rtx_cost_data *
#define MD_REG_NUM (MD_REG_LAST - MD_REG_FIRST + 1)
#define MD_DBX_FIRST (FP_DBX_FIRST + FP_REG_NUM)
+/* The DWARF 2 CFA column which tracks the return address from a
+ signal handler context. */
+#define SIGNAL_UNWIND_RETURN_COLUMN 66
+
#define ST_REG_FIRST 67
#define ST_REG_LAST 74
#define ST_REG_NUM (ST_REG_LAST - ST_REG_FIRST + 1)
@@ -1432,6 +1433,8 @@ extern const struct mips_rtx_cost_data *
&& GET_CODE (XEXP (X, 0)) == UNSPEC \
&& XINT (XEXP (X, 0), 1) == UNSPEC_GP)
+#define SIGNAL_UNWIND_RETURN_P(REGNO) ((REGNO) == SIGNAL_UNWIND_RETURN_COLUMN)
+
/* Return coprocessor number from register number. */
#define COPNUM_AS_CHAR_FROM_REGNUM(REGNO) \