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