1169689Skan/* DWARF2 EH unwinding support for MIPS Linux. 2169689Skan Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3169689Skan 4169689SkanThis file is part of GCC. 5169689Skan 6169689SkanGCC is free software; you can redistribute it and/or modify 7169689Skanit under the terms of the GNU General Public License as published by 8169689Skanthe Free Software Foundation; either version 2, or (at your option) 9169689Skanany later version. 10169689Skan 11169689SkanIn addition to the permissions in the GNU General Public License, the 12169689SkanFree Software Foundation gives you unlimited permission to link the 13169689Skancompiled version of this file with other programs, and to distribute 14169689Skanthose programs without any restriction coming from the use of this 15169689Skanfile. (The General Public License restrictions do apply in other 16169689Skanrespects; for example, they cover modification of the file, and 17169689Skandistribution when not linked into another program.) 18169689Skan 19169689SkanGCC is distributed in the hope that it will be useful, 20169689Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 21169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22169689SkanGNU General Public License for more details. 23169689Skan 24169689SkanYou should have received a copy of the GNU General Public License 25169689Skanalong with GCC; see the file COPYING. If not, write to 26169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 27169689SkanBoston, MA 02110-1301, USA. */ 28169689Skan 29169689Skan#ifndef inhibit_libc 30169689Skan/* Do code reading to identify a signal frame, and set the frame 31169689Skan state data appropriately. See unwind-dw2.c for the structs. */ 32169689Skan 33169689Skan#include <signal.h> 34169689Skan#include <asm/unistd.h> 35169689Skan 36169689Skan/* The third parameter to the signal handler points to something with 37169689Skan * this structure defined in asm/ucontext.h, but the name clashes with 38169689Skan * struct ucontext from sys/ucontext.h so this private copy is used. */ 39169689Skantypedef struct _sig_ucontext { 40169689Skan unsigned long uc_flags; 41169689Skan struct _sig_ucontext *uc_link; 42169689Skan stack_t uc_stack; 43169689Skan struct sigcontext uc_mcontext; 44169689Skan sigset_t uc_sigmask; 45169689Skan} _sig_ucontext_t; 46169689Skan 47169689Skan#define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state 48169689Skan 49169689Skanstatic _Unwind_Reason_Code 50169689Skanmips_fallback_frame_state (struct _Unwind_Context *context, 51169689Skan _Unwind_FrameState *fs) 52169689Skan{ 53169689Skan u_int32_t *pc = (u_int32_t *) context->ra; 54169689Skan struct sigcontext *sc; 55169689Skan _Unwind_Ptr new_cfa; 56169689Skan int i; 57169689Skan 58169689Skan /* 24021061 li v0, 0x1061 (rt_sigreturn)*/ 59169689Skan /* 0000000c syscall */ 60169689Skan /* or */ 61169689Skan /* 24021017 li v0, 0x1017 (sigreturn) */ 62169689Skan /* 0000000c syscall */ 63169689Skan if (pc[1] != 0x0000000c) 64169689Skan return _URC_END_OF_STACK; 65169689Skan#if _MIPS_SIM == _ABIO32 66169689Skan if (pc[0] == (0x24020000 | __NR_sigreturn)) 67169689Skan { 68169689Skan struct sigframe { 69169689Skan u_int32_t trampoline[2]; 70169689Skan struct sigcontext sigctx; 71169689Skan } *rt_ = context->ra; 72169689Skan sc = &rt_->sigctx; 73169689Skan } 74169689Skan else 75169689Skan#endif 76169689Skan if (pc[0] == (0x24020000 | __NR_rt_sigreturn)) 77169689Skan { 78169689Skan struct rt_sigframe { 79169689Skan u_int32_t trampoline[2]; 80169689Skan struct siginfo info; 81169689Skan _sig_ucontext_t uc; 82169689Skan } *rt_ = context->ra; 83169689Skan sc = &rt_->uc.uc_mcontext; 84169689Skan } 85169689Skan else 86169689Skan return _URC_END_OF_STACK; 87169689Skan 88169689Skan new_cfa = (_Unwind_Ptr)sc; 89169689Skan fs->cfa_how = CFA_REG_OFFSET; 90169689Skan fs->cfa_reg = STACK_POINTER_REGNUM; 91169689Skan fs->cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; 92169689Skan 93169689Skan#if _MIPS_SIM == _ABIO32 && defined __MIPSEB__ 94169689Skan /* On o32 Linux, the register save slots in the sigcontext are 95169689Skan eight bytes. We need the lower half of each register slot, 96169689Skan so slide our view of the structure back four bytes. */ 97169689Skan new_cfa -= 4; 98169689Skan#endif 99169689Skan 100169689Skan for (i = 0; i < 32; i++) { 101169689Skan fs->regs.reg[i].how = REG_SAVED_OFFSET; 102169689Skan fs->regs.reg[i].loc.offset 103169689Skan = (_Unwind_Ptr)&(sc->sc_regs[i]) - new_cfa; 104169689Skan } 105169689Skan fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].how = REG_SAVED_OFFSET; 106169689Skan fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].loc.offset 107169689Skan = (_Unwind_Ptr)&(sc->sc_pc) - new_cfa; 108169689Skan fs->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN; 109169689Skan 110169689Skan return _URC_NO_REASON; 111169689Skan} 112169689Skan#endif 113