1 /* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux.
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4 This file is part of GCC.
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
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
33 __attribute__ ((vector_size (16))) int vr
[32];
48 unsigned long gpr
[32];
51 unsigned long orig_gpr3
;
61 unsigned long pad1
[4];
70 struct gcc_vregs vregs
;
76 unsigned long pad
[28];
78 unsigned long pad
[12];
80 struct gcc_regs
*regs
;
81 struct gcc_regs rsave
;
86 enum { SIGNAL_FRAMESIZE
= 128 };
88 /* If PC is at a sigreturn trampoline, return a pointer to the
89 regs. Otherwise return NULL. */
91 static struct gcc_regs
*
92 get_regs (struct _Unwind_Context
*context
)
94 const unsigned int *pc
= context
->ra
;
96 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */
97 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */
98 if (pc
[0] != 0x38210000 + SIGNAL_FRAMESIZE
|| pc
[2] != 0x44000002)
100 if (pc
[1] == 0x38000077)
103 char gap
[SIGNAL_FRAMESIZE
];
104 unsigned long pad
[7];
105 struct gcc_regs
*regs
;
106 } *frame
= (struct sigframe
*) context
->cfa
;
109 else if (pc
[1] == 0x380000AC)
111 /* This works for 2.4 kernels, but not for 2.6 kernels with vdso
112 because pc isn't pointing into the stack. Can be removed when
113 no one is running 2.4.19 or 2.4.20, the first two ppc64
115 const struct rt_sigframe_24
{
118 struct gcc_ucontext
*puc
;
119 } *frame24
= (const struct rt_sigframe_24
*) context
->ra
;
121 /* Test for magic value in *puc of vdso. */
122 if ((long) frame24
->puc
!= -21 * 8)
123 return frame24
->puc
->regs
;
126 /* This works for 2.4.21 and later kernels. */
128 char gap
[SIGNAL_FRAMESIZE
];
129 struct gcc_ucontext uc
;
130 unsigned long pad
[2];
133 struct gcc_ucontext
*puc
;
134 } *frame
= (struct rt_sigframe
*) context
->cfa
;
135 return frame
->uc
.regs
;
141 #else /* !__powerpc64__ */
143 enum { SIGNAL_FRAMESIZE
= 64 };
145 static struct gcc_regs
*
146 get_regs (struct _Unwind_Context
*context
)
148 const unsigned int *pc
= context
->ra
;
150 /* li r0, 0x7777; sc (sigreturn old) */
151 /* li r0, 0x0077; sc (sigreturn new) */
152 /* li r0, 0x6666; sc (rt_sigreturn old) */
153 /* li r0, 0x00AC; sc (rt_sigreturn new) */
154 if (pc
[1] != 0x44000002)
156 if (pc
[0] == 0x38007777 || pc
[0] == 0x38000077)
159 char gap
[SIGNAL_FRAMESIZE
];
160 unsigned long pad
[7];
161 struct gcc_regs
*regs
;
162 } *frame
= (struct sigframe
*) context
->cfa
;
165 else if (pc
[0] == 0x38006666 || pc
[0] == 0x380000AC)
168 char gap
[SIGNAL_FRAMESIZE
+ 16];
170 struct gcc_ucontext uc
;
171 } *frame
= (struct rt_sigframe
*) context
->cfa
;
172 return frame
->uc
.regs
;
178 /* Find an entry in the process auxiliary vector. The canonical way to
179 test for VMX is to look at AT_HWCAP. */
182 ppc_linux_aux_vector (long which
)
184 /* __libc_stack_end holds the original stack passed to a process. */
185 extern long *__libc_stack_end
;
195 /* The Linux kernel puts argc first on the stack. */
196 argc
= __libc_stack_end
[0];
197 /* Followed by argv, NULL terminated. */
198 argv
= (char **) __libc_stack_end
+ 1;
199 /* Followed by environment string pointers, NULL terminated. */
200 envp
= argv
+ argc
+ 1;
203 /* Followed by the aux vector, zero terminated. */
204 for (auxp
= (struct auxv
*) envp
; auxp
->a_type
!= 0; ++auxp
)
205 if (auxp
->a_type
== which
)
210 /* Do code reading to identify a signal frame, and set the frame
211 state data appropriately. See unwind-dw2.c for the structs. */
213 #define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state
215 static _Unwind_Reason_Code
216 ppc_fallback_frame_state (struct _Unwind_Context
*context
,
217 _Unwind_FrameState
*fs
)
219 static long hwcap
= 0;
220 struct gcc_regs
*regs
= get_regs (context
);
225 return _URC_END_OF_STACK
;
227 new_cfa
= regs
->gpr
[STACK_POINTER_REGNUM
];
228 fs
->regs
.cfa_how
= CFA_REG_OFFSET
;
229 fs
->regs
.cfa_reg
= STACK_POINTER_REGNUM
;
230 fs
->regs
.cfa_offset
= new_cfa
- (long) context
->cfa
;
232 for (i
= 0; i
< 32; i
++)
233 if (i
!= STACK_POINTER_REGNUM
)
235 fs
->regs
.reg
[i
].how
= REG_SAVED_OFFSET
;
236 fs
->regs
.reg
[i
].loc
.offset
= (long) ®s
->gpr
[i
] - new_cfa
;
239 fs
->regs
.reg
[R_CR2
].how
= REG_SAVED_OFFSET
;
240 /* CR? regs are always 32-bit and PPC is big-endian, so in 64-bit
241 libgcc loc.offset needs to point to the low 32 bits of regs->ccr. */
242 fs
->regs
.reg
[R_CR2
].loc
.offset
= (long) ®s
->ccr
- new_cfa
245 fs
->regs
.reg
[R_LR
].how
= REG_SAVED_OFFSET
;
246 fs
->regs
.reg
[R_LR
].loc
.offset
= (long) ®s
->link
- new_cfa
;
248 fs
->regs
.reg
[ARG_POINTER_REGNUM
].how
= REG_SAVED_OFFSET
;
249 fs
->regs
.reg
[ARG_POINTER_REGNUM
].loc
.offset
= (long) ®s
->nip
- new_cfa
;
250 fs
->retaddr_column
= ARG_POINTER_REGNUM
;
251 fs
->signal_frame
= 1;
255 hwcap
= ppc_linux_aux_vector (16);
256 /* These will already be set if we found AT_HWCAP. A nonzero
257 value stops us looking again if for some reason we couldn't
266 /* If we have a FPU... */
267 if (hwcap
& 0x08000000)
268 for (i
= 0; i
< 32; i
++)
270 fs
->regs
.reg
[i
+ 32].how
= REG_SAVED_OFFSET
;
271 fs
->regs
.reg
[i
+ 32].loc
.offset
= (long) ®s
->fpr
[i
] - new_cfa
;
274 /* If we have a VMX unit... */
275 if (hwcap
& 0x10000000)
277 struct gcc_vregs
*vregs
;
281 vregs
= ®s
->vregs
;
283 if (regs
->msr
& (1 << 25))
285 for (i
= 0; i
< 32; i
++)
287 fs
->regs
.reg
[i
+ R_VR0
].how
= REG_SAVED_OFFSET
;
288 fs
->regs
.reg
[i
+ R_VR0
].loc
.offset
289 = (long) &vregs
->vr
[i
] - new_cfa
;
292 fs
->regs
.reg
[R_VSCR
].how
= REG_SAVED_OFFSET
;
293 fs
->regs
.reg
[R_VSCR
].loc
.offset
= (long) &vregs
->vscr
- new_cfa
;
296 fs
->regs
.reg
[R_VRSAVE
].how
= REG_SAVED_OFFSET
;
297 fs
->regs
.reg
[R_VRSAVE
].loc
.offset
= (long) &vregs
->vsave
- new_cfa
;
300 /* If we have SPE register high-parts... we check at compile-time to
301 avoid expanding the code for all other PowerPC. */
303 for (i
= 0; i
< 32; i
++)
305 fs
->regs
.reg
[i
+ FIRST_PSEUDO_REGISTER
- 1].how
= REG_SAVED_OFFSET
;
306 fs
->regs
.reg
[i
+ FIRST_PSEUDO_REGISTER
- 1].loc
.offset
307 = (long) ®s
->vregs
- new_cfa
+ 4 * i
;
311 return _URC_NO_REASON
;
314 #define MD_FROB_UPDATE_CONTEXT frob_update_context
317 frob_update_context (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs ATTRIBUTE_UNUSED
)
319 const unsigned int *pc
= (const unsigned int *) context
->ra
;
321 /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't
322 have S flag in it. */
324 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */
325 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */
326 if (pc
[0] == 0x38210000 + SIGNAL_FRAMESIZE
327 && (pc
[1] == 0x38000077 || pc
[1] == 0x380000AC)
328 && pc
[2] == 0x44000002)
329 _Unwind_SetSignalFrame (context
, 1);
331 /* li r0, 0x7777; sc (sigreturn old) */
332 /* li r0, 0x0077; sc (sigreturn new) */
333 /* li r0, 0x6666; sc (rt_sigreturn old) */
334 /* li r0, 0x00AC; sc (rt_sigreturn new) */
335 if ((pc
[0] == 0x38007777 || pc
[0] == 0x38000077
336 || pc
[0] == 0x38006666 || pc
[0] == 0x380000AC)
337 && pc
[1] == 0x44000002)
338 _Unwind_SetSignalFrame (context
, 1);
342 if (fs
->regs
.reg
[2].how
== REG_UNSAVED
)
344 /* If the current unwind info (FS) does not contain explicit info
345 saving R2, then we have to do a minor amount of code reading to
346 figure out if it was saved. The big problem here is that the
347 code that does the save/restore is generated by the linker, so
348 we have no good way to determine at compile time what to do. */
350 = (unsigned int *) _Unwind_GetGR (context
, R_LR
);
351 if (insn
&& *insn
== 0xE8410028)
352 _Unwind_SetGRPtr (context
, 2, context
->cfa
+ 40);