Index: iris6-unwind.h
===================================================================
*** iris6-unwind.h (revision 0)
--- iris6-unwind.h (revision 0)
***************
*** 0 ****
--- 1,140 ----
+ /* DWARF2 EH unwinding support for MIPS Irix 6.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ . */
+
+ /* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+ /* This code was developed-for and only tested-in limited abi
+ configurations. Characterize that. */
+
+ #if defined (_ABIN32)
+ #define SUPPORTED_ABI 1
+ #else
+ #define SUPPORTED_ABI 0
+ #endif
+
+ #include
+
+ #define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state
+
+ #define UINT_AT(ADDR) (*(unsigned int *)(ADDR))
+
+ /* Look at the code around RA to see if it matches a sighandler caller with a
+ sigcontext_t * argument (SA_SIGINFO cleared). Return that pointer argument
+ if it does match, or 0 otherwise. */
+
+ static sigcontext_t *
+ sigcontext_for (void * ra, void * cfa)
+ {
+ /* IRIX 6.5, mono-threaded application. We're lucky enough to be able
+ to expect a short very sighandler specific sequence around. */
+ if (UINT_AT (ra + 24) == 0x24020440 /* li v0,1088 (SYS_sigreturn) */
+ && UINT_AT (ra + 28) == 0x0000000c) /* syscall */
+ return (sigcontext_t *)(cfa + 0x30);
+
+ /* IRIX 6.5 variants, multi-threaded application, pthreads. Nothing really
+ sighandler specific handy, so match a fairly long constant sequence. */
+ if (UINT_AT (ra - 40) == 0xffb00000 /* sd s0,0(sp) */
+ && UINT_AT (ra - 36) == 0x0004f880 /* sll ra,a0,0x2 */
+ && (UINT_AT (ra - 32) == 0x27399058 /* addiu t9,t9,-28584 */
+ || UINT_AT (ra - 32) == 0x273990d8) /* addiu t9,t9,-28456 */
+ && UINT_AT (ra - 28) == 0x8c300edc /* lw s0,3804(at) */
+ && UINT_AT (ra - 24) == 0x033fc821 /* addu t9,t9,ra */
+ && UINT_AT (ra - 20) == 0x8f390000 /* lw t9,0(t9) */
+ && UINT_AT (ra - 16) == 0xdc210e70 /* ld at,3696(at) */
+ && UINT_AT (ra - 12) == 0xde120058 /* ld s2,88(s0) */
+ && UINT_AT (ra - 8) == 0x0320f809 /* jalr t9 */
+ && UINT_AT (ra - 4) == 0xfe010058) /* sd at,88(s0) */
+ return (sigcontext_t *)(cfa + 0x60);
+
+ return 0;
+ }
+
+ #define SIGCTX_GREG_ADDR(REGNO,SIGCTX) \
+ ((void *) &(SIGCTX)->sc_regs[REGNO])
+
+ #define SIGCTX_FPREG_ADDR(REGNO,SIGCTX) \
+ ((void *) &(SIGCTX)->sc_fpregs[REGNO])
+
+ static _Unwind_Reason_Code
+ mips_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+ {
+ /* Return address and CFA of the frame we're attempting to unwind through,
+ possibly a signal handler. */
+ void *ctx_ra = (void *)context->ra;
+ void *ctx_cfa = (void *)context->cfa;
+
+ /* CFA of the intermediate abstract kernel frame between the interrupted
+ code and the signal handler, if we're indeed unwinding through a signal
+ handler. */
+ void *k_cfa;
+
+ /* Pointer to the sigcontext_t structure pushed by the kernel when we're
+ unwinding through a signal handler setup with SA_SIGINFO cleared. */
+ sigcontext_t *sigctx;
+ int i;
+
+ if (! SUPPORTED_ABI)
+ return _URC_END_OF_STACK;
+
+ sigctx = sigcontext_for (ctx_ra, ctx_cfa);
+
+ if (sigctx == 0)
+ return _URC_END_OF_STACK;
+
+ /* The abstract kernel frame's CFA is extactly the stack pointer
+ value at the interruption point. */
+ k_cfa = *(void **)SIGCTX_GREG_ADDR (CTX_SP, sigctx);
+
+ /* State the rules to compute the CFA we have the value of: use the
+ previous CFA and offset by the difference between the two. See
+ uw_update_context_1 for the supporting details. */
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
+ fs->regs.cfa_offset = k_cfa - ctx_cfa;
+
+ /* Fill the internal frame_state structure with information stating where
+ each register of interest can be found from the CFA. */
+ for (i = 0; i <= 31; i ++)
+ {
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset = SIGCTX_GREG_ADDR (i, sigctx) - k_cfa;
+ }
+
+ for (i = 0; i <= 31; i ++)
+ {
+ fs->regs.reg[32+i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[32+i].loc.offset = SIGCTX_FPREG_ADDR (i, sigctx) - k_cfa;
+ }
+
+ /* State the rules to find the kernel's code "return address", which is the
+ address of the active instruction when the signal was caught. */
+ fs->retaddr_column = DWARF_FRAME_RETURN_COLUMN;
+ fs->regs.reg[fs->retaddr_column].how = REG_SAVED_OFFSET;
+ fs->regs.reg[fs->retaddr_column].loc.offset = (void *)&sigctx->sc_pc - k_cfa;
+ fs->signal_frame = 1;
+
+ return _URC_NO_REASON;
+ }
Index: iris6.h
===================================================================
*** iris6.h (revision 167992)
--- iris6.h (working copy)
*************** along with GCC; see the file COPYING3.
*** 62,67 ****
--- 62,69 ----
as DWARF_OFFSET_SIZE. */
#define DWARF_INITIAL_LENGTH_SIZE DWARF_OFFSET_SIZE
+ #define MD_UNWIND_SUPPORT "config/mips/iris6-unwind.h"
+
/* MIPS assemblers don't have the usual .set foo,bar construct;
.set is used for assembler options instead. */
#undef SET_ASM_OP