OSDN Git Service

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