1 /* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux.
2 Copyright (C) 2004-2019 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
40 struct 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
55 struct 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
82 struct 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
95 enum { SIGNAL_FRAMESIZE = 128 };
96
97 /* If PC is at a sigreturn trampoline, return a pointer to the
98 regs. Otherwise return NULL. */
99
100 static struct gcc_regs *
get_regs(struct _Unwind_Context * context)101 get_regs (struct _Unwind_Context *context)
102 {
103 const unsigned int *pc = context->ra;
104
105 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */
106 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */
107 if (pc[0] != 0x38210000 + SIGNAL_FRAMESIZE || pc[2] != 0x44000002)
108 return NULL;
109 if (pc[1] == 0x38000077)
110 {
111 struct sigframe {
112 char gap[SIGNAL_FRAMESIZE];
113 unsigned long pad[7];
114 struct gcc_regs *regs;
115 } *frame = (struct sigframe *) context->cfa;
116 return frame->regs;
117 }
118 else if (pc[1] == 0x380000AC)
119 {
120 #if _CALL_ELF != 2
121 /* These old kernel versions never supported ELFv2. */
122 /* This works for 2.4 kernels, but not for 2.6 kernels with vdso
123 because pc isn't pointing into the stack. Can be removed when
124 no one is running 2.4.19 or 2.4.20, the first two ppc64
125 kernels released. */
126 const struct rt_sigframe_24 {
127 int tramp[6];
128 void *pinfo;
129 struct gcc_ucontext *puc;
130 } *frame24 = (const struct rt_sigframe_24 *) context->ra;
131
132 /* Test for magic value in *puc of vdso. */
133 if ((long) frame24->puc != -21 * 8)
134 return frame24->puc->regs;
135 else
136 #endif
137 {
138 /* This works for 2.4.21 and later kernels. */
139 struct rt_sigframe {
140 char gap[SIGNAL_FRAMESIZE];
141 struct gcc_ucontext uc;
142 unsigned long pad[2];
143 int tramp[6];
144 void *pinfo;
145 struct gcc_ucontext *puc;
146 } *frame = (struct rt_sigframe *) context->cfa;
147 return frame->uc.regs;
148 }
149 }
150 return NULL;
151 }
152
153 #else /* !__powerpc64__ */
154
155 enum { SIGNAL_FRAMESIZE = 64 };
156
157 static struct gcc_regs *
get_regs(struct _Unwind_Context * context)158 get_regs (struct _Unwind_Context *context)
159 {
160 const unsigned int *pc = context->ra;
161
162 /* li r0, 0x7777; sc (sigreturn old) */
163 /* li r0, 0x0077; sc (sigreturn new) */
164 /* li r0, 0x6666; sc (rt_sigreturn old) */
165 /* li r0, 0x00AC; sc (rt_sigreturn new) */
166 if (pc[1] != 0x44000002)
167 return NULL;
168 if (pc[0] == 0x38007777 || pc[0] == 0x38000077)
169 {
170 struct sigframe {
171 char gap[SIGNAL_FRAMESIZE];
172 unsigned long pad[7];
173 struct gcc_regs *regs;
174 } *frame = (struct sigframe *) context->cfa;
175 return frame->regs;
176 }
177 else if (pc[0] == 0x38006666 || pc[0] == 0x380000AC)
178 {
179 struct rt_sigframe {
180 char gap[SIGNAL_FRAMESIZE + 16];
181 char siginfo[128];
182 struct gcc_ucontext uc;
183 } *frame = (struct rt_sigframe *) context->cfa;
184 return frame->uc.regs;
185 }
186 return NULL;
187 }
188 #endif
189
190 /* Do code reading to identify a signal frame, and set the frame
191 state data appropriately. See unwind-dw2.c for the structs. */
192
193 #define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state
194
195 static _Unwind_Reason_Code
ppc_fallback_frame_state(struct _Unwind_Context * context,_Unwind_FrameState * fs)196 ppc_fallback_frame_state (struct _Unwind_Context *context,
197 _Unwind_FrameState *fs)
198 {
199 struct gcc_regs *regs = get_regs (context);
200 struct gcc_vregs *vregs;
201 long cr_offset;
202 long new_cfa;
203 int i;
204
205 if (regs == NULL)
206 return _URC_END_OF_STACK;
207
208 new_cfa = regs->gpr[__LIBGCC_STACK_POINTER_REGNUM__];
209 fs->regs.cfa_how = CFA_REG_OFFSET;
210 fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
211 fs->regs.cfa_offset = new_cfa - (long) context->cfa;
212
213 #ifdef __powerpc64__
214 fs->regs.reg[2].how = REG_SAVED_OFFSET;
215 fs->regs.reg[2].loc.offset = (long) ®s->gpr[2] - new_cfa;
216 #endif
217 for (i = 14; i < 32; i++)
218 {
219 fs->regs.reg[i].how = REG_SAVED_OFFSET;
220 fs->regs.reg[i].loc.offset = (long) ®s->gpr[i] - new_cfa;
221 }
222
223 /* The CR is saved in the low 32 bits of regs->ccr. */
224 cr_offset = (long) ®s->ccr - new_cfa;
225 #ifndef __LITTLE_ENDIAN__
226 cr_offset += sizeof (long) - 4;
227 #endif
228 /* In the ELFv1 ABI, CR2 stands in for the whole CR. */
229 fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET;
230 fs->regs.reg[R_CR2].loc.offset = cr_offset;
231 #if _CALL_ELF == 2
232 /* In the ELFv2 ABI, every CR field has a separate CFI entry. */
233 fs->regs.reg[R_CR3].how = REG_SAVED_OFFSET;
234 fs->regs.reg[R_CR3].loc.offset = cr_offset;
235 fs->regs.reg[R_CR4].how = REG_SAVED_OFFSET;
236 fs->regs.reg[R_CR4].loc.offset = cr_offset;
237 #endif
238
239 fs->regs.reg[R_LR].how = REG_SAVED_OFFSET;
240 fs->regs.reg[R_LR].loc.offset = (long) ®s->link - new_cfa;
241
242 fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET;
243 fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) ®s->nip - new_cfa;
244 fs->retaddr_column = ARG_POINTER_REGNUM;
245 fs->signal_frame = 1;
246
247 /* If we have a FPU... */
248 for (i = 14; i < 32; i++)
249 {
250 fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
251 fs->regs.reg[i + 32].loc.offset = (long) ®s->fpr[i] - new_cfa;
252 }
253
254 /* If we have a VMX unit... */
255 #ifdef __powerpc64__
256 vregs = regs->vp;
257 #else
258 vregs = ®s->vregs;
259 #endif
260 if (regs->msr & (1 << 25))
261 {
262 for (i = 20; i < 32; i++)
263 {
264 fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET;
265 fs->regs.reg[i + R_VR0].loc.offset = (long) &vregs->vr[i] - new_cfa;
266 }
267 }
268
269 fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET;
270 fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa;
271
272 /* If we have SPE register high-parts... we check at compile-time to
273 avoid expanding the code for all other PowerPC. */
274 #ifdef __SPE__
275 for (i = 14; i < 32; i++)
276 {
277 fs->regs.reg[i + FIRST_SPE_HIGH_REGNO - 4].how = REG_SAVED_OFFSET;
278 fs->regs.reg[i + FIRST_SPE_HIGH_REGNO - 4].loc.offset
279 = (long) ®s->vregs - new_cfa + 4 * i;
280 }
281 #endif
282
283 return _URC_NO_REASON;
284 }
285
286 #define MD_FROB_UPDATE_CONTEXT frob_update_context
287
288 static void
frob_update_context(struct _Unwind_Context * context,_Unwind_FrameState * fs ATTRIBUTE_UNUSED)289 frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED)
290 {
291 const unsigned int *pc = (const unsigned int *) context->ra;
292
293 /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't
294 have S flag in it. */
295 #ifdef __powerpc64__
296 /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */
297 /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */
298 if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE
299 && (pc[1] == 0x38000077 || pc[1] == 0x380000AC)
300 && pc[2] == 0x44000002)
301 _Unwind_SetSignalFrame (context, 1);
302 #else
303 /* li r0, 0x7777; sc (sigreturn old) */
304 /* li r0, 0x0077; sc (sigreturn new) */
305 /* li r0, 0x6666; sc (rt_sigreturn old) */
306 /* li r0, 0x00AC; sc (rt_sigreturn new) */
307 if ((pc[0] == 0x38007777 || pc[0] == 0x38000077
308 || pc[0] == 0x38006666 || pc[0] == 0x380000AC)
309 && pc[1] == 0x44000002)
310 _Unwind_SetSignalFrame (context, 1);
311 #endif
312
313 #ifdef __powerpc64__
314 if (fs->regs.reg[2].how == REG_UNSAVED)
315 {
316 /* If the current unwind info (FS) does not contain explicit info
317 saving R2, then we have to do a minor amount of code reading to
318 figure out if it was saved. The big problem here is that the
319 code that does the save/restore is generated by the linker, so
320 we have no good way to determine at compile time what to do. */
321 if (pc[0] == 0xF8410000 + TOC_SAVE_SLOT
322 #if _CALL_ELF != 2
323 /* The ELFv2 linker never generates the old PLT stub form. */
324 || ((pc[0] & 0xFFFF0000) == 0x3D820000
325 && pc[1] == 0xF8410000 + TOC_SAVE_SLOT)
326 #endif
327 )
328 {
329 /* We are in a plt call stub or r2 adjusting long branch stub,
330 before r2 has been saved. Keep REG_UNSAVED. */
331 }
332 else
333 {
334 unsigned int *insn
335 = (unsigned int *) _Unwind_GetGR (context, R_LR);
336 if (insn && *insn == 0xE8410000 + TOC_SAVE_SLOT)
337 _Unwind_SetGRPtr (context, 2, context->cfa + TOC_SAVE_SLOT);
338 #if _CALL_ELF != 2
339 /* ELFv2 does not use this function pointer call sequence. */
340 else if (pc[0] == 0x4E800421
341 && pc[1] == 0xE8410000 + TOC_SAVE_SLOT)
342 {
343 /* We are at the bctrl instruction in a call via function
344 pointer. gcc always emits the load of the new R2 just
345 before the bctrl so this is the first and only place
346 we need to use the stored R2. */
347 _Unwind_Word sp = _Unwind_GetGR (context, 1);
348 _Unwind_SetGRPtr (context, 2, (void *)(sp + TOC_SAVE_SLOT));
349 }
350 #endif
351 }
352 }
353 #endif
354 }
355