1/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux. 2 Copyright (C) 2004, 2005, 2006 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 8 by the Free Software Foundation; either version 2, or (at your 9 option) any later version. 10 11 In addition to the permissions in the GNU General Public License, 12 the Free Software Foundation gives you unlimited permission to link 13 the compiled version of this file with other programs, and to 14 distribute those programs without any restriction coming from the 15 use of this file. (The General Public License restrictions do 16 apply in other respects; for example, they cover modification of 17 the file, and distribution when not linked into another program.) 18 19 GCC is distributed in the hope that it will be useful, but WITHOUT 20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 21 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22 License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with GCC; see the file COPYING. If not, write to the 26 Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, 27 MA 02110-1301, USA. */ 28 29/* This file defines our own versions of various kernel and user 30 structs, so that system headers are not needed, which otherwise 31 can make bootstrapping a new toolchain difficult. Do not use 32 these structs elsewhere; Many fields are missing, particularly 33 from the end of the structures. */ 34 35struct gcc_vregs 36{ 37 __attribute__ ((vector_size (16))) int vr[32]; 38#ifdef __powerpc64__ 39 unsigned int pad1[3]; 40 unsigned int vscr; 41 unsigned int vsave; 42 unsigned int pad2[3]; 43#else 44 unsigned int vsave; 45 unsigned int pad[2]; 46 unsigned int vscr; 47#endif 48}; 49 50struct gcc_regs 51{ 52 unsigned long gpr[32]; 53 unsigned long nip; 54 unsigned long msr; 55 unsigned long orig_gpr3; 56 unsigned long ctr; 57 unsigned long link; 58 unsigned long xer; 59 unsigned long ccr; 60 unsigned long softe; 61 unsigned long trap; 62 unsigned long dar; 63 unsigned long dsisr; 64 unsigned long result; 65 unsigned long pad1[4]; 66 double fpr[32]; 67 unsigned int pad2; 68 unsigned int fpscr; 69#ifdef __powerpc64__ 70 struct gcc_vregs *vp; 71#else 72 unsigned int pad3[2]; 73#endif 74 struct gcc_vregs vregs; 75}; 76 77struct gcc_ucontext 78{ 79#ifdef __powerpc64__ 80 unsigned long pad[28]; 81#else 82 unsigned long pad[12]; 83#endif 84 struct gcc_regs *regs; 85 struct gcc_regs rsave; 86}; 87 88#ifdef __powerpc64__ 89 90enum { SIGNAL_FRAMESIZE = 128 }; 91 92/* If PC is at a sigreturn trampoline, return a pointer to the 93 regs. Otherwise return NULL. */ 94 95static struct gcc_regs * 96get_regs (struct _Unwind_Context *context) 97{ 98 const unsigned char *pc = context->ra; 99 100 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ 101 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ 102 if (*(unsigned int *) (pc + 0) != 0x38210000 + SIGNAL_FRAMESIZE 103 || *(unsigned int *) (pc + 8) != 0x44000002) 104 return NULL; 105 if (*(unsigned int *) (pc + 4) == 0x38000077) 106 { 107 struct sigframe { 108 char gap[SIGNAL_FRAMESIZE]; 109 unsigned long pad[7]; 110 struct gcc_regs *regs; 111 } *frame = (struct sigframe *) context->cfa; 112 return frame->regs; 113 } 114 else if (*(unsigned int *) (pc + 4) == 0x380000AC) 115 { 116 /* This works for 2.4 kernels, but not for 2.6 kernels with vdso 117 because pc isn't pointing into the stack. Can be removed when 118 no one is running 2.4.19 or 2.4.20, the first two ppc64 119 kernels released. */ 120 struct rt_sigframe_24 { 121 int tramp[6]; 122 void *pinfo; 123 struct gcc_ucontext *puc; 124 } *frame24 = (struct rt_sigframe_24 *) pc; 125 126 /* Test for magic value in *puc of vdso. */ 127 if ((long) frame24->puc != -21 * 8) 128 return frame24->puc->regs; 129 else 130 { 131 /* This works for 2.4.21 and later kernels. */ 132 struct rt_sigframe { 133 char gap[SIGNAL_FRAMESIZE]; 134 struct gcc_ucontext uc; 135 unsigned long pad[2]; 136 int tramp[6]; 137 void *pinfo; 138 struct gcc_ucontext *puc; 139 } *frame = (struct rt_sigframe *) context->cfa; 140 return frame->uc.regs; 141 } 142 } 143 return NULL; 144} 145 146#else /* !__powerpc64__ */ 147 148enum { SIGNAL_FRAMESIZE = 64 }; 149 150static struct gcc_regs * 151get_regs (struct _Unwind_Context *context) 152{ 153 const unsigned char *pc = context->ra; 154 155 /* li r0, 0x7777; sc (sigreturn old) */ 156 /* li r0, 0x0077; sc (sigreturn new) */ 157 /* li r0, 0x6666; sc (rt_sigreturn old) */ 158 /* li r0, 0x00AC; sc (rt_sigreturn new) */ 159 if (*(unsigned int *) (pc + 4) != 0x44000002) 160 return NULL; 161 if (*(unsigned int *) (pc + 0) == 0x38007777 162 || *(unsigned int *) (pc + 0) == 0x38000077) 163 { 164 struct sigframe { 165 char gap[SIGNAL_FRAMESIZE]; 166 unsigned long pad[7]; 167 struct gcc_regs *regs; 168 } *frame = (struct sigframe *) context->cfa; 169 return frame->regs; 170 } 171 else if (*(unsigned int *) (pc + 0) == 0x38006666 172 || *(unsigned int *) (pc + 0) == 0x380000AC) 173 { 174 struct rt_sigframe { 175 char gap[SIGNAL_FRAMESIZE + 16]; 176 char siginfo[128]; 177 struct gcc_ucontext uc; 178 } *frame = (struct rt_sigframe *) context->cfa; 179 return frame->uc.regs; 180 } 181 return NULL; 182} 183#endif 184 185/* Find an entry in the process auxiliary vector. The canonical way to 186 test for VMX is to look at AT_HWCAP. */ 187 188static long 189ppc_linux_aux_vector (long which) 190{ 191 /* __libc_stack_end holds the original stack passed to a process. */ 192 extern long *__libc_stack_end; 193 long argc; 194 char **argv; 195 char **envp; 196 struct auxv 197 { 198 long a_type; 199 long a_val; 200 } *auxp; 201 202 /* The Linux kernel puts argc first on the stack. */ 203 argc = __libc_stack_end[0]; 204 /* Followed by argv, NULL terminated. */ 205 argv = (char **) __libc_stack_end + 1; 206 /* Followed by environment string pointers, NULL terminated. */ 207 envp = argv + argc + 1; 208 while (*envp++) 209 continue; 210 /* Followed by the aux vector, zero terminated. */ 211 for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp) 212 if (auxp->a_type == which) 213 return auxp->a_val; 214 return 0; 215} 216 217/* Do code reading to identify a signal frame, and set the frame 218 state data appropriately. See unwind-dw2.c for the structs. */ 219 220#define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state 221 222static _Unwind_Reason_Code 223ppc_fallback_frame_state (struct _Unwind_Context *context, 224 _Unwind_FrameState *fs) 225{ 226 static long hwcap = 0; 227 struct gcc_regs *regs = get_regs (context); 228 long new_cfa; 229 int i; 230 231 if (regs == NULL) 232 return _URC_END_OF_STACK; 233 234 new_cfa = regs->gpr[STACK_POINTER_REGNUM]; 235 fs->cfa_how = CFA_REG_OFFSET; 236 fs->cfa_reg = STACK_POINTER_REGNUM; 237 fs->cfa_offset = new_cfa - (long) context->cfa; 238 239 for (i = 0; i < 32; i++) 240 if (i != STACK_POINTER_REGNUM) 241 { 242 fs->regs.reg[i].how = REG_SAVED_OFFSET; 243 fs->regs.reg[i].loc.offset = (long) ®s->gpr[i] - new_cfa; 244 } 245 246 fs->regs.reg[CR2_REGNO].how = REG_SAVED_OFFSET; 247 fs->regs.reg[CR2_REGNO].loc.offset = (long) ®s->ccr - new_cfa; 248 249 fs->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; 250 fs->regs.reg[LINK_REGISTER_REGNUM].loc.offset = (long) ®s->link - new_cfa; 251 252 fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; 253 fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) ®s->nip - new_cfa; 254 fs->retaddr_column = ARG_POINTER_REGNUM; 255 fs->signal_frame = 1; 256 257 if (hwcap == 0) 258 { 259 hwcap = ppc_linux_aux_vector (16); 260 /* These will already be set if we found AT_HWCAP. A nonzero 261 value stops us looking again if for some reason we couldn't 262 find AT_HWCAP. */ 263#ifdef __powerpc64__ 264 hwcap |= 0xc0000000; 265#else 266 hwcap |= 0x80000000; 267#endif 268 } 269 270 /* If we have a FPU... */ 271 if (hwcap & 0x08000000) 272 for (i = 0; i < 32; i++) 273 { 274 fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; 275 fs->regs.reg[i + 32].loc.offset = (long) ®s->fpr[i] - new_cfa; 276 } 277 278 /* If we have a VMX unit... */ 279 if (hwcap & 0x10000000) 280 { 281 struct gcc_vregs *vregs; 282#ifdef __powerpc64__ 283 vregs = regs->vp; 284#else 285 vregs = ®s->vregs; 286#endif 287 if (regs->msr & (1 << 25)) 288 { 289 for (i = 0; i < 32; i++) 290 { 291 fs->regs.reg[i + FIRST_ALTIVEC_REGNO].how = REG_SAVED_OFFSET; 292 fs->regs.reg[i + FIRST_ALTIVEC_REGNO].loc.offset 293 = (long) &vregs[i] - new_cfa; 294 } 295 296 fs->regs.reg[VSCR_REGNO].how = REG_SAVED_OFFSET; 297 fs->regs.reg[VSCR_REGNO].loc.offset = (long) &vregs->vscr - new_cfa; 298 } 299 300 fs->regs.reg[VRSAVE_REGNO].how = REG_SAVED_OFFSET; 301 fs->regs.reg[VRSAVE_REGNO].loc.offset = (long) &vregs->vsave - new_cfa; 302 } 303 304 return _URC_NO_REASON; 305} 306 307#define MD_FROB_UPDATE_CONTEXT frob_update_context 308 309static void 310frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED) 311{ 312 const unsigned int *pc = (const unsigned int *) context->ra; 313 314 /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't 315 have S flag in it. */ 316#ifdef __powerpc64__ 317 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ 318 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ 319 if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE 320 && (pc[1] == 0x38000077 || pc[1] == 0x380000AC) 321 && pc[2] == 0x44000002) 322 _Unwind_SetSignalFrame (context, 1); 323#else 324 /* li r0, 0x7777; sc (sigreturn old) */ 325 /* li r0, 0x0077; sc (sigreturn new) */ 326 /* li r0, 0x6666; sc (rt_sigreturn old) */ 327 /* li r0, 0x00AC; sc (rt_sigreturn new) */ 328 if ((pc[0] == 0x38007777 || pc[0] == 0x38000077 329 || pc[0] == 0x38006666 || pc[0] == 0x380000AC) 330 && pc[1] == 0x44000002) 331 _Unwind_SetSignalFrame (context, 1); 332#endif 333 334#ifdef __powerpc64__ 335 if (fs->regs.reg[2].how == REG_UNSAVED) 336 { 337 /* If the current unwind info (FS) does not contain explicit info 338 saving R2, then we have to do a minor amount of code reading to 339 figure out if it was saved. The big problem here is that the 340 code that does the save/restore is generated by the linker, so 341 we have no good way to determine at compile time what to do. */ 342 unsigned int *insn 343 = (unsigned int *) _Unwind_GetGR (context, LINK_REGISTER_REGNUM); 344 if (*insn == 0xE8410028) 345 _Unwind_SetGRPtr (context, 2, context->cfa + 40); 346 } 347#endif 348} 349