OSDN Git Service

2008-11-18 Kai Tietz <kai.tietz@onevision.com>
[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 #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
52
53 typedef unsigned long reg_unit;
54
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.  */
58
59 static bool
60 interpret_libc (reg_unit gprs[32], struct _Unwind_Context *context)
61 {
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;
67
68   int i;
69
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);
76
77   /* For each supported Libc, we have to track the code flow
78      all the way back into the kernel.
79   
80      This code is believed to support all released Libc/Libsystem builds since
81      Jaguar 6C115, including all the security updates.  To be precise,
82
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
91      
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
99      
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.
103   */
104
105   for (;;)
106     {
107       uint32_t ins = *pc++;
108       
109       if ((ins & 0xFC000003) == 0x48000000)  /* b instruction */
110         {
111           pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4;
112           continue;
113         }
114       if ((ins & 0xFC600000) == 0x2C000000)  /* cmpwi */
115         {
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;
126         }
127       if ((ins & 0xFEC38003) == 0x40820000)  /* forwards beq/bne */
128         {
129           if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1))
130             pc += (ins & 0x7FFC) / 4 - 1;
131           continue;
132         }
133       if ((ins & 0xFC0007FF) == 0x7C000378) /* or, including mr */
134         {
135           gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F] 
136                                      | gprs [ins >> 21 & 0x1F]);
137           continue;
138         }
139       if (ins >> 26 == 0x0E)  /* addi, including li */
140         {
141           reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
142           gprs [ins >> 21 & 0x1F] = src + (int16_t) ins;
143           continue;
144         }
145       if (ins >> 26 == 0x0F)  /* addis, including lis */
146         {
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;
150         }
151       if (ins >> 26 == 0x20)  /* lwz */
152         {
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;
159         }
160       if (ins >> 26 == 0x21)  /* lwzu */
161         {
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;
167         }
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.  */
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           if (p == NULL || invalid_address != NULL)
176             return false;
177           invalid_address = p;
178           continue;
179         }
180       if (ins >> 26 == 0x2E) /* lmw */
181         {
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;
185
186           for (i = (ins >> 21 & 0x1F); i < 32; i++)
187             {
188               if (p == invalid_address)
189                 return false;
190               gprs[i] = *p++;
191             }
192           continue;
193         }
194       if ((ins & 0xFC1FFFFF) == 0x7c0803a6)  /* mtlr */
195         {
196           lr = gprs [ins >> 21 & 0x1F];
197           continue;
198         }
199       if ((ins & 0xFC1FFFFF) == 0x7c0802a6)  /* mflr */
200         {
201           gprs [ins >> 21 & 0x1F] = lr;
202           continue;
203         }
204       if ((ins & 0xFC1FFFFF) == 0x7c0903a6)  /* mtctr */
205         {
206           ctr = gprs [ins >> 21 & 0x1F];
207           continue;
208         }
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 */
213         {
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;
220         }
221       if (ins == 0x429f0005)  /* bcl- 20,4*cr7+so,.+4, loads pc into LR */
222         {
223           lr = (reg_unit) pc;
224           continue;
225         }
226       if (ins == 0x4e800420) /* bctr */
227         {
228           pc = (uint32_t *) ctr;
229           continue;
230         }
231       if (ins == 0x44000002) /* sc */
232         return true;
233
234       return false;
235     }
236 }
237
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.  */
242
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
254
255 struct gcc_ucontext 
256 {
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;
265 };
266
267 struct gcc_float_vector_state 
268 {
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];
274 };
275
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;
291 };
292
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!).  */
298
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;
313 };
314
315 #define UC_FLAVOR_SIZE \
316   (sizeof (struct gcc_mcontext32) - 33*16)
317
318 #define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32))
319
320 #define UC_FLAVOR64_SIZE \
321   (sizeof (struct gcc_mcontext64) - 33*16)
322
323 #define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64))
324
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.  */
328
329 static bool
330 handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32],
331                 _Unwind_Ptr old_cfa)
332 {
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;
339   
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.  */
344   
345   if (gprs[0] == 0x67 /* SYS_SIGRETURN */)
346     {
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);
352     }
353   else if (gprs[0] == 0 /* SYS_syscall */ && gprs[3] == 184)
354     {
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);
361     }
362   else if (gprs[0] == 184 /* SYS_sigreturn */)
363     {
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);
370     }
371   else
372     return false;
373
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)
377
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.  */
381
382   /* Handle the GPRs, and produce the information needed to do the rest.  */
383   if (is_64)
384     {
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;
390
391       float_vector_state = &m64->fvs;
392
393       new_cfa = m64->gpr[1][1];
394       
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);
403       
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;
413     }
414   else
415     {
416       struct gcc_mcontext32 *m = uctx->mcontext;
417       int i;
418
419       float_vector_state = &m->fvs;
420       
421       new_cfa = m->gpr[1];
422
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);
429
430       if (is_vector)
431         set_offset (R_VRSAVE, &m->vrsave);
432
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;
442     }
443
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;;
447   
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);
458
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);
462   
463   if (is_vector)
464     {
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);
468     }
469
470   return true;
471 }
472
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);
477
478 /* Implement the MD_FALLBACK_FRAME_STATE_FOR macro,
479    returning true iff the frame was a sigreturn() frame that we
480    can understand.  */
481
482 bool
483 _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
484                                   _Unwind_FrameState *fs)
485 {
486   reg_unit gprs[32];
487
488   if (!interpret_libc (gprs, context))
489     return false;
490   return handle_syscall (fs, gprs, _Unwind_GetCFA (context));
491 }
492 #endif