This patch is against gcc-3.3.1, I have not tried it against the cvs
mainline yet.
Gcc was generating bad eh_frame data for MIPS targets, but the problem
did not become evident until unwinding through leaf functions. Which
can only be done if unwinding through a signal handler, which in turn
is not possible without the attached patch (or the superseded
http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00652.html).
The problem is that initial_return_save() was causing the emission of
the return save to be suppressed due to munging of the register numbers.
This patch attempts to rectify that.
David Daney
------------------------------------------------------------------------
20003-09-17 David Daney <ddaney@avtrex.com>
* gcc/config/mips/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New,
needed for mips/libgcj signal handling.
* gcc/config/mips/mips.h (DWARF_FRAME_REGNUM_FOR_INITIAL_RETURN_SAVE): New.
* gcc/dwarf2out.c (DWARF_FRAME_REGNUM_FOR_INITIAL_RETURN_SAVE): New.
* gcc/dwarf2out.c (initial_return_save): Use
DWARF_FRAME_REGNUM_FOR_INITIAL_RETURN_SAVE instead of DWARF_FRAME_REGNUM
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/gcc/config/mips/linux.h gcc-3.3.1.dave/gcc/config/mips/linux.h
--- gcc-3.3.1/gcc/config/mips/linux.h Thu May 8 10:31:34 2003
+++ gcc-3.3.1.dave/gcc/config/mips/linux.h Wed Sep 17 13:47:35 2003
@@ -252,3 +252,78 @@
/* The current Linux binutils uses MIPS_STABS_ELF and doesn't support
COFF. */
#undef SDB_DEBUGGING_INFO
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+#ifdef IN_LIBGCC2
+#include <signal.h>
+
+/* The third parameter to the signal handler points to something with
+ * this structure defined in asm/ucontext.h, but the name clashes with
+ * struct ucontext from sys/ucontext.h so this private copy is used. */
+typedef struct _sig_ucontext {
+ unsigned long uc_flags;
+ struct _sig_ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask;
+} sig_ucontext_t;
+
+#endif /* IN_LIBGCC2 */
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned char *pc_ = (CONTEXT)->ra; \
+ struct sigcontext *sc_; \
+ long new_cfa_; \
+ int i_; \
+ \
+ /* 24021061 li v0, 0x1061 (rt_sigreturn)*/ \
+ /* 0000000c syscall */ \
+ /* or */ \
+ /* 24021017 li v0, 0x1017 (sigreturn) */ \
+ /* 0000000c syscall */ \
+ if (*(unsigned int *) (pc_+4) != 0x0000000c) \
+ break; \
+ if (*(unsigned int *) (pc_+0) == 0x24021017) \
+ { \
+ struct sigframe { \
+ unsigned int trampoline[2]; \
+ struct sigcontext sigctx; \
+ } *rt_ = (CONTEXT)->ra; \
+ sc_ = &rt_->sigctx; \
+ } \
+ else if (*(unsigned int *) (pc_+0) == 0x24021061) \
+ { \
+ struct rt_sigframe { \
+ unsigned int trampoline[2]; \
+ struct siginfo info; \
+ sig_ucontext_t uc; \
+ } *rt_ = (CONTEXT)->ra; \
+ sc_ = &rt_->uc.uc_mcontext; \
+ } \
+ else \
+ break; \
+ \
+ new_cfa_ = sc_->sc_regs[STACK_POINTER_REGNUM]; \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = STACK_POINTER_REGNUM; \
+ (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
+ \
+ for (i_ = 0; i_ < 32; i_++) \
+ if (i_ != STACK_POINTER_REGNUM) \
+ { \
+ (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_].loc.offset \
+ = (long)&(sc_->sc_regs[i_]) - new_cfa_; \
+ } \
+ /* Overload RAP_REG_NUM to be signal handler return address. */ \
+ /* Is this correct? It seems to work. We don't have to define */ \
+ /* more pseudo registers. RAP should be unused in a signal frame. */\
+ (FS)->regs.reg[DWARF_FRAME_RETURN_COLUMN].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[DWARF_FRAME_RETURN_COLUMN].loc.offset \
+ = (long)&(sc_->sc_pc) - new_cfa_; \
+ (FS)->retaddr_column = DWARF_FRAME_RETURN_COLUMN; \
+ \
+ goto SUCCESS; \
+ } while (0)
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/gcc/config/mips/mips.h gcc-3.3.1.dave/gcc/config/mips/mips.h
--- gcc-3.3.1/gcc/config/mips/mips.h Fri May 30 05:00:42 2003
+++ gcc-3.3.1.dave/gcc/config/mips/mips.h Wed Sep 17 13:44:38 2003
@@ -1289,6 +1289,12 @@
/* Before the prologue, RA lives in r31. */
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31)
+/* Don't use DWARF_FRAME_REGNUM in dwarf2out.c(initial_return_save).
+ Mapping r31 to DWARF_FRAME_RETURN_COLUMN breaks unwinding through
+ leaf functions which can happen when unwinding through a signal
+ handler.*/
+#define DWARF_FRAME_REGNUM_FOR_INITIAL_RETURN_SAVE(REG) (REG)
+
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) ((N) < (TARGET_MIPS16 ? 2 : 4) ? (N) + GP_ARG_FIRST : INVALID_REGNUM)
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 3)
diff -u --recursive --ignore-space-change --new-file --exclude=*~ --exclude=Makefile.in --exclude=configure --exclude=semantic.cache* gcc-3.3.1/gcc/dwarf2out.c gcc-3.3.1.dave/gcc/dwarf2out.c
--- gcc-3.3.1/gcc/dwarf2out.c Sun Jul 20 00:22:55 2003
+++ gcc-3.3.1.dave/gcc/dwarf2out.c Wed Sep 17 13:44:35 2003
@@ -377,6 +377,11 @@
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
#endif
+#ifndef DWARF_FRAME_REGNUM_FOR_INITIAL_RETURN_SAVE
+#define DWARF_FRAME_REGNUM_FOR_INITIAL_RETURN_SAVE(REG) \
+ DWARF_FRAME_REGNUM (REG)
+#endif
+
/* The offset from the incoming value of %sp to the top of the stack frame
for the current function. */
#ifndef INCOMING_FRAME_SP_OFFSET
@@ -885,7 +890,7 @@
{
case REG:
/* RA is in a register. */
- reg = DWARF_FRAME_REGNUM (REGNO (rtl));
+ reg = DWARF_FRAME_REGNUM_FOR_INITIAL_RETURN_SAVE (REGNO (rtl));
break;
case MEM: