1146895Skan/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux.
2169689Skan   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
3146895Skan
4146895Skan   This file is part of GCC.
5146895Skan
6146895Skan   GCC is free software; you can redistribute it and/or modify it
7146895Skan   under the terms of the GNU General Public License as published
8146895Skan   by the Free Software Foundation; either version 2, or (at your
9146895Skan   option) any later version.
10146895Skan
11146895Skan   In addition to the permissions in the GNU General Public License,
12146895Skan   the Free Software Foundation gives you unlimited permission to link
13146895Skan   the compiled version of this file with other programs, and to
14146895Skan   distribute those programs without any restriction coming from the
15146895Skan   use of this file.  (The General Public License restrictions do
16146895Skan   apply in other respects; for example, they cover modification of
17146895Skan   the file, and distribution when not linked into another program.)
18146895Skan
19146895Skan   GCC is distributed in the hope that it will be useful, but WITHOUT
20146895Skan   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21146895Skan   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
22146895Skan   License for more details.
23146895Skan
24146895Skan   You should have received a copy of the GNU General Public License
25146895Skan   along with GCC; see the file COPYING.  If not, write to the
26169689Skan   Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
27169689Skan   MA 02110-1301, USA.  */
28146895Skan
29146895Skan/* This file defines our own versions of various kernel and user
30146895Skan   structs, so that system headers are not needed, which otherwise
31146895Skan   can make bootstrapping a new toolchain difficult.  Do not use
32146895Skan   these structs elsewhere;  Many fields are missing, particularly
33146895Skan   from the end of the structures.  */
34146895Skan
35146895Skanstruct gcc_vregs
36146895Skan{
37146895Skan  __attribute__ ((vector_size (16))) int vr[32];
38146895Skan#ifdef __powerpc64__
39146895Skan  unsigned int pad1[3];
40146895Skan  unsigned int vscr;
41146895Skan  unsigned int vsave;
42146895Skan  unsigned int pad2[3];
43146895Skan#else
44146895Skan  unsigned int vsave;
45146895Skan  unsigned int pad[2];
46146895Skan  unsigned int vscr;
47146895Skan#endif
48146895Skan};
49146895Skan
50146895Skanstruct gcc_regs
51146895Skan{
52146895Skan  unsigned long gpr[32];
53146895Skan  unsigned long nip;
54146895Skan  unsigned long msr;
55146895Skan  unsigned long orig_gpr3;
56146895Skan  unsigned long ctr;
57146895Skan  unsigned long link;
58146895Skan  unsigned long xer;
59146895Skan  unsigned long ccr;
60146895Skan  unsigned long softe;
61146895Skan  unsigned long trap;
62146895Skan  unsigned long dar;
63146895Skan  unsigned long dsisr;
64146895Skan  unsigned long result;
65146895Skan  unsigned long pad1[4];
66146895Skan  double fpr[32];
67146895Skan  unsigned int pad2;
68146895Skan  unsigned int fpscr;
69146895Skan#ifdef __powerpc64__
70146895Skan  struct gcc_vregs *vp;
71146895Skan#else
72146895Skan  unsigned int pad3[2];
73146895Skan#endif
74146895Skan  struct gcc_vregs vregs;
75146895Skan};
76146895Skan
77146895Skanstruct gcc_ucontext
78146895Skan{
79146895Skan#ifdef __powerpc64__
80146895Skan  unsigned long pad[28];
81146895Skan#else
82146895Skan  unsigned long pad[12];
83146895Skan#endif
84146895Skan  struct gcc_regs *regs;
85146895Skan  struct gcc_regs rsave;
86146895Skan};
87146895Skan
88146895Skan#ifdef __powerpc64__
89146895Skan
90146895Skanenum { SIGNAL_FRAMESIZE = 128 };
91146895Skan
92146895Skan/* If PC is at a sigreturn trampoline, return a pointer to the
93146895Skan   regs.  Otherwise return NULL.  */
94146895Skan
95169689Skanstatic struct gcc_regs *
96169689Skanget_regs (struct _Unwind_Context *context)
97169689Skan{
98169689Skan  const unsigned char *pc = context->ra;
99146895Skan
100169689Skan  /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
101169689Skan  /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
102169689Skan  if (*(unsigned int *) (pc + 0) != 0x38210000 + SIGNAL_FRAMESIZE
103169689Skan      || *(unsigned int *) (pc + 8) != 0x44000002)
104169689Skan    return NULL;
105169689Skan  if (*(unsigned int *) (pc + 4) == 0x38000077)
106169689Skan    {
107169689Skan      struct sigframe {
108169689Skan	char gap[SIGNAL_FRAMESIZE];
109169689Skan	unsigned long pad[7];
110169689Skan	struct gcc_regs *regs;
111169689Skan      } *frame = (struct sigframe *) context->cfa;
112169689Skan      return frame->regs;
113169689Skan    }
114169689Skan  else if (*(unsigned int *) (pc + 4) == 0x380000AC)
115169689Skan    {
116169689Skan      /* This works for 2.4 kernels, but not for 2.6 kernels with vdso
117169689Skan	 because pc isn't pointing into the stack.  Can be removed when
118169689Skan	 no one is running 2.4.19 or 2.4.20, the first two ppc64
119169689Skan	 kernels released.  */
120169689Skan      struct rt_sigframe_24 {
121169689Skan	int tramp[6];
122169689Skan	void *pinfo;
123169689Skan	struct gcc_ucontext *puc;
124169689Skan      } *frame24 = (struct rt_sigframe_24 *) pc;
125146895Skan
126169689Skan      /* Test for magic value in *puc of vdso.  */
127169689Skan      if ((long) frame24->puc != -21 * 8)
128169689Skan	return frame24->puc->regs;
129169689Skan      else
130169689Skan	{
131169689Skan	  /* This works for 2.4.21 and later kernels.  */
132169689Skan	  struct rt_sigframe {
133169689Skan	    char gap[SIGNAL_FRAMESIZE];
134169689Skan	    struct gcc_ucontext uc;
135169689Skan	    unsigned long pad[2];
136169689Skan	    int tramp[6];
137169689Skan	    void *pinfo;
138169689Skan	    struct gcc_ucontext *puc;
139169689Skan	  } *frame = (struct rt_sigframe *) context->cfa;
140169689Skan	  return frame->uc.regs;
141169689Skan	}
142169689Skan    }
143169689Skan  return NULL;
144169689Skan}
145146895Skan
146146895Skan#else  /* !__powerpc64__ */
147146895Skan
148146895Skanenum { SIGNAL_FRAMESIZE = 64 };
149146895Skan
150169689Skanstatic struct gcc_regs *
151169689Skanget_regs (struct _Unwind_Context *context)
152169689Skan{
153169689Skan  const unsigned char *pc = context->ra;
154146895Skan
155169689Skan  /* li r0, 0x7777; sc  (sigreturn old)  */
156169689Skan  /* li r0, 0x0077; sc  (sigreturn new)  */
157169689Skan  /* li r0, 0x6666; sc  (rt_sigreturn old)  */
158169689Skan  /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
159169689Skan  if (*(unsigned int *) (pc + 4) != 0x44000002)
160169689Skan    return NULL;
161169689Skan  if (*(unsigned int *) (pc + 0) == 0x38007777
162169689Skan      || *(unsigned int *) (pc + 0) == 0x38000077)
163169689Skan    {
164169689Skan      struct sigframe {
165169689Skan	char gap[SIGNAL_FRAMESIZE];
166169689Skan	unsigned long pad[7];
167169689Skan	struct gcc_regs *regs;
168169689Skan      } *frame = (struct sigframe *) context->cfa;
169169689Skan      return frame->regs;
170169689Skan    }
171169689Skan  else if (*(unsigned int *) (pc + 0) == 0x38006666
172169689Skan	   || *(unsigned int *) (pc + 0) == 0x380000AC)
173169689Skan    {
174169689Skan      struct rt_sigframe {
175169689Skan	char gap[SIGNAL_FRAMESIZE + 16];
176169689Skan	char siginfo[128];
177169689Skan	struct gcc_ucontext uc;
178169689Skan      } *frame = (struct rt_sigframe *) context->cfa;
179169689Skan      return frame->uc.regs;
180169689Skan    }
181169689Skan  return NULL;
182169689Skan}
183169689Skan#endif
184146895Skan
185169689Skan/* Find an entry in the process auxiliary vector.  The canonical way to
186169689Skan   test for VMX is to look at AT_HWCAP.  */
187146895Skan
188169689Skanstatic long
189169689Skanppc_linux_aux_vector (long which)
190169689Skan{
191169689Skan  /* __libc_stack_end holds the original stack passed to a process.  */
192169689Skan  extern long *__libc_stack_end;
193169689Skan  long argc;
194169689Skan  char **argv;
195169689Skan  char **envp;
196169689Skan  struct auxv
197169689Skan  {
198169689Skan    long a_type;
199169689Skan    long a_val;
200169689Skan  } *auxp;
201146895Skan
202169689Skan  /* The Linux kernel puts argc first on the stack.  */
203169689Skan  argc = __libc_stack_end[0];
204169689Skan  /* Followed by argv, NULL terminated.  */
205169689Skan  argv = (char **) __libc_stack_end + 1;
206169689Skan  /* Followed by environment string pointers, NULL terminated. */
207169689Skan  envp = argv + argc + 1;
208169689Skan  while (*envp++)
209169689Skan    continue;
210169689Skan  /* Followed by the aux vector, zero terminated.  */
211169689Skan  for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp)
212169689Skan    if (auxp->a_type == which)
213169689Skan      return auxp->a_val;
214169689Skan  return 0;
215169689Skan}
216169689Skan
217146895Skan/* Do code reading to identify a signal frame, and set the frame
218146895Skan   state data appropriately.  See unwind-dw2.c for the structs.  */
219146895Skan
220169689Skan#define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state
221169689Skan
222169689Skanstatic _Unwind_Reason_Code
223169689Skanppc_fallback_frame_state (struct _Unwind_Context *context,
224169689Skan			  _Unwind_FrameState *fs)
225169689Skan{
226169689Skan  static long hwcap = 0;
227169689Skan  struct gcc_regs *regs = get_regs (context);
228169689Skan  long new_cfa;
229169689Skan  int i;
230169689Skan
231169689Skan  if (regs == NULL)
232169689Skan    return _URC_END_OF_STACK;
233169689Skan
234169689Skan  new_cfa = regs->gpr[STACK_POINTER_REGNUM];
235169689Skan  fs->cfa_how = CFA_REG_OFFSET;
236169689Skan  fs->cfa_reg = STACK_POINTER_REGNUM;
237169689Skan  fs->cfa_offset = new_cfa - (long) context->cfa;
238169689Skan
239169689Skan  for (i = 0; i < 32; i++)
240169689Skan    if (i != STACK_POINTER_REGNUM)
241169689Skan      {
242169689Skan	fs->regs.reg[i].how = REG_SAVED_OFFSET;
243169689Skan	fs->regs.reg[i].loc.offset = (long) &regs->gpr[i] - new_cfa;
244169689Skan      }
245169689Skan
246169689Skan  fs->regs.reg[CR2_REGNO].how = REG_SAVED_OFFSET;
247169689Skan  fs->regs.reg[CR2_REGNO].loc.offset = (long) &regs->ccr - new_cfa;
248169689Skan
249169689Skan  fs->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET;
250169689Skan  fs->regs.reg[LINK_REGISTER_REGNUM].loc.offset = (long) &regs->link - new_cfa;
251169689Skan
252169689Skan  fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET;
253169689Skan  fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) &regs->nip - new_cfa;
254169689Skan  fs->retaddr_column = ARG_POINTER_REGNUM;
255169689Skan  fs->signal_frame = 1;
256169689Skan
257169689Skan  if (hwcap == 0)
258169689Skan    {
259169689Skan      hwcap = ppc_linux_aux_vector (16);
260169689Skan      /* These will already be set if we found AT_HWCAP.  A nonzero
261169689Skan	 value stops us looking again if for some reason we couldn't
262169689Skan	 find AT_HWCAP.  */
263169689Skan#ifdef __powerpc64__
264169689Skan      hwcap |= 0xc0000000;
265169689Skan#else
266169689Skan      hwcap |= 0x80000000;
267169689Skan#endif
268169689Skan    }
269169689Skan
270169689Skan  /* If we have a FPU...  */
271169689Skan  if (hwcap & 0x08000000)
272169689Skan    for (i = 0; i < 32; i++)
273169689Skan      {
274169689Skan	fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
275169689Skan	fs->regs.reg[i + 32].loc.offset = (long) &regs->fpr[i] - new_cfa;
276169689Skan      }
277169689Skan
278169689Skan  /* If we have a VMX unit...  */
279169689Skan  if (hwcap & 0x10000000)
280169689Skan    {
281169689Skan      struct gcc_vregs *vregs;
282169689Skan#ifdef __powerpc64__
283169689Skan      vregs = regs->vp;
284169689Skan#else
285169689Skan      vregs = &regs->vregs;
286169689Skan#endif
287169689Skan      if (regs->msr & (1 << 25))
288169689Skan	{
289169689Skan	  for (i = 0; i < 32; i++)
290169689Skan	    {
291169689Skan	      fs->regs.reg[i + FIRST_ALTIVEC_REGNO].how = REG_SAVED_OFFSET;
292169689Skan	      fs->regs.reg[i + FIRST_ALTIVEC_REGNO].loc.offset
293169689Skan		= (long) &vregs[i] - new_cfa;
294169689Skan	    }
295169689Skan
296169689Skan	  fs->regs.reg[VSCR_REGNO].how = REG_SAVED_OFFSET;
297169689Skan	  fs->regs.reg[VSCR_REGNO].loc.offset = (long) &vregs->vscr - new_cfa;
298169689Skan	}
299169689Skan
300169689Skan      fs->regs.reg[VRSAVE_REGNO].how = REG_SAVED_OFFSET;
301169689Skan      fs->regs.reg[VRSAVE_REGNO].loc.offset = (long) &vregs->vsave - new_cfa;
302169689Skan    }
303169689Skan
304169689Skan  return _URC_NO_REASON;
305169689Skan}
306169689Skan
307169689Skan#define MD_FROB_UPDATE_CONTEXT frob_update_context
308169689Skan
309169689Skanstatic void
310169689Skanfrob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED)
311169689Skan{
312169689Skan  const unsigned int *pc = (const unsigned int *) context->ra;
313169689Skan
314169689Skan  /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't
315169689Skan     have S flag in it.  */
316169689Skan#ifdef __powerpc64__
317169689Skan  /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
318169689Skan  /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
319169689Skan  if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE
320169689Skan      && (pc[1] == 0x38000077 || pc[1] == 0x380000AC)
321169689Skan      && pc[2] == 0x44000002)
322169689Skan    _Unwind_SetSignalFrame (context, 1);
323169689Skan#else
324169689Skan  /* li r0, 0x7777; sc  (sigreturn old)  */
325169689Skan  /* li r0, 0x0077; sc  (sigreturn new)  */
326169689Skan  /* li r0, 0x6666; sc  (rt_sigreturn old)  */
327169689Skan  /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
328169689Skan  if ((pc[0] == 0x38007777 || pc[0] == 0x38000077
329169689Skan       || pc[0] == 0x38006666 || pc[0] == 0x380000AC)
330169689Skan      && pc[1] == 0x44000002)
331169689Skan    _Unwind_SetSignalFrame (context, 1);
332169689Skan#endif
333169689Skan
334169689Skan#ifdef __powerpc64__
335169689Skan  if (fs->regs.reg[2].how == REG_UNSAVED)
336169689Skan    {
337169689Skan      /* If the current unwind info (FS) does not contain explicit info
338169689Skan	 saving R2, then we have to do a minor amount of code reading to
339169689Skan	 figure out if it was saved.  The big problem here is that the
340169689Skan	 code that does the save/restore is generated by the linker, so
341169689Skan	 we have no good way to determine at compile time what to do.  */
342169689Skan      unsigned int *insn
343169689Skan	= (unsigned int *) _Unwind_GetGR (context, LINK_REGISTER_REGNUM);
344169689Skan      if (*insn == 0xE8410028)
345169689Skan	_Unwind_SetGRPtr (context, 2, context->cfa + 40);
346169689Skan    }
347169689Skan#endif
348169689Skan}
349