1/* DWARF2 EH unwinding support for MIPS Linux. 2 Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 2, or (at your option) 9any later version. 10 11In addition to the permissions in the GNU General Public License, the 12Free Software Foundation gives you unlimited permission to link the 13compiled version of this file with other programs, and to distribute 14those programs without any restriction coming from the use of this 15file. (The General Public License restrictions do apply in other 16respects; for example, they cover modification of the file, and 17distribution when not linked into another program.) 18 19GCC is distributed in the hope that it will be useful, 20but WITHOUT ANY WARRANTY; without even the implied warranty of 21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22GNU General Public License for more details. 23 24You should have received a copy of the GNU General Public License 25along with GCC; see the file COPYING. If not, write to 26the Free Software Foundation, 51 Franklin Street, Fifth Floor, 27Boston, MA 02110-1301, USA. */ 28 29#ifndef inhibit_libc 30/* Do code reading to identify a signal frame, and set the frame 31 state data appropriately. See unwind-dw2.c for the structs. */ 32 33#include <signal.h> 34#include <asm/unistd.h> 35 36/* The third parameter to the signal handler points to something with 37 * this structure defined in asm/ucontext.h, but the name clashes with 38 * struct ucontext from sys/ucontext.h so this private copy is used. */ 39typedef struct _sig_ucontext { 40 unsigned long uc_flags; 41 struct _sig_ucontext *uc_link; 42 stack_t uc_stack; 43 struct sigcontext uc_mcontext; 44 sigset_t uc_sigmask; 45} _sig_ucontext_t; 46 47#define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state 48 49static _Unwind_Reason_Code 50mips_fallback_frame_state (struct _Unwind_Context *context, 51 _Unwind_FrameState *fs) 52{ 53 u_int32_t *pc = (u_int32_t *) context->ra; 54 struct sigcontext *sc; 55 _Unwind_Ptr new_cfa; 56 int i; 57 58 /* 24021061 li v0, 0x1061 (rt_sigreturn)*/ 59 /* 0000000c syscall */ 60 /* or */ 61 /* 24021017 li v0, 0x1017 (sigreturn) */ 62 /* 0000000c syscall */ 63 if (pc[1] != 0x0000000c) 64 return _URC_END_OF_STACK; 65#if _MIPS_SIM == _ABIO32 66 if (pc[0] == (0x24020000 | __NR_sigreturn)) 67 { 68 struct sigframe { 69 u_int32_t trampoline[2]; 70 struct sigcontext sigctx; 71 } *rt_ = context->ra; 72 sc = &rt_->sigctx; 73 } 74 else 75#endif 76 if (pc[0] == (0x24020000 | __NR_rt_sigreturn)) 77 { 78 struct rt_sigframe { 79 u_int32_t trampoline[2]; 80 struct siginfo info; 81 _sig_ucontext_t uc; 82 } *rt_ = context->ra; 83 sc = &rt_->uc.uc_mcontext; 84 } 85 else 86 return _URC_END_OF_STACK; 87 88 new_cfa = (_Unwind_Ptr)sc; 89 fs->cfa_how = CFA_REG_OFFSET; 90 fs->cfa_reg = STACK_POINTER_REGNUM; 91 fs->cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; 92 93#if _MIPS_SIM == _ABIO32 && defined __MIPSEB__ 94 /* On o32 Linux, the register save slots in the sigcontext are 95 eight bytes. We need the lower half of each register slot, 96 so slide our view of the structure back four bytes. */ 97 new_cfa -= 4; 98#endif 99 100 for (i = 0; i < 32; i++) { 101 fs->regs.reg[i].how = REG_SAVED_OFFSET; 102 fs->regs.reg[i].loc.offset 103 = (_Unwind_Ptr)&(sc->sc_regs[i]) - new_cfa; 104 } 105 fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].how = REG_SAVED_OFFSET; 106 fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].loc.offset 107 = (_Unwind_Ptr)&(sc->sc_pc) - new_cfa; 108 fs->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN; 109 110 return _URC_NO_REASON; 111} 112#endif 113