OSDN Git Service

update copyright
[pf3gnuchains/gcc-fork.git] / libgcc / config / rs6000 / linux-unwind.h
1 /* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux.
2    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011
3    Free Software Foundation, Inc.
4
5    This file is part of GCC.
6
7    GCC is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published
9    by the Free Software Foundation; either version 3, or (at your
10    option) any later version.
11
12    GCC is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    Under Section 7 of GPL version 3, you are granted additional
18    permissions described in the GCC Runtime Library Exception, version
19    3.1, as published by the Free Software Foundation.
20
21    You should have received a copy of the GNU General Public License and
22    a copy of the GCC Runtime Library Exception along with this program;
23    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24    <http://www.gnu.org/licenses/>.  */
25
26 #define R_LR            65
27 #define R_CR2           70
28 #define R_VR0           77
29 #define R_VRSAVE        109
30 #define R_VSCR          110
31
32 struct gcc_vregs
33 {
34   __attribute__ ((vector_size (16))) int vr[32];
35 #ifdef __powerpc64__
36   unsigned int pad1[3];
37   unsigned int vscr;
38   unsigned int vsave;
39   unsigned int pad2[3];
40 #else
41   unsigned int vsave;
42   unsigned int pad[2];
43   unsigned int vscr;
44 #endif
45 };
46
47 struct gcc_regs
48 {
49   unsigned long gpr[32];
50   unsigned long nip;
51   unsigned long msr;
52   unsigned long orig_gpr3;
53   unsigned long ctr;
54   unsigned long link;
55   unsigned long xer;
56   unsigned long ccr;
57   unsigned long softe;
58   unsigned long trap;
59   unsigned long dar;
60   unsigned long dsisr;
61   unsigned long result;
62   unsigned long pad1[4];
63   double fpr[32];
64   unsigned int pad2;
65   unsigned int fpscr;
66 #ifdef __powerpc64__
67   struct gcc_vregs *vp;
68 #else
69   unsigned int pad3[2];
70 #endif
71   struct gcc_vregs vregs;
72 };
73
74 struct gcc_ucontext
75 {
76 #ifdef __powerpc64__
77   unsigned long pad[28];
78 #else
79   unsigned long pad[12];
80 #endif
81   struct gcc_regs *regs;
82   struct gcc_regs rsave;
83 };
84
85 #ifdef __powerpc64__
86
87 enum { SIGNAL_FRAMESIZE = 128 };
88
89 /* If PC is at a sigreturn trampoline, return a pointer to the
90    regs.  Otherwise return NULL.  */
91
92 static struct gcc_regs *
93 get_regs (struct _Unwind_Context *context)
94 {
95   const unsigned int *pc = context->ra;
96
97   /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
98   /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
99   if (pc[0] != 0x38210000 + SIGNAL_FRAMESIZE || pc[2] != 0x44000002)
100     return NULL;
101   if (pc[1] == 0x38000077)
102     {
103       struct sigframe {
104         char gap[SIGNAL_FRAMESIZE];
105         unsigned long pad[7];
106         struct gcc_regs *regs;
107       } *frame = (struct sigframe *) context->cfa;
108       return frame->regs;
109     }
110   else if (pc[1] == 0x380000AC)
111     {
112       /* This works for 2.4 kernels, but not for 2.6 kernels with vdso
113          because pc isn't pointing into the stack.  Can be removed when
114          no one is running 2.4.19 or 2.4.20, the first two ppc64
115          kernels released.  */
116       const struct rt_sigframe_24 {
117         int tramp[6];
118         void *pinfo;
119         struct gcc_ucontext *puc;
120       } *frame24 = (const struct rt_sigframe_24 *) context->ra;
121
122       /* Test for magic value in *puc of vdso.  */
123       if ((long) frame24->puc != -21 * 8)
124         return frame24->puc->regs;
125       else
126         {
127           /* This works for 2.4.21 and later kernels.  */
128           struct rt_sigframe {
129             char gap[SIGNAL_FRAMESIZE];
130             struct gcc_ucontext uc;
131             unsigned long pad[2];
132             int tramp[6];
133             void *pinfo;
134             struct gcc_ucontext *puc;
135           } *frame = (struct rt_sigframe *) context->cfa;
136           return frame->uc.regs;
137         }
138     }
139   return NULL;
140 }
141
142 #else  /* !__powerpc64__ */
143
144 enum { SIGNAL_FRAMESIZE = 64 };
145
146 static struct gcc_regs *
147 get_regs (struct _Unwind_Context *context)
148 {
149   const unsigned int *pc = context->ra;
150
151   /* li r0, 0x7777; sc  (sigreturn old)  */
152   /* li r0, 0x0077; sc  (sigreturn new)  */
153   /* li r0, 0x6666; sc  (rt_sigreturn old)  */
154   /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
155   if (pc[1] != 0x44000002)
156     return NULL;
157   if (pc[0] == 0x38007777 || pc[0] == 0x38000077)
158     {
159       struct sigframe {
160         char gap[SIGNAL_FRAMESIZE];
161         unsigned long pad[7];
162         struct gcc_regs *regs;
163       } *frame = (struct sigframe *) context->cfa;
164       return frame->regs;
165     }
166   else if (pc[0] == 0x38006666 || pc[0] == 0x380000AC)
167     {
168       struct rt_sigframe {
169         char gap[SIGNAL_FRAMESIZE + 16];
170         char siginfo[128];
171         struct gcc_ucontext uc;
172       } *frame = (struct rt_sigframe *) context->cfa;
173       return frame->uc.regs;
174     }
175   return NULL;
176 }
177 #endif
178
179 /* Find an entry in the process auxiliary vector.  The canonical way to
180    test for VMX is to look at AT_HWCAP.  */
181
182 static long
183 ppc_linux_aux_vector (long which)
184 {
185   /* __libc_stack_end holds the original stack passed to a process.  */
186   extern long *__libc_stack_end;
187   long argc;
188   char **argv;
189   char **envp;
190   struct auxv
191   {
192     long a_type;
193     long a_val;
194   } *auxp;
195
196   /* The Linux kernel puts argc first on the stack.  */
197   argc = __libc_stack_end[0];
198   /* Followed by argv, NULL terminated.  */
199   argv = (char **) __libc_stack_end + 1;
200   /* Followed by environment string pointers, NULL terminated. */
201   envp = argv + argc + 1;
202   while (*envp++)
203     continue;
204   /* Followed by the aux vector, zero terminated.  */
205   for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp)
206     if (auxp->a_type == which)
207       return auxp->a_val;
208   return 0;
209 }
210
211 /* Do code reading to identify a signal frame, and set the frame
212    state data appropriately.  See unwind-dw2.c for the structs.  */
213
214 #define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state
215
216 static _Unwind_Reason_Code
217 ppc_fallback_frame_state (struct _Unwind_Context *context,
218                           _Unwind_FrameState *fs)
219 {
220   static long hwcap = 0;
221   struct gcc_regs *regs = get_regs (context);
222   long new_cfa;
223   int i;
224
225   if (regs == NULL)
226     return _URC_END_OF_STACK;
227
228   new_cfa = regs->gpr[STACK_POINTER_REGNUM];
229   fs->regs.cfa_how = CFA_REG_OFFSET;
230   fs->regs.cfa_reg = STACK_POINTER_REGNUM;
231   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
232
233   for (i = 0; i < 32; i++)
234     if (i != STACK_POINTER_REGNUM)
235       {
236         fs->regs.reg[i].how = REG_SAVED_OFFSET;
237         fs->regs.reg[i].loc.offset = (long) &regs->gpr[i] - new_cfa;
238       }
239
240   fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET;
241   /* CR? regs are always 32-bit and PPC is big-endian, so in 64-bit
242      libgcc loc.offset needs to point to the low 32 bits of regs->ccr.  */
243   fs->regs.reg[R_CR2].loc.offset = (long) &regs->ccr - new_cfa
244                                    + sizeof (long) - 4;
245
246   fs->regs.reg[R_LR].how = REG_SAVED_OFFSET;
247   fs->regs.reg[R_LR].loc.offset = (long) &regs->link - new_cfa;
248
249   fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET;
250   fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) &regs->nip - new_cfa;
251   fs->retaddr_column = ARG_POINTER_REGNUM;
252   fs->signal_frame = 1;
253
254   if (hwcap == 0)
255     {
256       hwcap = ppc_linux_aux_vector (16);
257       /* These will already be set if we found AT_HWCAP.  A nonzero
258          value stops us looking again if for some reason we couldn't
259          find AT_HWCAP.  */
260 #ifdef __powerpc64__
261       hwcap |= 0xc0000000;
262 #else
263       hwcap |= 0x80000000;
264 #endif
265     }
266
267   /* If we have a FPU...  */
268   if (hwcap & 0x08000000)
269     for (i = 0; i < 32; i++)
270       {
271         fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
272         fs->regs.reg[i + 32].loc.offset = (long) &regs->fpr[i] - new_cfa;
273       }
274
275   /* If we have a VMX unit...  */
276   if (hwcap & 0x10000000)
277     {
278       struct gcc_vregs *vregs;
279 #ifdef __powerpc64__
280       vregs = regs->vp;
281 #else
282       vregs = &regs->vregs;
283 #endif
284       if (regs->msr & (1 << 25))
285         {
286           for (i = 0; i < 32; i++)
287             {
288               fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET;
289               fs->regs.reg[i + R_VR0].loc.offset
290                 = (long) &vregs->vr[i] - new_cfa;
291             }
292
293           fs->regs.reg[R_VSCR].how = REG_SAVED_OFFSET;
294           fs->regs.reg[R_VSCR].loc.offset = (long) &vregs->vscr - new_cfa;
295         }
296
297       fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET;
298       fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa;
299     }
300
301   /* If we have SPE register high-parts... we check at compile-time to
302      avoid expanding the code for all other PowerPC.  */
303 #ifdef __SPE__
304   for (i = 0; i < 32; i++)
305     {
306       fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].how = REG_SAVED_OFFSET;
307       fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].loc.offset
308         = (long) &regs->vregs - new_cfa + 4 * i;
309     }
310 #endif
311
312   return _URC_NO_REASON;
313 }
314
315 #define MD_FROB_UPDATE_CONTEXT frob_update_context
316
317 static void
318 frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED)
319 {
320   const unsigned int *pc = (const unsigned int *) context->ra;
321
322   /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't
323      have S flag in it.  */
324 #ifdef __powerpc64__
325   /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
326   /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
327   if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE
328       && (pc[1] == 0x38000077 || pc[1] == 0x380000AC)
329       && pc[2] == 0x44000002)
330     _Unwind_SetSignalFrame (context, 1);
331 #else
332   /* li r0, 0x7777; sc  (sigreturn old)  */
333   /* li r0, 0x0077; sc  (sigreturn new)  */
334   /* li r0, 0x6666; sc  (rt_sigreturn old)  */
335   /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
336   if ((pc[0] == 0x38007777 || pc[0] == 0x38000077
337        || pc[0] == 0x38006666 || pc[0] == 0x380000AC)
338       && pc[1] == 0x44000002)
339     _Unwind_SetSignalFrame (context, 1);
340 #endif
341
342 #ifdef __powerpc64__
343   if (fs->regs.reg[2].how == REG_UNSAVED)
344     {
345       /* If the current unwind info (FS) does not contain explicit info
346          saving R2, then we have to do a minor amount of code reading to
347          figure out if it was saved.  The big problem here is that the
348          code that does the save/restore is generated by the linker, so
349          we have no good way to determine at compile time what to do.  */
350       if (pc[0] == 0xF8410028
351           || ((pc[0] & 0xFFFF0000) == 0x3D820000
352               && pc[1] == 0xF8410028))
353         {
354           /* We are in a plt call stub or r2 adjusting long branch stub,
355              before r2 has been saved.  Keep REG_UNSAVED.  */
356         }
357       else if (pc[0] == 0x4E800421
358                && pc[1] == 0xE8410028)
359         {
360           /* We are at the bctrl instruction in a call via function
361              pointer.  gcc always emits the load of the new r2 just
362              before the bctrl.  */
363           _Unwind_SetGRPtr (context, 2, context->cfa + 40);
364         }
365       else
366         {
367           unsigned int *insn
368             = (unsigned int *) _Unwind_GetGR (context, R_LR);
369           if (insn && *insn == 0xE8410028)
370             _Unwind_SetGRPtr (context, 2, context->cfa + 40);
371         }
372     }
373 #endif
374 }