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