1/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux. 2 Copyright (C) 2004-2022 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_CR3 71 28#define R_CR4 72 29#define R_VR0 77 30#define R_VRSAVE 109 31 32#ifdef __powerpc64__ 33#if _CALL_ELF == 2 34#define TOC_SAVE_SLOT 24 35#else 36#define TOC_SAVE_SLOT 40 37#endif 38#endif 39 40struct gcc_vregs 41{ 42 __attribute__ ((vector_size (16))) int vr[32]; 43#ifdef __powerpc64__ 44 unsigned int pad1[3]; 45 unsigned int vscr; 46 unsigned int vsave; 47 unsigned int pad2[3]; 48#else 49 unsigned int vsave; 50 unsigned int pad[2]; 51 unsigned int vscr; 52#endif 53}; 54 55struct gcc_regs 56{ 57 unsigned long gpr[32]; 58 unsigned long nip; 59 unsigned long msr; 60 unsigned long orig_gpr3; 61 unsigned long ctr; 62 unsigned long link; 63 unsigned long xer; 64 unsigned long ccr; 65 unsigned long softe; 66 unsigned long trap; 67 unsigned long dar; 68 unsigned long dsisr; 69 unsigned long result; 70 unsigned long pad1[4]; 71 double fpr[32]; 72 unsigned int pad2; 73 unsigned int fpscr; 74#ifdef __powerpc64__ 75 struct gcc_vregs *vp; 76#else 77 unsigned int pad3[2]; 78#endif 79 struct gcc_vregs vregs; 80}; 81 82struct gcc_ucontext 83{ 84#ifdef __powerpc64__ 85 unsigned long pad[28]; 86#else 87 unsigned long pad[12]; 88#endif 89 struct gcc_regs *regs; 90 struct gcc_regs rsave; 91}; 92 93#ifdef __powerpc64__ 94 95enum { SIGNAL_FRAMESIZE = 128 }; 96 97struct rt_sigframe { 98 char gap[SIGNAL_FRAMESIZE]; 99 struct gcc_ucontext uc; 100 unsigned long pad[2]; 101 int tramp[6]; 102 void *pinfo; 103 struct gcc_ucontext *puc; 104}; 105 106/* If PC is at a sigreturn trampoline, return a pointer to the 107 regs. Otherwise return NULL. */ 108 109static struct gcc_regs * 110get_regs (struct _Unwind_Context *context) 111{ 112 const unsigned int *pc = context->ra; 113 114 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ 115 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ 116 if (pc[0] != 0x38210000 + SIGNAL_FRAMESIZE || pc[2] != 0x44000002) 117 return NULL; 118 if (pc[1] == 0x38000077) 119 { 120 struct sigframe { 121 char gap[SIGNAL_FRAMESIZE]; 122 unsigned long pad[7]; 123 struct gcc_regs *regs; 124 } *frame = (struct sigframe *) context->cfa; 125 return frame->regs; 126 } 127 else if (pc[1] == 0x380000AC) 128 { 129#if _CALL_ELF != 2 130 /* These old kernel versions never supported ELFv2. */ 131 /* This works for 2.4 kernels, but not for 2.6 kernels with vdso 132 because pc isn't pointing into the stack. Can be removed when 133 no one is running 2.4.19 or 2.4.20, the first two ppc64 134 kernels released. */ 135 const struct rt_sigframe_24 { 136 int tramp[6]; 137 void *pinfo; 138 struct gcc_ucontext *puc; 139 } *frame24 = (const struct rt_sigframe_24 *) context->ra; 140 141 /* Test for magic value in *puc of vdso. */ 142 if ((long) frame24->puc != -21 * 8) 143 return frame24->puc->regs; 144 else 145#endif 146 { 147 /* This works for 2.4.21 and later kernels. */ 148 struct rt_sigframe *frame = (struct rt_sigframe *) context->cfa; 149 return frame->uc.regs; 150 } 151 } 152 return NULL; 153} 154 155#else /* !__powerpc64__ */ 156 157enum { SIGNAL_FRAMESIZE = 64 }; 158 159struct rt_sigframe { 160 char gap[SIGNAL_FRAMESIZE + 16]; 161 char siginfo[128]; 162 struct gcc_ucontext uc; 163}; 164 165static struct gcc_regs * 166get_regs (struct _Unwind_Context *context) 167{ 168 const unsigned int *pc = context->ra; 169 170 /* li r0, 0x7777; sc (sigreturn old) */ 171 /* li r0, 0x0077; sc (sigreturn new) */ 172 /* li r0, 0x6666; sc (rt_sigreturn old) */ 173 /* li r0, 0x00AC; sc (rt_sigreturn new) */ 174 if (pc[1] != 0x44000002) 175 return NULL; 176 if (pc[0] == 0x38007777 || pc[0] == 0x38000077) 177 { 178 struct sigframe { 179 char gap[SIGNAL_FRAMESIZE]; 180 unsigned long pad[7]; 181 struct gcc_regs *regs; 182 } *frame = (struct sigframe *) context->cfa; 183 return frame->regs; 184 } 185 else if (pc[0] == 0x38006666 || pc[0] == 0x380000AC) 186 { 187 struct rt_sigframe *frame = (struct rt_sigframe *) context->cfa; 188 return frame->uc.regs; 189 } 190 return NULL; 191} 192#endif 193 194/* Do code reading to identify a signal frame, and set the frame 195 state data appropriately. See unwind-dw2.c for the structs. */ 196 197#define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state 198 199static _Unwind_Reason_Code 200ppc_fallback_frame_state (struct _Unwind_Context *context, 201 _Unwind_FrameState *fs) 202{ 203 struct gcc_regs *regs = get_regs (context); 204 struct gcc_vregs *vregs; 205 long cr_offset; 206 long new_cfa; 207 int i; 208 209 if (regs == NULL) 210 return _URC_NORMAL_STOP; 211 212 new_cfa = regs->gpr[__LIBGCC_STACK_POINTER_REGNUM__]; 213 fs->regs.cfa_how = CFA_REG_OFFSET; 214 fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__; 215 fs->regs.cfa_offset = new_cfa - (long) context->cfa; 216 217#ifdef __powerpc64__ 218 fs->regs.reg[2].how = REG_SAVED_OFFSET; 219 fs->regs.reg[2].loc.offset = (long) ®s->gpr[2] - new_cfa; 220#endif 221 for (i = 14; i < 32; i++) 222 { 223 fs->regs.reg[i].how = REG_SAVED_OFFSET; 224 fs->regs.reg[i].loc.offset = (long) ®s->gpr[i] - new_cfa; 225 } 226 227 /* The CR is saved in the low 32 bits of regs->ccr. */ 228 cr_offset = (long) ®s->ccr - new_cfa; 229#ifndef __LITTLE_ENDIAN__ 230 cr_offset += sizeof (long) - 4; 231#endif 232 /* In the ELFv1 ABI, CR2 stands in for the whole CR. */ 233 fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET; 234 fs->regs.reg[R_CR2].loc.offset = cr_offset; 235#if _CALL_ELF == 2 236 /* In the ELFv2 ABI, every CR field has a separate CFI entry. */ 237 fs->regs.reg[R_CR3].how = REG_SAVED_OFFSET; 238 fs->regs.reg[R_CR3].loc.offset = cr_offset; 239 fs->regs.reg[R_CR4].how = REG_SAVED_OFFSET; 240 fs->regs.reg[R_CR4].loc.offset = cr_offset; 241#endif 242 243 fs->regs.reg[R_LR].how = REG_SAVED_OFFSET; 244 fs->regs.reg[R_LR].loc.offset = (long) ®s->link - new_cfa; 245 246 fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; 247 fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) ®s->nip - new_cfa; 248 fs->retaddr_column = ARG_POINTER_REGNUM; 249 fs->signal_frame = 1; 250 251 /* If we have a FPU... */ 252 for (i = 14; i < 32; i++) 253 { 254 fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; 255 fs->regs.reg[i + 32].loc.offset = (long) ®s->fpr[i] - new_cfa; 256 } 257 258 /* If we have a VMX unit... */ 259#ifdef __powerpc64__ 260 vregs = regs->vp; 261#else 262 vregs = ®s->vregs; 263#endif 264 if (regs->msr & (1 << 25)) 265 { 266 for (i = 20; i < 32; i++) 267 { 268 fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET; 269 fs->regs.reg[i + R_VR0].loc.offset = (long) &vregs->vr[i] - new_cfa; 270 } 271 } 272 273 fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET; 274 fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa; 275 276 /* If we have SPE register high-parts... we check at compile-time to 277 avoid expanding the code for all other PowerPC. */ 278#ifdef __SPE__ 279 for (i = 14; i < 32; i++) 280 { 281 fs->regs.reg[i + FIRST_SPE_HIGH_REGNO - 4].how = REG_SAVED_OFFSET; 282 fs->regs.reg[i + FIRST_SPE_HIGH_REGNO - 4].loc.offset 283 = (long) ®s->vregs - new_cfa + 4 * i; 284 } 285#endif 286 287 return _URC_NO_REASON; 288} 289 290#define MD_FROB_UPDATE_CONTEXT frob_update_context 291 292static void 293frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED) 294{ 295 const unsigned int *pc = (const unsigned int *) context->ra; 296 297 /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't 298 have S flag in it. */ 299#ifdef __powerpc64__ 300 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ 301 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ 302 if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE 303 && (pc[1] == 0x38000077 || pc[1] == 0x380000AC) 304 && pc[2] == 0x44000002) 305 _Unwind_SetSignalFrame (context, 1); 306#else 307 /* li r0, 0x7777; sc (sigreturn old) */ 308 /* li r0, 0x0077; sc (sigreturn new) */ 309 /* li r0, 0x6666; sc (rt_sigreturn old) */ 310 /* li r0, 0x00AC; sc (rt_sigreturn new) */ 311 if ((pc[0] == 0x38007777 || pc[0] == 0x38000077 312 || pc[0] == 0x38006666 || pc[0] == 0x380000AC) 313 && pc[1] == 0x44000002) 314 _Unwind_SetSignalFrame (context, 1); 315#endif 316 317#ifdef __powerpc64__ 318 if (fs->regs.reg[2].how == REG_UNSAVED) 319 { 320 /* If the current unwind info (FS) does not contain explicit info 321 saving R2, then we have to do a minor amount of code reading to 322 figure out if it was saved. The big problem here is that the 323 code that does the save/restore is generated by the linker, so 324 we have no good way to determine at compile time what to do. */ 325 if (pc[0] == 0xF8410000 + TOC_SAVE_SLOT 326#if _CALL_ELF != 2 327 /* The ELFv2 linker never generates the old PLT stub form. */ 328 || ((pc[0] & 0xFFFF0000) == 0x3D820000 329 && pc[1] == 0xF8410000 + TOC_SAVE_SLOT) 330#endif 331 ) 332 { 333 /* We are in a plt call stub or r2 adjusting long branch stub, 334 before r2 has been saved. Keep REG_UNSAVED. */ 335 } 336 else 337 { 338 unsigned int *insn 339 = (unsigned int *) _Unwind_GetGR (context, R_LR); 340 if (insn && *insn == 0xE8410000 + TOC_SAVE_SLOT) 341 _Unwind_SetGRPtr (context, 2, context->cfa + TOC_SAVE_SLOT); 342#if _CALL_ELF != 2 343 /* ELFv2 does not use this function pointer call sequence. */ 344 else if (pc[0] == 0x4E800421 345 && pc[1] == 0xE8410000 + TOC_SAVE_SLOT) 346 { 347 /* We are at the bctrl instruction in a call via function 348 pointer. gcc always emits the load of the new R2 just 349 before the bctrl so this is the first and only place 350 we need to use the stored R2. */ 351 _Unwind_Word sp = _Unwind_GetGR (context, 1); 352 _Unwind_SetGRPtr (context, 2, (void *)(sp + TOC_SAVE_SLOT)); 353 } 354#endif 355 } 356 } 357#endif 358} 359 360#define MD_BACKCHAIN_FALLBACK ppc_backchain_fallback 361 362struct trace_arg 363{ 364 /* Stores the list of addresses. */ 365 void **array; 366 struct unwind_link *unwind_link; 367 _Unwind_Word cfa; 368 /* Number of addresses currently stored. */ 369 int count; 370 /* Maximum number of addresses. */ 371 int size; 372}; 373 374/* This is the stack layout we see with every stack frame. 375 Note that every routine is required by the ABI to lay out the stack 376 like this. 377 378 +----------------+ +-----------------+ 379 %r1 -> | previous frame--------> | previous frame--->... --> NULL 380 | | | | 381 | cr save | | cr save | 382 | | | | 383 | (unused) | | lr save | 384 +----------------+ +-----------------+ 385 386 The CR save is only present on 64-bit ABIs. 387*/ 388struct frame_layout 389{ 390 struct frame_layout *backchain; 391#ifdef __powerpc64__ 392 long int cr_save; 393#endif 394 void *lr_save; 395}; 396 397 398static void 399ppc_backchain_fallback (struct _Unwind_Context *context, void *a) 400{ 401 struct frame_layout *current; 402 struct trace_arg *arg = a; 403 int count; 404 405 /* Get the last address computed. */ 406 current = context->cfa; 407 408 /* If the trace CFA is not the context CFA the backtrace is done. */ 409 if (arg == NULL || arg->cfa != current) 410 return; 411 412 /* Start with next address. */ 413 current = current->backchain; 414 415 for (count = arg->count; current != NULL; current = current->backchain) 416 { 417 arg->array[count] = current->lr_save; 418 419 /* Check if the symbol is the signal trampoline and get the interrupted 420 symbol address from the trampoline saved area. */ 421 context->ra = current->lr_save; 422 if (current->lr_save && get_regs (context)) 423 { 424 struct rt_sigframe *sigframe = (struct rt_sigframe *) current; 425 if (count + 1 == arg->size) 426 break; 427 arg->array[++count] = (void *) sigframe->uc.rsave.nip; 428 current = (void *) sigframe->uc.rsave.gpr[1]; 429 } 430 if (count++ >= arg->size) 431 break; 432 } 433 434 arg->count = count-1; 435} 436