1 /* DWARF2 EH unwinding support for MIPS Linux.
2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 /* Do code reading to identify a signal frame, and set the frame
23 state data appropriately. See unwind-dw2.c for the structs. */
27 /* The third parameter to the signal handler points to something with
28 * this structure defined in asm/ucontext.h, but the name clashes with
29 * struct ucontext from sys/ucontext.h so this private copy is used. */
30 typedef struct _sig_ucontext
{
31 unsigned long uc_flags
;
32 struct _sig_ucontext
*uc_link
;
34 struct sigcontext uc_mcontext
;
38 #define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state
40 static _Unwind_Reason_Code
41 mips_fallback_frame_state (struct _Unwind_Context
*context
,
42 _Unwind_FrameState
*fs
)
44 u_int32_t
*pc
= (u_int32_t
*) context
->ra
;
45 struct sigcontext
*sc
;
49 /* 24021061 li v0, 0x1061 (rt_sigreturn)*/
50 /* 0000000c syscall */
52 /* 24021017 li v0, 0x1017 (sigreturn) */
53 /* 0000000c syscall */
54 if (*(pc
+ 1) != 0x0000000c)
55 return _URC_END_OF_STACK
;
56 if (*(pc
+ 0) == 0x24021017)
59 u_int32_t trampoline
[2];
60 struct sigcontext sigctx
;
64 else if (*(pc
+ 0) == 0x24021061)
67 u_int32_t trampoline
[2];
71 sc
= &rt_
->uc
.uc_mcontext
;
74 return _URC_END_OF_STACK
;
76 new_cfa
= (_Unwind_Ptr
)sc
;
77 fs
->cfa_how
= CFA_REG_OFFSET
;
78 fs
->cfa_reg
= STACK_POINTER_REGNUM
;
79 fs
->cfa_offset
= new_cfa
- (_Unwind_Ptr
) context
->cfa
;
81 for (i
= 0; i
< 32; i
++) {
82 fs
->regs
.reg
[i
].how
= REG_SAVED_OFFSET
;
83 fs
->regs
.reg
[i
].loc
.offset
84 = (_Unwind_Ptr
)&(sc
->sc_regs
[i
]) - new_cfa
;
86 fs
->regs
.reg
[SIGNAL_UNWIND_RETURN_COLUMN
].how
= REG_SAVED_OFFSET
;
87 fs
->regs
.reg
[SIGNAL_UNWIND_RETURN_COLUMN
].loc
.offset
88 = (_Unwind_Ptr
)&(sc
->sc_pc
) - new_cfa
;
89 fs
->retaddr_column
= SIGNAL_UNWIND_RETURN_COLUMN
;
91 return _URC_NO_REASON
;