1 /* Fallback frame-state unwinder for Darwin.
2 Copyright (C) 2004, 2005 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)
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
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
32 #include "coretypes.h"
36 #include "unwind-dw2.h"
39 #include <sys/types.h>
42 typedef unsigned long reg_unit
;
44 /* Place in GPRS the parameters to the first 'sc' instruction that would
45 have been executed if we were returning from this CONTEXT, or
46 return false if an unexpected instruction is encountered. */
49 interpret_libc (reg_unit gprs
[32], struct _Unwind_Context
*context
)
51 uint32_t *pc
= (uint32_t *)_Unwind_GetIP (context
);
53 reg_unit lr
= (reg_unit
) pc
;
55 uint32_t *invalid_address
= NULL
;
59 for (i
= 0; i
< 13; i
++)
61 gprs
[1] = _Unwind_GetCFA (context
);
63 gprs
[i
] = _Unwind_GetGR (context
, i
);
64 cr
= _Unwind_GetGR (context
, CR2_REGNO
);
66 /* For each supported Libc, we have to track the code flow
67 all the way back into the kernel.
69 This code is believed to support all released Libc/Libsystem builds since
70 Jaguar 6C115, including all the security updates. To be precise,
72 Libc Libsystem Build(s)
79 262.4.1~1 63~84 6L123-6R172
81 320~1 71~101 7B85-7D28
82 320~1 71~266 7F54-7F56
85 320.1.3~1 71.1.1~29 7H60-7H105
86 320.1.3~1 71.1.1~30 7H110-7H113
87 320.1.3~1 71.1.1~31 7H114
89 That's a big table! It would be insane to try to keep track of
90 every little detail, so we just read the code itself and do what
98 if ((ins
& 0xFC000003) == 0x48000000) /* b instruction */
100 pc
+= ((((int32_t) ins
& 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4;
103 if ((ins
& 0xFC600000) == 0x2C000000) /* cmpwi */
105 int32_t val1
= (int16_t) ins
;
106 int32_t val2
= gprs
[ins
>> 16 & 0x1F];
107 /* Only beq and bne instructions are supported, so we only
108 need to set the EQ bit. */
109 uint32_t mask
= 0xF << ((ins
>> 21 & 0x1C) ^ 0x1C);
116 if ((ins
& 0xFEC38003) == 0x40820000) /* forwards beq/bne */
118 if ((cr
>> ((ins
>> 16 & 0x1F) ^ 0x1F) & 1) == (ins
>> 24 & 1))
119 pc
+= (ins
& 0x7FFC) / 4 - 1;
122 if ((ins
& 0xFC0007FF) == 0x7C000378) /* or, including mr */
124 gprs
[ins
>> 16 & 0x1F] = (gprs
[ins
>> 11 & 0x1F]
125 | gprs
[ins
>> 21 & 0x1F]);
128 if (ins
>> 26 == 0x0E) /* addi, including li */
130 reg_unit src
= (ins
>> 16 & 0x1F) == 0 ? 0 : gprs
[ins
>> 16 & 0x1F];
131 gprs
[ins
>> 21 & 0x1F] = src
+ (int16_t) ins
;
134 if (ins
>> 26 == 0x0F) /* addis, including lis */
136 reg_unit src
= (ins
>> 16 & 0x1F) == 0 ? 0 : gprs
[ins
>> 16 & 0x1F];
137 gprs
[ins
>> 21 & 0x1F] = src
+ ((int16_t) ins
<< 16);
140 if (ins
>> 26 == 0x20) /* lwz */
142 reg_unit src
= (ins
>> 16 & 0x1F) == 0 ? 0 : gprs
[ins
>> 16 & 0x1F];
143 uint32_t *p
= (uint32_t *)(src
+ (int16_t) ins
);
144 if (p
== invalid_address
)
146 gprs
[ins
>> 21 & 0x1F] = *p
;
149 if (ins
>> 26 == 0x21) /* lwzu */
151 uint32_t *p
= (uint32_t *)(gprs
[ins
>> 16 & 0x1F] += (int16_t) ins
);
152 if (p
== invalid_address
)
154 gprs
[ins
>> 21 & 0x1F] = *p
;
157 if (ins
>> 26 == 0x24) /* stw */
158 /* What we hope this is doing is '--in_sigtramp'. We don't want
159 to actually store to memory, so just make a note of the
160 address and refuse to load from it. */
162 reg_unit src
= (ins
>> 16 & 0x1F) == 0 ? 0 : gprs
[ins
>> 16 & 0x1F];
163 uint32_t *p
= (uint32_t *)(src
+ (int16_t) ins
);
164 if (p
== NULL
|| invalid_address
!= NULL
)
169 if (ins
>> 26 == 0x2E) /* lmw */
171 reg_unit src
= (ins
>> 16 & 0x1F) == 0 ? 0 : gprs
[ins
>> 16 & 0x1F];
172 uint32_t *p
= (uint32_t *)(src
+ (int16_t) ins
);
175 for (i
= (ins
>> 21 & 0x1F); i
< 32; i
++)
177 if (p
== invalid_address
)
183 if ((ins
& 0xFC1FFFFF) == 0x7c0803a6) /* mtlr */
185 lr
= gprs
[ins
>> 21 & 0x1F];
188 if ((ins
& 0xFC1FFFFF) == 0x7c0802a6) /* mflr */
190 gprs
[ins
>> 21 & 0x1F] = lr
;
193 if ((ins
& 0xFC1FFFFF) == 0x7c0903a6) /* mtctr */
195 ctr
= gprs
[ins
>> 21 & 0x1F];
198 /* The PowerPC User's Manual says that bit 11 of the mtcrf
199 instruction is reserved and should be set to zero, but it
200 looks like the Darwin assembler doesn't do that... */
201 if ((ins
& 0xFC000FFF) == 0x7c000120) /* mtcrf */
205 for (i
= 0; i
< 8; i
++)
206 mask
|= ((-(ins
>> (12 + i
) & 1)) & 0xF) << 4 * i
;
207 cr
= (cr
& ~mask
) | (gprs
[ins
>> 21 & 0x1F] & mask
);
210 if (ins
== 0x429f0005) /* bcl- 20,4*cr7+so,.+4, loads pc into LR */
215 if (ins
== 0x4e800420) /* bctr */
217 pc
= (uint32_t *) ctr
;
220 if (ins
== 0x44000002) /* sc */
227 /* We used to include <ucontext.h> and <mach/thread_status.h>,
228 but they change so much between different Darwin system versions
229 that it's much easier to just write the structures involved here
232 /* These defines are from the kernel's bsd/dev/ppc/unix_signal.c. */
234 #define UC_TRAD_VEC 6
236 #define UC_TRAD64_VEC 25
238 #define UC_FLAVOR_VEC 35
239 #define UC_FLAVOR64 40
240 #define UC_FLAVOR64_VEC 45
242 #define UC_DUAL_VEC 55
251 struct gcc_ucontext
*link
;
253 struct gcc_mcontext32
*mcontext
;
256 struct gcc_float_vector_state
261 uint32_t save_vr
[32][4];
262 uint32_t save_vscr
[4];
265 struct gcc_mcontext32
{
269 uint32_t padding1
[5];
279 struct gcc_float_vector_state fvs
;
282 /* These are based on /usr/include/ppc/ucontext.h and
283 /usr/include/mach/ppc/thread_status.h, but rewritten to be more
284 convenient, to compile on Jaguar, and to work around Radar 3712064
285 on Panther, which is that the 'es' field of 'struct mcontext64' has
286 the wrong type (doh!). */
288 struct gcc_mcontext64
{
292 uint32_t padding1
[4];
297 uint32_t xer
[2]; /* These are arrays because the original structure has them misaligned. */
301 struct gcc_float_vector_state fvs
;
304 #define UC_FLAVOR_SIZE \
305 (sizeof (struct gcc_mcontext32) - 33*16)
307 #define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32))
309 #define UC_FLAVOR64_SIZE \
310 (sizeof (struct gcc_mcontext64) - 33*16)
312 #define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64))
314 /* Given GPRS as input to a 'sc' instruction, and OLD_CFA, update FS
315 to represent the execution of a signal return; or, if not a signal
316 return, return false. */
319 handle_syscall (_Unwind_FrameState
*fs
, const reg_unit gprs
[32],
322 struct gcc_ucontext
*uctx
;
323 bool is_64
, is_vector
;
324 struct gcc_float_vector_state
* float_vector_state
;
327 static _Unwind_Ptr return_addr
;
329 /* Yay! We're in a Libc that we understand, and it's made a
330 system call. It'll be one of two kinds: either a Jaguar-style
331 SYS_sigreturn, or a Panther-style 'syscall' call with 184, which
332 is also SYS_sigreturn. */
334 if (gprs
[0] == 0x67 /* SYS_SIGRETURN */)
336 uctx
= (struct gcc_ucontext
*) gprs
[3];
337 is_vector
= (uctx
->mcsize
== UC_FLAVOR64_VEC_SIZE
338 || uctx
->mcsize
== UC_FLAVOR_VEC_SIZE
);
339 is_64
= (uctx
->mcsize
== UC_FLAVOR64_VEC_SIZE
340 || uctx
->mcsize
== UC_FLAVOR64_SIZE
);
342 else if (gprs
[0] == 0 && gprs
[3] == 184)
344 int ctxstyle
= gprs
[5];
345 uctx
= (struct gcc_ucontext
*) gprs
[4];
346 is_vector
= (ctxstyle
== UC_FLAVOR_VEC
|| ctxstyle
== UC_FLAVOR64_VEC
347 || ctxstyle
== UC_TRAD_VEC
|| ctxstyle
== UC_TRAD64_VEC
);
348 is_64
= (ctxstyle
== UC_FLAVOR64_VEC
|| ctxstyle
== UC_TRAD64_VEC
349 || ctxstyle
== UC_FLAVOR64
|| ctxstyle
== UC_TRAD64
);
354 #define set_offset(r, addr) \
355 (fs->regs.reg[r].how = REG_SAVED_OFFSET, \
356 fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa)
358 /* Restore even the registers that are not call-saved, since they
359 might be being used in the prologue to save other registers,
360 for instance GPR0 is sometimes used to save LR. */
362 /* Handle the GPRs, and produce the information needed to do the rest. */
365 /* The context is 64-bit, but it doesn't carry any extra information
366 for us because only the low 32 bits of the registers are
368 struct gcc_mcontext64
*m64
= (struct gcc_mcontext64
*)uctx
->mcontext
;
371 float_vector_state
= &m64
->fvs
;
373 new_cfa
= m64
->gpr
[1][1];
375 set_offset (CR2_REGNO
, &m64
->cr
);
376 for (i
= 0; i
< 32; i
++)
377 set_offset (i
, m64
->gpr
[i
] + 1);
378 set_offset (XER_REGNO
, m64
->xer
+ 1);
379 set_offset (LINK_REGISTER_REGNUM
, m64
->lr
+ 1);
380 set_offset (COUNT_REGISTER_REGNUM
, m64
->ctr
+ 1);
382 set_offset (VRSAVE_REGNO
, &m64
->vrsave
);
384 /* Sometimes, srr0 points to the instruction that caused the exception,
385 and sometimes to the next instruction to be executed; we want
387 if (m64
->exception
== 3 || m64
->exception
== 4
388 || m64
->exception
== 6
389 || (m64
->exception
== 7 && !(m64
->srr1
& 0x10000)))
390 return_addr
= m64
->srr0
+ 4;
392 return_addr
= m64
->srr0
;
396 struct gcc_mcontext32
*m
= uctx
->mcontext
;
399 float_vector_state
= &m
->fvs
;
403 set_offset (CR2_REGNO
, &m
->cr
);
404 for (i
= 0; i
< 32; i
++)
405 set_offset (i
, m
->gpr
+ i
);
406 set_offset (XER_REGNO
, &m
->xer
);
407 set_offset (LINK_REGISTER_REGNUM
, &m
->lr
);
408 set_offset (COUNT_REGISTER_REGNUM
, &m
->ctr
);
411 set_offset (VRSAVE_REGNO
, &m
->vrsave
);
413 /* Sometimes, srr0 points to the instruction that caused the exception,
414 and sometimes to the next instruction to be executed; we want
416 if (m
->exception
== 3 || m
->exception
== 4
418 || (m
->exception
== 7 && !(m
->srr1
& 0x10000)))
419 return_addr
= m
->srr0
+ 4;
421 return_addr
= m
->srr0
;
424 fs
->cfa_how
= CFA_REG_OFFSET
;
425 fs
->cfa_reg
= STACK_POINTER_REGNUM
;
426 fs
->cfa_offset
= new_cfa
- old_cfa
;;
428 /* The choice of column for the return address is somewhat tricky.
429 Fortunately, the actual choice is private to this file, and
430 the space it's reserved from is the GCC register space, not the
431 DWARF2 numbering. So any free element of the right size is an OK
433 fs
->retaddr_column
= ARG_POINTER_REGNUM
;
434 /* FIXME: this should really be done using a DWARF2 location expression,
435 not using a static variable. In fact, this entire file should
436 be implemented in DWARF2 expressions. */
437 set_offset (ARG_POINTER_REGNUM
, &return_addr
);
439 for (i
= 0; i
< 32; i
++)
440 set_offset (32 + i
, float_vector_state
->fpregs
+ i
);
441 set_offset (SPEFSCR_REGNO
, &float_vector_state
->fpscr
);
445 for (i
= 0; i
< 32; i
++)
446 set_offset (FIRST_ALTIVEC_REGNO
+ i
, float_vector_state
->save_vr
+ i
);
447 set_offset (VSCR_REGNO
, float_vector_state
->save_vscr
);
453 /* This is also prototyped in rs6000/darwin.h, inside the
454 MD_FALLBACK_FRAME_STATE_FOR macro. */
455 extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context
*context
,
456 _Unwind_FrameState
*fs
);
458 /* Implement the MD_FALLBACK_FRAME_STATE_FOR macro,
459 returning true iff the frame was a sigreturn() frame that we
463 _Unwind_fallback_frame_state_for (struct _Unwind_Context
*context
,
464 _Unwind_FrameState
*fs
)
468 if (!interpret_libc (gprs
, context
))
470 return handle_syscall (fs
, gprs
, _Unwind_GetCFA (context
));