1 /* DWARF2 EH unwinding support for PA 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. */
21 /* Do code reading to identify a signal frame, and set the frame
22 state data appropriately. See unwind-dw2.c for the structs. */
25 #include <sys/ucontext.h>
27 /* Unfortunately, because of various bugs and changes to the kernel,
28 we have several cases to deal with.
30 In 2.4, the signal trampoline is 4 words, and (CONTEXT)->ra should
31 point directly at the beginning of the trampoline and struct rt_sigframe.
33 In <= 2.6.5-rc2-pa3, the signal trampoline is 9 words, and
34 (CONTEXT)->ra points at the 4th word in the trampoline structure. This
35 is wrong, it should point at the 5th word. This is fixed in 2.6.5-rc2-pa4.
37 To detect these cases, we first take (CONTEXT)->ra, align it to 64-bytes
38 to get the beginning of the signal frame, and then check offsets 0, 4
39 and 5 to see if we found the beginning of the trampoline. This will
40 tell us how to locate the sigcontext structure.
42 Note that with a 2.4 64-bit kernel, the signal context is not properly
43 passed back to userspace so the unwind will not work correctly. */
45 #define MD_FALLBACK_FRAME_STATE_FOR pa32_fallback_frame_state
47 static _Unwind_Reason_Code
48 pa32_fallback_frame_state (struct _Unwind_Context
*context
,
49 _Unwind_FrameState
*fs
)
51 unsigned long sp
= (unsigned long)context
->ra
& ~63;
52 unsigned int *pc
= (unsigned int *)sp
;
56 struct sigcontext
*sc
;
62 /* rt_sigreturn trampoline:
63 3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2)
64 3414015a ldi __NR_rt_sigreturn, %r20
65 e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31
68 if (pc
[0] == 0x34190000 || pc
[0] == 0x34190002)
70 else if (pc
[4] == 0x34190000 || pc
[4] == 0x34190002)
75 else if (pc
[5] == 0x34190000 || pc
[5] == 0x34190002)
81 return _URC_END_OF_STACK
;
82 if (pc
[1] != 0x3414015a
83 || pc
[2] != 0xe4008200
84 || pc
[3] != 0x08000240)
85 return _URC_END_OF_STACK
;
87 frame
= (struct rt_sigframe
*)(sp
+ off
);
88 sc
= &frame
->uc
.uc_mcontext
;
90 new_cfa
= sc
->sc_gr
[30];
91 fs
->cfa_how
= CFA_REG_OFFSET
;
93 fs
->cfa_offset
= new_cfa
- (long) context
->cfa
;
94 for (i
= 1; i
<= 31; i
++)
96 fs
->regs
.reg
[i
].how
= REG_SAVED_OFFSET
;
97 fs
->regs
.reg
[i
].loc
.offset
= (long)&sc
->sc_gr
[i
] - new_cfa
;
99 for (i
= 4; i
<= 31; i
++)
101 /* FP regs have left and right halves */
102 fs
->regs
.reg
[2*i
+24].how
= REG_SAVED_OFFSET
;
103 fs
->regs
.reg
[2*i
+24].loc
.offset
104 = (long)&sc
->sc_fr
[i
] - new_cfa
;
105 fs
->regs
.reg
[2*i
+24+1].how
= REG_SAVED_OFFSET
;
106 fs
->regs
.reg
[2*i
+24+1].loc
.offset
107 = (long)&sc
->sc_fr
[i
] + 4 - new_cfa
;
109 fs
->regs
.reg
[88].how
= REG_SAVED_OFFSET
;
110 fs
->regs
.reg
[88].loc
.offset
= (long) &sc
->sc_sar
- new_cfa
;
111 fs
->regs
.reg
[2].how
= REG_SAVED_OFFSET
;
112 fs
->regs
.reg
[2].loc
.offset
= (long) &sc
->sc_iaoq
[0] - new_cfa
;
113 fs
->retaddr_column
= 2;
114 return _URC_NO_REASON
;