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