* alias.c, c-common.h, c-incpath.c, c-incpath.h, expr.c,
[official-gcc.git] / gcc / config / pa / linux-unwind.h
blob41ec61caa9e63aa50e5a0c51dbbcb02b8fee2f44
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)
9 any later version.
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. */
24 #include <signal.h>
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;
53 unsigned long off;
54 _Unwind_Ptr new_cfa;
55 int i;
56 struct sigcontext *sc;
57 struct rt_sigframe {
58 struct siginfo info;
59 struct ucontext uc;
60 } *frame;
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
66 08000240 nop */
68 if (pc[0] == 0x34190000 || pc[0] == 0x34190002)
69 off = 4*4;
70 else if (pc[4] == 0x34190000 || pc[4] == 0x34190002)
72 pc += 4;
73 off = 10 * 4;
75 else if (pc[5] == 0x34190000 || pc[5] == 0x34190002)
77 pc += 5;
78 off = 10 * 4;
80 else
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;
92 fs->cfa_reg = 30;
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;