1 /* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux. 2 Copyright (C) 2004-2013 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 3, or (at your 9 option) any later version. 10 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. 15 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. 19 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/>. */ 24 25 #define R_LR 65 26 #define R_CR2 70 27 #define R_VR0 77 28 #define R_VRSAVE 109 29 30 struct gcc_vregs 31 { 32 __attribute__ ((vector_size (16))) int vr[32]; 33 #ifdef __powerpc64__ 34 unsigned int pad1[3]; 35 unsigned int vscr; 36 unsigned int vsave; 37 unsigned int pad2[3]; 38 #else 39 unsigned int vsave; 40 unsigned int pad[2]; 41 unsigned int vscr; 42 #endif 43 }; 44 45 struct gcc_regs 46 { 47 unsigned long gpr[32]; 48 unsigned long nip; 49 unsigned long msr; 50 unsigned long orig_gpr3; 51 unsigned long ctr; 52 unsigned long link; 53 unsigned long xer; 54 unsigned long ccr; 55 unsigned long softe; 56 unsigned long trap; 57 unsigned long dar; 58 unsigned long dsisr; 59 unsigned long result; 60 unsigned long pad1[4]; 61 double fpr[32]; 62 unsigned int pad2; 63 unsigned int fpscr; 64 #ifdef __powerpc64__ 65 struct gcc_vregs *vp; 66 #else 67 unsigned int pad3[2]; 68 #endif 69 struct gcc_vregs vregs; 70 }; 71 72 struct gcc_ucontext 73 { 74 #ifdef __powerpc64__ 75 unsigned long pad[28]; 76 #else 77 unsigned long pad[12]; 78 #endif 79 struct gcc_regs *regs; 80 struct gcc_regs rsave; 81 }; 82 83 #ifdef __powerpc64__ 84 85 enum { SIGNAL_FRAMESIZE = 128 }; 86 87 /* If PC is at a sigreturn trampoline, return a pointer to the 88 regs. Otherwise return NULL. */ 89 90 static struct gcc_regs * 91 get_regs (struct _Unwind_Context *context) 92 { 93 const unsigned int *pc = context->ra; 94 95 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ 96 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ 97 if (pc[0] != 0x38210000 + SIGNAL_FRAMESIZE || pc[2] != 0x44000002) 98 return NULL; 99 if (pc[1] == 0x38000077) 100 { 101 struct sigframe { 102 char gap[SIGNAL_FRAMESIZE]; 103 unsigned long pad[7]; 104 struct gcc_regs *regs; 105 } *frame = (struct sigframe *) context->cfa; 106 return frame->regs; 107 } 108 else if (pc[1] == 0x380000AC) 109 { 110 /* This works for 2.4 kernels, but not for 2.6 kernels with vdso 111 because pc isn't pointing into the stack. Can be removed when 112 no one is running 2.4.19 or 2.4.20, the first two ppc64 113 kernels released. */ 114 const struct rt_sigframe_24 { 115 int tramp[6]; 116 void *pinfo; 117 struct gcc_ucontext *puc; 118 } *frame24 = (const struct rt_sigframe_24 *) context->ra; 119 120 /* Test for magic value in *puc of vdso. */ 121 if ((long) frame24->puc != -21 * 8) 122 return frame24->puc->regs; 123 else 124 { 125 /* This works for 2.4.21 and later kernels. */ 126 struct rt_sigframe { 127 char gap[SIGNAL_FRAMESIZE]; 128 struct gcc_ucontext uc; 129 unsigned long pad[2]; 130 int tramp[6]; 131 void *pinfo; 132 struct gcc_ucontext *puc; 133 } *frame = (struct rt_sigframe *) context->cfa; 134 return frame->uc.regs; 135 } 136 } 137 return NULL; 138 } 139 140 #else /* !__powerpc64__ */ 141 142 enum { SIGNAL_FRAMESIZE = 64 }; 143 144 static struct gcc_regs * 145 get_regs (struct _Unwind_Context *context) 146 { 147 const unsigned int *pc = context->ra; 148 149 /* li r0, 0x7777; sc (sigreturn old) */ 150 /* li r0, 0x0077; sc (sigreturn new) */ 151 /* li r0, 0x6666; sc (rt_sigreturn old) */ 152 /* li r0, 0x00AC; sc (rt_sigreturn new) */ 153 if (pc[1] != 0x44000002) 154 return NULL; 155 if (pc[0] == 0x38007777 || pc[0] == 0x38000077) 156 { 157 struct sigframe { 158 char gap[SIGNAL_FRAMESIZE]; 159 unsigned long pad[7]; 160 struct gcc_regs *regs; 161 } *frame = (struct sigframe *) context->cfa; 162 return frame->regs; 163 } 164 else if (pc[0] == 0x38006666 || pc[0] == 0x380000AC) 165 { 166 struct rt_sigframe { 167 char gap[SIGNAL_FRAMESIZE + 16]; 168 char siginfo[128]; 169 struct gcc_ucontext uc; 170 } *frame = (struct rt_sigframe *) context->cfa; 171 return frame->uc.regs; 172 } 173 return NULL; 174 } 175 #endif 176 177 /* Do code reading to identify a signal frame, and set the frame 178 state data appropriately. See unwind-dw2.c for the structs. */ 179 180 #define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state 181 182 static _Unwind_Reason_Code 183 ppc_fallback_frame_state (struct _Unwind_Context *context, 184 _Unwind_FrameState *fs) 185 { 186 struct gcc_regs *regs = get_regs (context); 187 struct gcc_vregs *vregs; 188 long new_cfa; 189 int i; 190 191 if (regs == NULL) 192 return _URC_END_OF_STACK; 193 194 new_cfa = regs->gpr[STACK_POINTER_REGNUM]; 195 fs->regs.cfa_how = CFA_REG_OFFSET; 196 fs->regs.cfa_reg = STACK_POINTER_REGNUM; 197 fs->regs.cfa_offset = new_cfa - (long) context->cfa; 198 199 #ifdef __powerpc64__ 200 fs->regs.reg[2].how = REG_SAVED_OFFSET; 201 fs->regs.reg[2].loc.offset = (long) ®s->gpr[2] - new_cfa; 202 #endif 203 for (i = 14; i < 32; i++) 204 { 205 fs->regs.reg[i].how = REG_SAVED_OFFSET; 206 fs->regs.reg[i].loc.offset = (long) ®s->gpr[i] - new_cfa; 207 } 208 209 fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET; 210 /* CR? regs are always 32-bit and PPC is big-endian, so in 64-bit 211 libgcc loc.offset needs to point to the low 32 bits of regs->ccr. */ 212 fs->regs.reg[R_CR2].loc.offset = (long) ®s->ccr - new_cfa 213 + sizeof (long) - 4; 214 215 fs->regs.reg[R_LR].how = REG_SAVED_OFFSET; 216 fs->regs.reg[R_LR].loc.offset = (long) ®s->link - new_cfa; 217 218 fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; 219 fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) ®s->nip - new_cfa; 220 fs->retaddr_column = ARG_POINTER_REGNUM; 221 fs->signal_frame = 1; 222 223 /* If we have a FPU... */ 224 for (i = 14; i < 32; i++) 225 { 226 fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; 227 fs->regs.reg[i + 32].loc.offset = (long) ®s->fpr[i] - new_cfa; 228 } 229 230 /* If we have a VMX unit... */ 231 #ifdef __powerpc64__ 232 vregs = regs->vp; 233 #else 234 vregs = ®s->vregs; 235 #endif 236 if (regs->msr & (1 << 25)) 237 { 238 for (i = 20; i < 32; i++) 239 { 240 fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET; 241 fs->regs.reg[i + R_VR0].loc.offset = (long) &vregs->vr[i] - new_cfa; 242 } 243 } 244 245 fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET; 246 fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa; 247 248 /* If we have SPE register high-parts... we check at compile-time to 249 avoid expanding the code for all other PowerPC. */ 250 #ifdef __SPE__ 251 for (i = 14; i < 32; i++) 252 { 253 fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].how = REG_SAVED_OFFSET; 254 fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].loc.offset 255 = (long) ®s->vregs - new_cfa + 4 * i; 256 } 257 #endif 258 259 return _URC_NO_REASON; 260 } 261 262 #define MD_FROB_UPDATE_CONTEXT frob_update_context 263 264 static void 265 frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED) 266 { 267 const unsigned int *pc = (const unsigned int *) context->ra; 268 269 /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't 270 have S flag in it. */ 271 #ifdef __powerpc64__ 272 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ 273 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ 274 if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE 275 && (pc[1] == 0x38000077 || pc[1] == 0x380000AC) 276 && pc[2] == 0x44000002) 277 _Unwind_SetSignalFrame (context, 1); 278 #else 279 /* li r0, 0x7777; sc (sigreturn old) */ 280 /* li r0, 0x0077; sc (sigreturn new) */ 281 /* li r0, 0x6666; sc (rt_sigreturn old) */ 282 /* li r0, 0x00AC; sc (rt_sigreturn new) */ 283 if ((pc[0] == 0x38007777 || pc[0] == 0x38000077 284 || pc[0] == 0x38006666 || pc[0] == 0x380000AC) 285 && pc[1] == 0x44000002) 286 _Unwind_SetSignalFrame (context, 1); 287 #endif 288 289 #ifdef __powerpc64__ 290 if (fs->regs.reg[2].how == REG_UNSAVED) 291 { 292 /* If the current unwind info (FS) does not contain explicit info 293 saving R2, then we have to do a minor amount of code reading to 294 figure out if it was saved. The big problem here is that the 295 code that does the save/restore is generated by the linker, so 296 we have no good way to determine at compile time what to do. */ 297 if (pc[0] == 0xF8410028 298 || ((pc[0] & 0xFFFF0000) == 0x3D820000 299 && pc[1] == 0xF8410028)) 300 { 301 /* We are in a plt call stub or r2 adjusting long branch stub, 302 before r2 has been saved. Keep REG_UNSAVED. */ 303 } 304 else 305 { 306 unsigned int *insn 307 = (unsigned int *) _Unwind_GetGR (context, R_LR); 308 if (insn && *insn == 0xE8410028) 309 _Unwind_SetGRPtr (context, 2, context->cfa + 40); 310 else if (pc[0] == 0x4E800421 311 && pc[1] == 0xE8410028) 312 { 313 /* We are at the bctrl instruction in a call via function 314 pointer. gcc always emits the load of the new R2 just 315 before the bctrl so this is the first and only place 316 we need to use the stored R2. */ 317 _Unwind_Word sp = _Unwind_GetGR (context, 1); 318 _Unwind_SetGRPtr (context, 2, (void *)(sp + 40)); 319 } 320 } 321 } 322 #endif 323 } 324