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