]>
Commit | Line | Data |
---|---|---|
8662eb14 | 1 | /* DWARF2 EH unwinding support for PA Linux. |
748086b7 | 2 | Copyright (C) 2004, 2005, 2009 Free Software Foundation, Inc. |
8662eb14 AM |
3 | |
4 | This file is part of GCC. | |
5 | ||
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 | |
748086b7 | 8 | the Free Software Foundation; either version 3, or (at your option) |
8662eb14 AM |
9 | any later version. |
10 | ||
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. | |
15 | ||
748086b7 JJ |
16 | Under Section 7 of GPL version 3, you are granted additional |
17 | permissions described in the GCC Runtime Library Exception, version | |
18 | 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | You should have received a copy of the GNU General Public License and | |
21 | a copy of the GCC Runtime Library Exception along with this program; | |
22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | <http://www.gnu.org/licenses/>. */ | |
24 | ||
8662eb14 AM |
25 | |
26 | /* Do code reading to identify a signal frame, and set the frame | |
27 | state data appropriately. See unwind-dw2.c for the structs. */ | |
28 | ||
d4c56bd7 SK |
29 | /* Don't use this if inhibit_libc is set. |
30 | The build for this target will fail trying to include missing headers. */ | |
31 | #ifndef inhibit_libc | |
8662eb14 AM |
32 | #include <signal.h> |
33 | #include <sys/ucontext.h> | |
34 | ||
35 | /* Unfortunately, because of various bugs and changes to the kernel, | |
36 | we have several cases to deal with. | |
37 | ||
38 | In 2.4, the signal trampoline is 4 words, and (CONTEXT)->ra should | |
39 | point directly at the beginning of the trampoline and struct rt_sigframe. | |
40 | ||
41 | In <= 2.6.5-rc2-pa3, the signal trampoline is 9 words, and | |
42 | (CONTEXT)->ra points at the 4th word in the trampoline structure. This | |
43 | is wrong, it should point at the 5th word. This is fixed in 2.6.5-rc2-pa4. | |
44 | ||
45 | To detect these cases, we first take (CONTEXT)->ra, align it to 64-bytes | |
46 | to get the beginning of the signal frame, and then check offsets 0, 4 | |
47 | and 5 to see if we found the beginning of the trampoline. This will | |
48 | tell us how to locate the sigcontext structure. | |
49 | ||
50 | Note that with a 2.4 64-bit kernel, the signal context is not properly | |
51 | passed back to userspace so the unwind will not work correctly. */ | |
52 | ||
53 | #define MD_FALLBACK_FRAME_STATE_FOR pa32_fallback_frame_state | |
54 | ||
55 | static _Unwind_Reason_Code | |
56 | pa32_fallback_frame_state (struct _Unwind_Context *context, | |
57 | _Unwind_FrameState *fs) | |
58 | { | |
59 | unsigned long sp = (unsigned long)context->ra & ~63; | |
60 | unsigned int *pc = (unsigned int *)sp; | |
61 | unsigned long off; | |
62 | _Unwind_Ptr new_cfa; | |
63 | int i; | |
64 | struct sigcontext *sc; | |
65 | struct rt_sigframe { | |
66 | struct siginfo info; | |
67 | struct ucontext uc; | |
68 | } *frame; | |
69 | ||
70 | /* rt_sigreturn trampoline: | |
71 | 3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2) | |
72 | 3414015a ldi __NR_rt_sigreturn, %r20 | |
73 | e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31 | |
74 | 08000240 nop */ | |
75 | ||
76 | if (pc[0] == 0x34190000 || pc[0] == 0x34190002) | |
77 | off = 4*4; | |
78 | else if (pc[4] == 0x34190000 || pc[4] == 0x34190002) | |
79 | { | |
80 | pc += 4; | |
81 | off = 10 * 4; | |
82 | } | |
83 | else if (pc[5] == 0x34190000 || pc[5] == 0x34190002) | |
84 | { | |
85 | pc += 5; | |
86 | off = 10 * 4; | |
87 | } | |
88 | else | |
9dcab61e JDA |
89 | { |
90 | /* We may have to unwind through an alternate signal stack. | |
91 | We assume that the alignment of the alternate signal stack | |
92 | is BIGGEST_ALIGNMENT (i.e., that it has been allocated using | |
93 | malloc). As a result, we can't distinguish trampolines | |
94 | used prior to 2.6.5-rc2-pa4. However after 2.6.5-rc2-pa4, | |
95 | the return address of a signal trampoline will be on an odd | |
96 | word boundary and we can then determine the frame offset. */ | |
97 | sp = (unsigned long)context->ra; | |
98 | pc = (unsigned int *)sp; | |
99 | if ((pc[0] == 0x34190000 || pc[0] == 0x34190002) && (sp & 4)) | |
100 | off = 5 * 4; | |
101 | else | |
102 | return _URC_END_OF_STACK; | |
103 | } | |
104 | ||
8662eb14 AM |
105 | if (pc[1] != 0x3414015a |
106 | || pc[2] != 0xe4008200 | |
107 | || pc[3] != 0x08000240) | |
108 | return _URC_END_OF_STACK; | |
109 | ||
110 | frame = (struct rt_sigframe *)(sp + off); | |
111 | sc = &frame->uc.uc_mcontext; | |
112 | ||
113 | new_cfa = sc->sc_gr[30]; | |
6673f90b NF |
114 | fs->regs.cfa_how = CFA_REG_OFFSET; |
115 | fs->regs.cfa_reg = 30; | |
116 | fs->regs.cfa_offset = new_cfa - (long) context->cfa; | |
8662eb14 AM |
117 | for (i = 1; i <= 31; i++) |
118 | { | |
119 | fs->regs.reg[i].how = REG_SAVED_OFFSET; | |
120 | fs->regs.reg[i].loc.offset = (long)&sc->sc_gr[i] - new_cfa; | |
121 | } | |
122 | for (i = 4; i <= 31; i++) | |
123 | { | |
124 | /* FP regs have left and right halves */ | |
125 | fs->regs.reg[2*i+24].how = REG_SAVED_OFFSET; | |
126 | fs->regs.reg[2*i+24].loc.offset | |
127 | = (long)&sc->sc_fr[i] - new_cfa; | |
128 | fs->regs.reg[2*i+24+1].how = REG_SAVED_OFFSET; | |
129 | fs->regs.reg[2*i+24+1].loc.offset | |
130 | = (long)&sc->sc_fr[i] + 4 - new_cfa; | |
131 | } | |
132 | fs->regs.reg[88].how = REG_SAVED_OFFSET; | |
133 | fs->regs.reg[88].loc.offset = (long) &sc->sc_sar - new_cfa; | |
9fb1c9db JDA |
134 | fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].how = REG_SAVED_OFFSET; |
135 | fs->regs.reg[DWARF_ALT_FRAME_RETURN_COLUMN].loc.offset | |
136 | = (long) &sc->sc_iaoq[0] - new_cfa; | |
137 | fs->retaddr_column = DWARF_ALT_FRAME_RETURN_COLUMN; | |
8662eb14 AM |
138 | return _URC_NO_REASON; |
139 | } | |
d4c56bd7 | 140 | #endif /* inhibit_libc */ |