darwin-fallback.c revision 1.1.1.1.4.2 1 1.1.1.1.4.2 yamt /* Fallback frame-state unwinder for Darwin.
2 1.1.1.1.4.2 yamt Copyright (C) 2004-2013 Free Software Foundation, Inc.
3 1.1.1.1.4.2 yamt
4 1.1.1.1.4.2 yamt This file is part of GCC.
5 1.1.1.1.4.2 yamt
6 1.1.1.1.4.2 yamt GCC is free software; you can redistribute it and/or modify it
7 1.1.1.1.4.2 yamt under the terms of the GNU General Public License as published by
8 1.1.1.1.4.2 yamt the Free Software Foundation; either version 3, or (at your option)
9 1.1.1.1.4.2 yamt any later version.
10 1.1.1.1.4.2 yamt
11 1.1.1.1.4.2 yamt GCC is distributed in the hope that it will be useful, but WITHOUT
12 1.1.1.1.4.2 yamt ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 1.1.1.1.4.2 yamt or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 1.1.1.1.4.2 yamt License for more details.
15 1.1.1.1.4.2 yamt
16 1.1.1.1.4.2 yamt Under Section 7 of GPL version 3, you are granted additional
17 1.1.1.1.4.2 yamt permissions described in the GCC Runtime Library Exception, version
18 1.1.1.1.4.2 yamt 3.1, as published by the Free Software Foundation.
19 1.1.1.1.4.2 yamt
20 1.1.1.1.4.2 yamt You should have received a copy of the GNU General Public License and
21 1.1.1.1.4.2 yamt a copy of the GCC Runtime Library Exception along with this program;
22 1.1.1.1.4.2 yamt see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 1.1.1.1.4.2 yamt <http://www.gnu.org/licenses/>. */
24 1.1.1.1.4.2 yamt
25 1.1.1.1.4.2 yamt #ifdef __ppc__
26 1.1.1.1.4.2 yamt
27 1.1.1.1.4.2 yamt #include "tconfig.h"
28 1.1.1.1.4.2 yamt #include "tsystem.h"
29 1.1.1.1.4.2 yamt #include "coretypes.h"
30 1.1.1.1.4.2 yamt #include "tm.h"
31 1.1.1.1.4.2 yamt #include "libgcc_tm.h"
32 1.1.1.1.4.2 yamt #include "dwarf2.h"
33 1.1.1.1.4.2 yamt #include "unwind.h"
34 1.1.1.1.4.2 yamt #include "unwind-dw2.h"
35 1.1.1.1.4.2 yamt #include <stdint.h>
36 1.1.1.1.4.2 yamt #include <stdbool.h>
37 1.1.1.1.4.2 yamt #include <sys/types.h>
38 1.1.1.1.4.2 yamt #include <signal.h>
39 1.1.1.1.4.2 yamt
40 1.1.1.1.4.2 yamt #define R_LR 65
41 1.1.1.1.4.2 yamt #define R_CTR 66
42 1.1.1.1.4.2 yamt #define R_CR2 70
43 1.1.1.1.4.2 yamt #define R_XER 76
44 1.1.1.1.4.2 yamt #define R_VR0 77
45 1.1.1.1.4.2 yamt #define R_VRSAVE 109
46 1.1.1.1.4.2 yamt #define R_VSCR 110
47 1.1.1.1.4.2 yamt #define R_SPEFSCR 112
48 1.1.1.1.4.2 yamt
49 1.1.1.1.4.2 yamt typedef unsigned long reg_unit;
50 1.1.1.1.4.2 yamt
51 1.1.1.1.4.2 yamt /* Place in GPRS the parameters to the first 'sc' instruction that would
52 1.1.1.1.4.2 yamt have been executed if we were returning from this CONTEXT, or
53 1.1.1.1.4.2 yamt return false if an unexpected instruction is encountered. */
54 1.1.1.1.4.2 yamt
55 1.1.1.1.4.2 yamt static bool
56 1.1.1.1.4.2 yamt interpret_libc (reg_unit gprs[32], struct _Unwind_Context *context)
57 1.1.1.1.4.2 yamt {
58 1.1.1.1.4.2 yamt uint32_t *pc = (uint32_t *)_Unwind_GetIP (context);
59 1.1.1.1.4.2 yamt uint32_t cr;
60 1.1.1.1.4.2 yamt reg_unit lr = (reg_unit) pc;
61 1.1.1.1.4.2 yamt reg_unit ctr = 0;
62 1.1.1.1.4.2 yamt uint32_t *invalid_address = NULL;
63 1.1.1.1.4.2 yamt
64 1.1.1.1.4.2 yamt int i;
65 1.1.1.1.4.2 yamt
66 1.1.1.1.4.2 yamt for (i = 0; i < 13; i++)
67 1.1.1.1.4.2 yamt gprs[i] = 1;
68 1.1.1.1.4.2 yamt gprs[1] = _Unwind_GetCFA (context);
69 1.1.1.1.4.2 yamt for (; i < 32; i++)
70 1.1.1.1.4.2 yamt gprs[i] = _Unwind_GetGR (context, i);
71 1.1.1.1.4.2 yamt cr = _Unwind_GetGR (context, R_CR2);
72 1.1.1.1.4.2 yamt
73 1.1.1.1.4.2 yamt /* For each supported Libc, we have to track the code flow
74 1.1.1.1.4.2 yamt all the way back into the kernel.
75 1.1.1.1.4.2 yamt
76 1.1.1.1.4.2 yamt This code is believed to support all released Libc/Libsystem builds since
77 1.1.1.1.4.2 yamt Jaguar 6C115, including all the security updates. To be precise,
78 1.1.1.1.4.2 yamt
79 1.1.1.1.4.2 yamt Libc Libsystem Build(s)
80 1.1.1.1.4.2 yamt 262~1 60~37 6C115
81 1.1.1.1.4.2 yamt 262~1 60.2~4 6D52
82 1.1.1.1.4.2 yamt 262~1 61~3 6F21-6F22
83 1.1.1.1.4.2 yamt 262~1 63~24 6G30-6G37
84 1.1.1.1.4.2 yamt 262~1 63~32 6I34-6I35
85 1.1.1.1.4.2 yamt 262~1 63~64 6L29-6L60
86 1.1.1.1.4.2 yamt 262.4.1~1 63~84 6L123-6R172
87 1.1.1.1.4.2 yamt
88 1.1.1.1.4.2 yamt 320~1 71~101 7B85-7D28
89 1.1.1.1.4.2 yamt 320~1 71~266 7F54-7F56
90 1.1.1.1.4.2 yamt 320~1 71~288 7F112
91 1.1.1.1.4.2 yamt 320~1 71~289 7F113
92 1.1.1.1.4.2 yamt 320.1.3~1 71.1.1~29 7H60-7H105
93 1.1.1.1.4.2 yamt 320.1.3~1 71.1.1~30 7H110-7H113
94 1.1.1.1.4.2 yamt 320.1.3~1 71.1.1~31 7H114
95 1.1.1.1.4.2 yamt
96 1.1.1.1.4.2 yamt That's a big table! It would be insane to try to keep track of
97 1.1.1.1.4.2 yamt every little detail, so we just read the code itself and do what
98 1.1.1.1.4.2 yamt it would do.
99 1.1.1.1.4.2 yamt */
100 1.1.1.1.4.2 yamt
101 1.1.1.1.4.2 yamt for (;;)
102 1.1.1.1.4.2 yamt {
103 1.1.1.1.4.2 yamt uint32_t ins = *pc++;
104 1.1.1.1.4.2 yamt
105 1.1.1.1.4.2 yamt if ((ins & 0xFC000003) == 0x48000000) /* b instruction */
106 1.1.1.1.4.2 yamt {
107 1.1.1.1.4.2 yamt pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4;
108 1.1.1.1.4.2 yamt continue;
109 1.1.1.1.4.2 yamt }
110 1.1.1.1.4.2 yamt if ((ins & 0xFC600000) == 0x2C000000) /* cmpwi */
111 1.1.1.1.4.2 yamt {
112 1.1.1.1.4.2 yamt int32_t val1 = (int16_t) ins;
113 1.1.1.1.4.2 yamt int32_t val2 = gprs[ins >> 16 & 0x1F];
114 1.1.1.1.4.2 yamt /* Only beq and bne instructions are supported, so we only
115 1.1.1.1.4.2 yamt need to set the EQ bit. */
116 1.1.1.1.4.2 yamt uint32_t mask = 0xF << ((ins >> 21 & 0x1C) ^ 0x1C);
117 1.1.1.1.4.2 yamt if (val1 == val2)
118 1.1.1.1.4.2 yamt cr |= mask;
119 1.1.1.1.4.2 yamt else
120 1.1.1.1.4.2 yamt cr &= ~mask;
121 1.1.1.1.4.2 yamt continue;
122 1.1.1.1.4.2 yamt }
123 1.1.1.1.4.2 yamt if ((ins & 0xFEC38003) == 0x40820000) /* forwards beq/bne */
124 1.1.1.1.4.2 yamt {
125 1.1.1.1.4.2 yamt if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1))
126 1.1.1.1.4.2 yamt pc += (ins & 0x7FFC) / 4 - 1;
127 1.1.1.1.4.2 yamt continue;
128 1.1.1.1.4.2 yamt }
129 1.1.1.1.4.2 yamt if ((ins & 0xFC0007FF) == 0x7C000378) /* or, including mr */
130 1.1.1.1.4.2 yamt {
131 1.1.1.1.4.2 yamt gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F]
132 1.1.1.1.4.2 yamt | gprs [ins >> 21 & 0x1F]);
133 1.1.1.1.4.2 yamt continue;
134 1.1.1.1.4.2 yamt }
135 1.1.1.1.4.2 yamt if (ins >> 26 == 0x0E) /* addi, including li */
136 1.1.1.1.4.2 yamt {
137 1.1.1.1.4.2 yamt reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
138 1.1.1.1.4.2 yamt gprs [ins >> 21 & 0x1F] = src + (int16_t) ins;
139 1.1.1.1.4.2 yamt continue;
140 1.1.1.1.4.2 yamt }
141 1.1.1.1.4.2 yamt if (ins >> 26 == 0x0F) /* addis, including lis */
142 1.1.1.1.4.2 yamt {
143 1.1.1.1.4.2 yamt reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
144 1.1.1.1.4.2 yamt gprs [ins >> 21 & 0x1F] = src + ((int16_t) ins << 16);
145 1.1.1.1.4.2 yamt continue;
146 1.1.1.1.4.2 yamt }
147 1.1.1.1.4.2 yamt if (ins >> 26 == 0x20) /* lwz */
148 1.1.1.1.4.2 yamt {
149 1.1.1.1.4.2 yamt reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
150 1.1.1.1.4.2 yamt uint32_t *p = (uint32_t *)(src + (int16_t) ins);
151 1.1.1.1.4.2 yamt if (p == invalid_address)
152 1.1.1.1.4.2 yamt return false;
153 1.1.1.1.4.2 yamt gprs [ins >> 21 & 0x1F] = *p;
154 1.1.1.1.4.2 yamt continue;
155 1.1.1.1.4.2 yamt }
156 1.1.1.1.4.2 yamt if (ins >> 26 == 0x21) /* lwzu */
157 1.1.1.1.4.2 yamt {
158 1.1.1.1.4.2 yamt uint32_t *p = (uint32_t *)(gprs [ins >> 16 & 0x1F] += (int16_t) ins);
159 1.1.1.1.4.2 yamt if (p == invalid_address)
160 1.1.1.1.4.2 yamt return false;
161 1.1.1.1.4.2 yamt gprs [ins >> 21 & 0x1F] = *p;
162 1.1.1.1.4.2 yamt continue;
163 1.1.1.1.4.2 yamt }
164 1.1.1.1.4.2 yamt if (ins >> 26 == 0x24) /* stw */
165 1.1.1.1.4.2 yamt /* What we hope this is doing is '--in_sigtramp'. We don't want
166 1.1.1.1.4.2 yamt to actually store to memory, so just make a note of the
167 1.1.1.1.4.2 yamt address and refuse to load from it. */
168 1.1.1.1.4.2 yamt {
169 1.1.1.1.4.2 yamt reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
170 1.1.1.1.4.2 yamt uint32_t *p = (uint32_t *)(src + (int16_t) ins);
171 1.1.1.1.4.2 yamt if (p == NULL || invalid_address != NULL)
172 1.1.1.1.4.2 yamt return false;
173 1.1.1.1.4.2 yamt invalid_address = p;
174 1.1.1.1.4.2 yamt continue;
175 1.1.1.1.4.2 yamt }
176 1.1.1.1.4.2 yamt if (ins >> 26 == 0x2E) /* lmw */
177 1.1.1.1.4.2 yamt {
178 1.1.1.1.4.2 yamt reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
179 1.1.1.1.4.2 yamt uint32_t *p = (uint32_t *)(src + (int16_t) ins);
180 1.1.1.1.4.2 yamt int i;
181 1.1.1.1.4.2 yamt
182 1.1.1.1.4.2 yamt for (i = (ins >> 21 & 0x1F); i < 32; i++)
183 1.1.1.1.4.2 yamt {
184 1.1.1.1.4.2 yamt if (p == invalid_address)
185 1.1.1.1.4.2 yamt return false;
186 1.1.1.1.4.2 yamt gprs[i] = *p++;
187 1.1.1.1.4.2 yamt }
188 1.1.1.1.4.2 yamt continue;
189 1.1.1.1.4.2 yamt }
190 1.1.1.1.4.2 yamt if ((ins & 0xFC1FFFFF) == 0x7c0803a6) /* mtlr */
191 1.1.1.1.4.2 yamt {
192 1.1.1.1.4.2 yamt lr = gprs [ins >> 21 & 0x1F];
193 1.1.1.1.4.2 yamt continue;
194 1.1.1.1.4.2 yamt }
195 1.1.1.1.4.2 yamt if ((ins & 0xFC1FFFFF) == 0x7c0802a6) /* mflr */
196 1.1.1.1.4.2 yamt {
197 1.1.1.1.4.2 yamt gprs [ins >> 21 & 0x1F] = lr;
198 1.1.1.1.4.2 yamt continue;
199 1.1.1.1.4.2 yamt }
200 1.1.1.1.4.2 yamt if ((ins & 0xFC1FFFFF) == 0x7c0903a6) /* mtctr */
201 1.1.1.1.4.2 yamt {
202 1.1.1.1.4.2 yamt ctr = gprs [ins >> 21 & 0x1F];
203 1.1.1.1.4.2 yamt continue;
204 1.1.1.1.4.2 yamt }
205 1.1.1.1.4.2 yamt /* The PowerPC User's Manual says that bit 11 of the mtcrf
206 1.1.1.1.4.2 yamt instruction is reserved and should be set to zero, but it
207 1.1.1.1.4.2 yamt looks like the Darwin assembler doesn't do that... */
208 1.1.1.1.4.2 yamt if ((ins & 0xFC000FFF) == 0x7c000120) /* mtcrf */
209 1.1.1.1.4.2 yamt {
210 1.1.1.1.4.2 yamt int i;
211 1.1.1.1.4.2 yamt uint32_t mask = 0;
212 1.1.1.1.4.2 yamt for (i = 0; i < 8; i++)
213 1.1.1.1.4.2 yamt mask |= ((-(ins >> (12 + i) & 1)) & 0xF) << 4 * i;
214 1.1.1.1.4.2 yamt cr = (cr & ~mask) | (gprs [ins >> 21 & 0x1F] & mask);
215 1.1.1.1.4.2 yamt continue;
216 1.1.1.1.4.2 yamt }
217 1.1.1.1.4.2 yamt if (ins == 0x429f0005) /* bcl- 20,4*cr7+so,.+4, loads pc into LR */
218 1.1.1.1.4.2 yamt {
219 1.1.1.1.4.2 yamt lr = (reg_unit) pc;
220 1.1.1.1.4.2 yamt continue;
221 1.1.1.1.4.2 yamt }
222 1.1.1.1.4.2 yamt if (ins == 0x4e800420) /* bctr */
223 1.1.1.1.4.2 yamt {
224 1.1.1.1.4.2 yamt pc = (uint32_t *) ctr;
225 1.1.1.1.4.2 yamt continue;
226 1.1.1.1.4.2 yamt }
227 1.1.1.1.4.2 yamt if (ins == 0x44000002) /* sc */
228 1.1.1.1.4.2 yamt return true;
229 1.1.1.1.4.2 yamt
230 1.1.1.1.4.2 yamt return false;
231 1.1.1.1.4.2 yamt }
232 1.1.1.1.4.2 yamt }
233 1.1.1.1.4.2 yamt
234 1.1.1.1.4.2 yamt /* We used to include <ucontext.h> and <mach/thread_status.h>,
235 1.1.1.1.4.2 yamt but they change so much between different Darwin system versions
236 1.1.1.1.4.2 yamt that it's much easier to just write the structures involved here
237 1.1.1.1.4.2 yamt directly. */
238 1.1.1.1.4.2 yamt
239 1.1.1.1.4.2 yamt /* These defines are from the kernel's bsd/dev/ppc/unix_signal.c. */
240 1.1.1.1.4.2 yamt #define UC_TRAD 1
241 1.1.1.1.4.2 yamt #define UC_TRAD_VEC 6
242 1.1.1.1.4.2 yamt #define UC_TRAD64 20
243 1.1.1.1.4.2 yamt #define UC_TRAD64_VEC 25
244 1.1.1.1.4.2 yamt #define UC_FLAVOR 30
245 1.1.1.1.4.2 yamt #define UC_FLAVOR_VEC 35
246 1.1.1.1.4.2 yamt #define UC_FLAVOR64 40
247 1.1.1.1.4.2 yamt #define UC_FLAVOR64_VEC 45
248 1.1.1.1.4.2 yamt #define UC_DUAL 50
249 1.1.1.1.4.2 yamt #define UC_DUAL_VEC 55
250 1.1.1.1.4.2 yamt
251 1.1.1.1.4.2 yamt struct gcc_ucontext
252 1.1.1.1.4.2 yamt {
253 1.1.1.1.4.2 yamt int onstack;
254 1.1.1.1.4.2 yamt sigset_t sigmask;
255 1.1.1.1.4.2 yamt void * stack_sp;
256 1.1.1.1.4.2 yamt size_t stack_sz;
257 1.1.1.1.4.2 yamt int stack_flags;
258 1.1.1.1.4.2 yamt struct gcc_ucontext *link;
259 1.1.1.1.4.2 yamt size_t mcsize;
260 1.1.1.1.4.2 yamt struct gcc_mcontext32 *mcontext;
261 1.1.1.1.4.2 yamt };
262 1.1.1.1.4.2 yamt
263 1.1.1.1.4.2 yamt struct gcc_float_vector_state
264 1.1.1.1.4.2 yamt {
265 1.1.1.1.4.2 yamt double fpregs[32];
266 1.1.1.1.4.2 yamt uint32_t fpscr_pad;
267 1.1.1.1.4.2 yamt uint32_t fpscr;
268 1.1.1.1.4.2 yamt uint32_t save_vr[32][4];
269 1.1.1.1.4.2 yamt uint32_t save_vscr[4];
270 1.1.1.1.4.2 yamt };
271 1.1.1.1.4.2 yamt
272 1.1.1.1.4.2 yamt struct gcc_mcontext32 {
273 1.1.1.1.4.2 yamt uint32_t dar;
274 1.1.1.1.4.2 yamt uint32_t dsisr;
275 1.1.1.1.4.2 yamt uint32_t exception;
276 1.1.1.1.4.2 yamt uint32_t padding1[5];
277 1.1.1.1.4.2 yamt uint32_t srr0;
278 1.1.1.1.4.2 yamt uint32_t srr1;
279 1.1.1.1.4.2 yamt uint32_t gpr[32];
280 1.1.1.1.4.2 yamt uint32_t cr;
281 1.1.1.1.4.2 yamt uint32_t xer;
282 1.1.1.1.4.2 yamt uint32_t lr;
283 1.1.1.1.4.2 yamt uint32_t ctr;
284 1.1.1.1.4.2 yamt uint32_t mq;
285 1.1.1.1.4.2 yamt uint32_t vrsave;
286 1.1.1.1.4.2 yamt struct gcc_float_vector_state fvs;
287 1.1.1.1.4.2 yamt };
288 1.1.1.1.4.2 yamt
289 1.1.1.1.4.2 yamt /* These are based on /usr/include/ppc/ucontext.h and
290 1.1.1.1.4.2 yamt /usr/include/mach/ppc/thread_status.h, but rewritten to be more
291 1.1.1.1.4.2 yamt convenient, to compile on Jaguar, and to work around Radar 3712064
292 1.1.1.1.4.2 yamt on Panther, which is that the 'es' field of 'struct mcontext64' has
293 1.1.1.1.4.2 yamt the wrong type (doh!). */
294 1.1.1.1.4.2 yamt
295 1.1.1.1.4.2 yamt struct gcc_mcontext64 {
296 1.1.1.1.4.2 yamt uint64_t dar;
297 1.1.1.1.4.2 yamt uint32_t dsisr;
298 1.1.1.1.4.2 yamt uint32_t exception;
299 1.1.1.1.4.2 yamt uint32_t padding1[4];
300 1.1.1.1.4.2 yamt uint64_t srr0;
301 1.1.1.1.4.2 yamt uint64_t srr1;
302 1.1.1.1.4.2 yamt uint32_t gpr[32][2];
303 1.1.1.1.4.2 yamt uint32_t cr;
304 1.1.1.1.4.2 yamt uint32_t xer[2]; /* These are arrays because the original structure has them misaligned. */
305 1.1.1.1.4.2 yamt uint32_t lr[2];
306 1.1.1.1.4.2 yamt uint32_t ctr[2];
307 1.1.1.1.4.2 yamt uint32_t vrsave;
308 1.1.1.1.4.2 yamt struct gcc_float_vector_state fvs;
309 1.1.1.1.4.2 yamt };
310 1.1.1.1.4.2 yamt
311 1.1.1.1.4.2 yamt #define UC_FLAVOR_SIZE \
312 1.1.1.1.4.2 yamt (sizeof (struct gcc_mcontext32) - 33*16)
313 1.1.1.1.4.2 yamt
314 1.1.1.1.4.2 yamt #define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32))
315 1.1.1.1.4.2 yamt
316 1.1.1.1.4.2 yamt #define UC_FLAVOR64_SIZE \
317 1.1.1.1.4.2 yamt (sizeof (struct gcc_mcontext64) - 33*16)
318 1.1.1.1.4.2 yamt
319 1.1.1.1.4.2 yamt #define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64))
320 1.1.1.1.4.2 yamt
321 1.1.1.1.4.2 yamt /* Given GPRS as input to a 'sc' instruction, and OLD_CFA, update FS
322 1.1.1.1.4.2 yamt to represent the execution of a signal return; or, if not a signal
323 1.1.1.1.4.2 yamt return, return false. */
324 1.1.1.1.4.2 yamt
325 1.1.1.1.4.2 yamt static bool
326 1.1.1.1.4.2 yamt handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32],
327 1.1.1.1.4.2 yamt _Unwind_Ptr old_cfa)
328 1.1.1.1.4.2 yamt {
329 1.1.1.1.4.2 yamt struct gcc_ucontext *uctx;
330 1.1.1.1.4.2 yamt bool is_64, is_vector;
331 1.1.1.1.4.2 yamt struct gcc_float_vector_state * float_vector_state;
332 1.1.1.1.4.2 yamt _Unwind_Ptr new_cfa;
333 1.1.1.1.4.2 yamt int i;
334 1.1.1.1.4.2 yamt static _Unwind_Ptr return_addr;
335 1.1.1.1.4.2 yamt
336 1.1.1.1.4.2 yamt /* Yay! We're in a Libc that we understand, and it's made a
337 1.1.1.1.4.2 yamt system call. In Jaguar, this is a direct system call with value 103;
338 1.1.1.1.4.2 yamt in Panther and Tiger it is a SYS_syscall call for system call number 184,
339 1.1.1.1.4.2 yamt and in Leopard it is a direct syscall with number 184. */
340 1.1.1.1.4.2 yamt
341 1.1.1.1.4.2 yamt if (gprs[0] == 0x67 /* SYS_SIGRETURN */)
342 1.1.1.1.4.2 yamt {
343 1.1.1.1.4.2 yamt uctx = (struct gcc_ucontext *) gprs[3];
344 1.1.1.1.4.2 yamt is_vector = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
345 1.1.1.1.4.2 yamt || uctx->mcsize == UC_FLAVOR_VEC_SIZE);
346 1.1.1.1.4.2 yamt is_64 = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
347 1.1.1.1.4.2 yamt || uctx->mcsize == UC_FLAVOR64_SIZE);
348 1.1.1.1.4.2 yamt }
349 1.1.1.1.4.2 yamt else if (gprs[0] == 0 /* SYS_syscall */ && gprs[3] == 184)
350 1.1.1.1.4.2 yamt {
351 1.1.1.1.4.2 yamt int ctxstyle = gprs[5];
352 1.1.1.1.4.2 yamt uctx = (struct gcc_ucontext *) gprs[4];
353 1.1.1.1.4.2 yamt is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
354 1.1.1.1.4.2 yamt || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
355 1.1.1.1.4.2 yamt is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
356 1.1.1.1.4.2 yamt || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
357 1.1.1.1.4.2 yamt }
358 1.1.1.1.4.2 yamt else if (gprs[0] == 184 /* SYS_sigreturn */)
359 1.1.1.1.4.2 yamt {
360 1.1.1.1.4.2 yamt int ctxstyle = gprs[4];
361 1.1.1.1.4.2 yamt uctx = (struct gcc_ucontext *) gprs[3];
362 1.1.1.1.4.2 yamt is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
363 1.1.1.1.4.2 yamt || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
364 1.1.1.1.4.2 yamt is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
365 1.1.1.1.4.2 yamt || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
366 1.1.1.1.4.2 yamt }
367 1.1.1.1.4.2 yamt else
368 1.1.1.1.4.2 yamt return false;
369 1.1.1.1.4.2 yamt
370 1.1.1.1.4.2 yamt #define set_offset(r, addr) \
371 1.1.1.1.4.2 yamt (fs->regs.reg[r].how = REG_SAVED_OFFSET, \
372 1.1.1.1.4.2 yamt fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa)
373 1.1.1.1.4.2 yamt
374 1.1.1.1.4.2 yamt /* Restore even the registers that are not call-saved, since they
375 1.1.1.1.4.2 yamt might be being used in the prologue to save other registers,
376 1.1.1.1.4.2 yamt for instance GPR0 is sometimes used to save LR. */
377 1.1.1.1.4.2 yamt
378 1.1.1.1.4.2 yamt /* Handle the GPRs, and produce the information needed to do the rest. */
379 1.1.1.1.4.2 yamt if (is_64)
380 1.1.1.1.4.2 yamt {
381 1.1.1.1.4.2 yamt /* The context is 64-bit, but it doesn't carry any extra information
382 1.1.1.1.4.2 yamt for us because only the low 32 bits of the registers are
383 1.1.1.1.4.2 yamt call-saved. */
384 1.1.1.1.4.2 yamt struct gcc_mcontext64 *m64 = (struct gcc_mcontext64 *)uctx->mcontext;
385 1.1.1.1.4.2 yamt int i;
386 1.1.1.1.4.2 yamt
387 1.1.1.1.4.2 yamt float_vector_state = &m64->fvs;
388 1.1.1.1.4.2 yamt
389 1.1.1.1.4.2 yamt new_cfa = m64->gpr[1][1];
390 1.1.1.1.4.2 yamt
391 1.1.1.1.4.2 yamt set_offset (R_CR2, &m64->cr);
392 1.1.1.1.4.2 yamt for (i = 0; i < 32; i++)
393 1.1.1.1.4.2 yamt set_offset (i, m64->gpr[i] + 1);
394 1.1.1.1.4.2 yamt set_offset (R_XER, m64->xer + 1);
395 1.1.1.1.4.2 yamt set_offset (R_LR, m64->lr + 1);
396 1.1.1.1.4.2 yamt set_offset (R_CTR, m64->ctr + 1);
397 1.1.1.1.4.2 yamt if (is_vector)
398 1.1.1.1.4.2 yamt set_offset (R_VRSAVE, &m64->vrsave);
399 1.1.1.1.4.2 yamt
400 1.1.1.1.4.2 yamt /* Sometimes, srr0 points to the instruction that caused the exception,
401 1.1.1.1.4.2 yamt and sometimes to the next instruction to be executed; we want
402 1.1.1.1.4.2 yamt the latter. */
403 1.1.1.1.4.2 yamt if (m64->exception == 3 || m64->exception == 4
404 1.1.1.1.4.2 yamt || m64->exception == 6
405 1.1.1.1.4.2 yamt || (m64->exception == 7 && !(m64->srr1 & 0x10000)))
406 1.1.1.1.4.2 yamt return_addr = m64->srr0 + 4;
407 1.1.1.1.4.2 yamt else
408 1.1.1.1.4.2 yamt return_addr = m64->srr0;
409 1.1.1.1.4.2 yamt }
410 1.1.1.1.4.2 yamt else
411 1.1.1.1.4.2 yamt {
412 1.1.1.1.4.2 yamt struct gcc_mcontext32 *m = uctx->mcontext;
413 1.1.1.1.4.2 yamt int i;
414 1.1.1.1.4.2 yamt
415 1.1.1.1.4.2 yamt float_vector_state = &m->fvs;
416 1.1.1.1.4.2 yamt
417 1.1.1.1.4.2 yamt new_cfa = m->gpr[1];
418 1.1.1.1.4.2 yamt
419 1.1.1.1.4.2 yamt set_offset (R_CR2, &m->cr);
420 1.1.1.1.4.2 yamt for (i = 0; i < 32; i++)
421 1.1.1.1.4.2 yamt set_offset (i, m->gpr + i);
422 1.1.1.1.4.2 yamt set_offset (R_XER, &m->xer);
423 1.1.1.1.4.2 yamt set_offset (R_LR, &m->lr);
424 1.1.1.1.4.2 yamt set_offset (R_CTR, &m->ctr);
425 1.1.1.1.4.2 yamt
426 1.1.1.1.4.2 yamt if (is_vector)
427 1.1.1.1.4.2 yamt set_offset (R_VRSAVE, &m->vrsave);
428 1.1.1.1.4.2 yamt
429 1.1.1.1.4.2 yamt /* Sometimes, srr0 points to the instruction that caused the exception,
430 1.1.1.1.4.2 yamt and sometimes to the next instruction to be executed; we want
431 1.1.1.1.4.2 yamt the latter. */
432 1.1.1.1.4.2 yamt if (m->exception == 3 || m->exception == 4
433 1.1.1.1.4.2 yamt || m->exception == 6
434 1.1.1.1.4.2 yamt || (m->exception == 7 && !(m->srr1 & 0x10000)))
435 1.1.1.1.4.2 yamt return_addr = m->srr0 + 4;
436 1.1.1.1.4.2 yamt else
437 1.1.1.1.4.2 yamt return_addr = m->srr0;
438 1.1.1.1.4.2 yamt }
439 1.1.1.1.4.2 yamt
440 1.1.1.1.4.2 yamt fs->regs.cfa_how = CFA_REG_OFFSET;
441 1.1.1.1.4.2 yamt fs->regs.cfa_reg = STACK_POINTER_REGNUM;
442 1.1.1.1.4.2 yamt fs->regs.cfa_offset = new_cfa - old_cfa;;
443 1.1.1.1.4.2 yamt
444 1.1.1.1.4.2 yamt /* The choice of column for the return address is somewhat tricky.
445 1.1.1.1.4.2 yamt Fortunately, the actual choice is private to this file, and
446 1.1.1.1.4.2 yamt the space it's reserved from is the GCC register space, not the
447 1.1.1.1.4.2 yamt DWARF2 numbering. So any free element of the right size is an OK
448 1.1.1.1.4.2 yamt choice. Thus: */
449 1.1.1.1.4.2 yamt fs->retaddr_column = ARG_POINTER_REGNUM;
450 1.1.1.1.4.2 yamt /* FIXME: this should really be done using a DWARF2 location expression,
451 1.1.1.1.4.2 yamt not using a static variable. In fact, this entire file should
452 1.1.1.1.4.2 yamt be implemented in DWARF2 expressions. */
453 1.1.1.1.4.2 yamt set_offset (ARG_POINTER_REGNUM, &return_addr);
454 1.1.1.1.4.2 yamt
455 1.1.1.1.4.2 yamt for (i = 0; i < 32; i++)
456 1.1.1.1.4.2 yamt set_offset (32 + i, float_vector_state->fpregs + i);
457 1.1.1.1.4.2 yamt set_offset (R_SPEFSCR, &float_vector_state->fpscr);
458 1.1.1.1.4.2 yamt
459 1.1.1.1.4.2 yamt if (is_vector)
460 1.1.1.1.4.2 yamt {
461 1.1.1.1.4.2 yamt for (i = 0; i < 32; i++)
462 1.1.1.1.4.2 yamt set_offset (R_VR0 + i, float_vector_state->save_vr + i);
463 1.1.1.1.4.2 yamt set_offset (R_VSCR, float_vector_state->save_vscr);
464 1.1.1.1.4.2 yamt }
465 1.1.1.1.4.2 yamt
466 1.1.1.1.4.2 yamt return true;
467 1.1.1.1.4.2 yamt }
468 1.1.1.1.4.2 yamt
469 1.1.1.1.4.2 yamt /* This is also prototyped in rs6000/darwin.h, inside the
470 1.1.1.1.4.2 yamt MD_FALLBACK_FRAME_STATE_FOR macro. */
471 1.1.1.1.4.2 yamt extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
472 1.1.1.1.4.2 yamt _Unwind_FrameState *fs);
473 1.1.1.1.4.2 yamt
474 1.1.1.1.4.2 yamt /* Implement the MD_FALLBACK_FRAME_STATE_FOR macro,
475 1.1.1.1.4.2 yamt returning true iff the frame was a sigreturn() frame that we
476 1.1.1.1.4.2 yamt can understand. */
477 1.1.1.1.4.2 yamt
478 1.1.1.1.4.2 yamt bool
479 1.1.1.1.4.2 yamt _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
480 1.1.1.1.4.2 yamt _Unwind_FrameState *fs)
481 1.1.1.1.4.2 yamt {
482 1.1.1.1.4.2 yamt reg_unit gprs[32];
483 1.1.1.1.4.2 yamt
484 1.1.1.1.4.2 yamt if (!interpret_libc (gprs, context))
485 1.1.1.1.4.2 yamt return false;
486 1.1.1.1.4.2 yamt return handle_syscall (fs, gprs, _Unwind_GetCFA (context));
487 1.1.1.1.4.2 yamt }
488 1.1.1.1.4.2 yamt #endif
489