1 /* Fallback frame-state unwinder for Darwin.
2    Copyright (C) 2004-2018 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 by
8    the Free Software Foundation; either version 3, or (at your option)
9    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 #ifdef __ppc__
26 
27 #include "tconfig.h"
28 #include "tsystem.h"
29 #include "coretypes.h"
30 #include "tm.h"
31 #include "libgcc_tm.h"
32 #include "dwarf2.h"
33 #include "unwind.h"
34 #include "unwind-dw2.h"
35 #include <stdint.h>
36 #include <stdbool.h>
37 #include <sys/types.h>
38 #include <signal.h>
39 
40 #define R_LR		65
41 #define R_CTR		66
42 #define R_CR2		70
43 #define R_XER		76
44 #define R_VR0		77
45 #define R_VRSAVE	109
46 #define R_VSCR		110
47 #define R_SPEFSCR	112
48 
49 typedef unsigned long reg_unit;
50 
51 /* Place in GPRS the parameters to the first 'sc' instruction that would
52    have been executed if we were returning from this CONTEXT, or
53    return false if an unexpected instruction is encountered.  */
54 
55 static bool
interpret_libc(reg_unit gprs[32],struct _Unwind_Context * context)56 interpret_libc (reg_unit gprs[32], struct _Unwind_Context *context)
57 {
58   uint32_t *pc = (uint32_t *)_Unwind_GetIP (context);
59   uint32_t cr;
60   reg_unit lr = (reg_unit) pc;
61   reg_unit ctr = 0;
62   uint32_t *invalid_address = NULL;
63 
64   int i;
65 
66   for (i = 0; i < 13; i++)
67     gprs[i] = 1;
68   gprs[1] = _Unwind_GetCFA (context);
69   for (; i < 32; i++)
70     gprs[i] = _Unwind_GetGR (context, i);
71   cr = _Unwind_GetGR (context, R_CR2);
72 
73   /* For each supported Libc, we have to track the code flow
74      all the way back into the kernel.
75 
76      This code is believed to support all released Libc/Libsystem builds since
77      Jaguar 6C115, including all the security updates.  To be precise,
78 
79      Libc	Libsystem	Build(s)
80      262~1	60~37		6C115
81      262~1	60.2~4		6D52
82      262~1	61~3		6F21-6F22
83      262~1	63~24		6G30-6G37
84      262~1	63~32		6I34-6I35
85      262~1	63~64		6L29-6L60
86      262.4.1~1	63~84		6L123-6R172
87 
88      320~1	71~101		7B85-7D28
89      320~1	71~266		7F54-7F56
90      320~1	71~288		7F112
91      320~1	71~289		7F113
92      320.1.3~1	71.1.1~29	7H60-7H105
93      320.1.3~1	71.1.1~30	7H110-7H113
94      320.1.3~1	71.1.1~31	7H114
95 
96      That's a big table!  It would be insane to try to keep track of
97      every little detail, so we just read the code itself and do what
98      it would do.
99   */
100 
101   for (;;)
102     {
103       uint32_t ins = *pc++;
104 
105       if ((ins & 0xFC000003) == 0x48000000)  /* b instruction */
106 	{
107 	  pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4;
108 	  continue;
109 	}
110       if ((ins & 0xFC600000) == 0x2C000000)  /* cmpwi */
111 	{
112 	  int32_t val1 = (int16_t) ins;
113 	  int32_t val2 = gprs[ins >> 16 & 0x1F];
114 	  /* Only beq and bne instructions are supported, so we only
115 	     need to set the EQ bit.  */
116 	  uint32_t mask = 0xF << ((ins >> 21 & 0x1C) ^ 0x1C);
117 	  if (val1 == val2)
118 	    cr |= mask;
119 	  else
120 	    cr &= ~mask;
121 	  continue;
122 	}
123       if ((ins & 0xFEC38003) == 0x40820000)  /* forwards beq/bne */
124 	{
125 	  if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1))
126 	    pc += (ins & 0x7FFC) / 4 - 1;
127 	  continue;
128 	}
129       if ((ins & 0xFC0007FF) == 0x7C000378) /* or, including mr */
130 	{
131 	  gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F]
132 				     | gprs [ins >> 21 & 0x1F]);
133 	  continue;
134 	}
135       if (ins >> 26 == 0x0E)  /* addi, including li */
136 	{
137 	  reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
138 	  gprs [ins >> 21 & 0x1F] = src + (int16_t) ins;
139 	  continue;
140 	}
141       if (ins >> 26 == 0x0F)  /* addis, including lis */
142 	{
143 	  reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
144 	  gprs [ins >> 21 & 0x1F] = src + ((int16_t) ins << 16);
145 	  continue;
146 	}
147       if (ins >> 26 == 0x20)  /* lwz */
148 	{
149 	  reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
150 	  uint32_t *p = (uint32_t *)(src + (int16_t) ins);
151 	  if (p == invalid_address)
152 	    return false;
153 	  gprs [ins >> 21 & 0x1F] = *p;
154 	  continue;
155 	}
156       if (ins >> 26 == 0x21)  /* lwzu */
157 	{
158 	  uint32_t *p = (uint32_t *)(gprs [ins >> 16 & 0x1F] += (int16_t) ins);
159 	  if (p == invalid_address)
160 	    return false;
161 	  gprs [ins >> 21 & 0x1F] = *p;
162 	  continue;
163 	}
164       if (ins >> 26 == 0x24)  /* stw */
165 	/* What we hope this is doing is '--in_sigtramp'.  We don't want
166 	   to actually store to memory, so just make a note of the
167 	   address and refuse to load from it.  */
168 	{
169 	  reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
170 	  uint32_t *p = (uint32_t *)(src + (int16_t) ins);
171 	  if (p == NULL || invalid_address != NULL)
172 	    return false;
173 	  invalid_address = p;
174 	  continue;
175 	}
176       if (ins >> 26 == 0x2E) /* lmw */
177 	{
178 	  reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
179 	  uint32_t *p = (uint32_t *)(src + (int16_t) ins);
180 	  int i;
181 
182 	  for (i = (ins >> 21 & 0x1F); i < 32; i++)
183 	    {
184 	      if (p == invalid_address)
185 		return false;
186 	      gprs[i] = *p++;
187 	    }
188 	  continue;
189 	}
190       if ((ins & 0xFC1FFFFF) == 0x7c0803a6)  /* mtlr */
191 	{
192 	  lr = gprs [ins >> 21 & 0x1F];
193 	  continue;
194 	}
195       if ((ins & 0xFC1FFFFF) == 0x7c0802a6)  /* mflr */
196 	{
197 	  gprs [ins >> 21 & 0x1F] = lr;
198 	  continue;
199 	}
200       if ((ins & 0xFC1FFFFF) == 0x7c0903a6)  /* mtctr */
201 	{
202 	  ctr = gprs [ins >> 21 & 0x1F];
203 	  continue;
204 	}
205       /* The PowerPC User's Manual says that bit 11 of the mtcrf
206 	 instruction is reserved and should be set to zero, but it
207 	 looks like the Darwin assembler doesn't do that... */
208       if ((ins & 0xFC000FFF) == 0x7c000120) /* mtcrf */
209 	{
210 	  int i;
211 	  uint32_t mask = 0;
212 	  for (i = 0; i < 8; i++)
213 	    mask |= ((-(ins >> (12 + i) & 1)) & 0xF) << 4 * i;
214 	  cr = (cr & ~mask) | (gprs [ins >> 21 & 0x1F] & mask);
215 	  continue;
216 	}
217       if (ins == 0x429f0005)  /* bcl- 20,4*cr7+so,.+4, loads pc into LR */
218 	{
219 	  lr = (reg_unit) pc;
220 	  continue;
221 	}
222       if (ins == 0x4e800420) /* bctr */
223 	{
224 	  pc = (uint32_t *) ctr;
225 	  continue;
226 	}
227       if (ins == 0x44000002) /* sc */
228 	return true;
229 
230       return false;
231     }
232 }
233 
234 /* We used to include <ucontext.h> and <mach/thread_status.h>,
235    but they change so much between different Darwin system versions
236    that it's much easier to just write the structures involved here
237    directly.  */
238 
239 /* These defines are from the kernel's bsd/dev/ppc/unix_signal.c.  */
240 #define UC_TRAD                 1
241 #define UC_TRAD_VEC             6
242 #define UC_TRAD64               20
243 #define UC_TRAD64_VEC           25
244 #define UC_FLAVOR               30
245 #define UC_FLAVOR_VEC           35
246 #define UC_FLAVOR64             40
247 #define UC_FLAVOR64_VEC         45
248 #define UC_DUAL                 50
249 #define UC_DUAL_VEC             55
250 
251 struct gcc_ucontext
252 {
253   int onstack;
254   sigset_t sigmask;
255   void * stack_sp;
256   size_t stack_sz;
257   int stack_flags;
258   struct gcc_ucontext *link;
259   size_t mcsize;
260   struct gcc_mcontext32 *mcontext;
261 };
262 
263 struct gcc_float_vector_state
264 {
265   double fpregs[32];
266   uint32_t fpscr_pad;
267   uint32_t fpscr;
268   uint32_t save_vr[32][4];
269   uint32_t save_vscr[4];
270 };
271 
272 struct gcc_mcontext32 {
273   uint32_t dar;
274   uint32_t dsisr;
275   uint32_t exception;
276   uint32_t padding1[5];
277   uint32_t srr0;
278   uint32_t srr1;
279   uint32_t gpr[32];
280   uint32_t cr;
281   uint32_t xer;
282   uint32_t lr;
283   uint32_t ctr;
284   uint32_t mq;
285   uint32_t vrsave;
286   struct gcc_float_vector_state fvs;
287 };
288 
289 /* These are based on /usr/include/ppc/ucontext.h and
290    /usr/include/mach/ppc/thread_status.h, but rewritten to be more
291    convenient, to compile on Jaguar, and to work around Radar 3712064
292    on Panther, which is that the 'es' field of 'struct mcontext64' has
293    the wrong type (doh!).  */
294 
295 struct gcc_mcontext64 {
296   uint64_t dar;
297   uint32_t dsisr;
298   uint32_t exception;
299   uint32_t padding1[4];
300   uint64_t srr0;
301   uint64_t srr1;
302   uint32_t gpr[32][2];
303   uint32_t cr;
304   uint32_t xer[2];  /* These are arrays because the original structure has them misaligned.  */
305   uint32_t lr[2];
306   uint32_t ctr[2];
307   uint32_t vrsave;
308   struct gcc_float_vector_state fvs;
309 };
310 
311 #define UC_FLAVOR_SIZE \
312   (sizeof (struct gcc_mcontext32) - 33*16)
313 
314 #define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32))
315 
316 #define UC_FLAVOR64_SIZE \
317   (sizeof (struct gcc_mcontext64) - 33*16)
318 
319 #define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64))
320 
321 /* Given GPRS as input to a 'sc' instruction, and OLD_CFA, update FS
322    to represent the execution of a signal return; or, if not a signal
323    return, return false.  */
324 
325 static bool
handle_syscall(_Unwind_FrameState * fs,const reg_unit gprs[32],_Unwind_Ptr old_cfa)326 handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32],
327 		_Unwind_Ptr old_cfa)
328 {
329   struct gcc_ucontext *uctx;
330   bool is_64, is_vector;
331   struct gcc_float_vector_state * float_vector_state;
332   _Unwind_Ptr new_cfa;
333   int i;
334   static _Unwind_Ptr return_addr;
335 
336   /* Yay!  We're in a Libc that we understand, and it's made a
337      system call.  In Jaguar, this is a direct system call with value 103;
338      in Panther and Tiger it is a SYS_syscall call for system call number 184,
339      and in Leopard it is a direct syscall with number 184.  */
340 
341   if (gprs[0] == 0x67 /* SYS_SIGRETURN */)
342     {
343       uctx = (struct gcc_ucontext *) gprs[3];
344       is_vector = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
345 		   || uctx->mcsize == UC_FLAVOR_VEC_SIZE);
346       is_64 = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
347 	       || uctx->mcsize == UC_FLAVOR64_SIZE);
348     }
349   else if (gprs[0] == 0 /* SYS_syscall */ && gprs[3] == 184)
350     {
351       int ctxstyle = gprs[5];
352       uctx = (struct gcc_ucontext *) gprs[4];
353       is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
354 		   || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
355       is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
356 	       || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
357     }
358   else if (gprs[0] == 184 /* SYS_sigreturn */)
359     {
360       int ctxstyle = gprs[4];
361       uctx = (struct gcc_ucontext *) gprs[3];
362       is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
363 		   || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
364       is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
365 	       || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
366     }
367   else
368     return false;
369 
370 #define set_offset(r, addr)					\
371   (fs->regs.reg[r].how = REG_SAVED_OFFSET,			\
372    fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa)
373 
374   /* Restore even the registers that are not call-saved, since they
375      might be being used in the prologue to save other registers,
376      for instance GPR0 is sometimes used to save LR.  */
377 
378   /* Handle the GPRs, and produce the information needed to do the rest.  */
379   if (is_64)
380     {
381       /* The context is 64-bit, but it doesn't carry any extra information
382 	 for us because only the low 32 bits of the registers are
383 	 call-saved.  */
384       struct gcc_mcontext64 *m64 = (struct gcc_mcontext64 *)uctx->mcontext;
385       int i;
386 
387       float_vector_state = &m64->fvs;
388 
389       new_cfa = m64->gpr[1][1];
390 
391       set_offset (R_CR2, &m64->cr);
392       for (i = 0; i < 32; i++)
393 	set_offset (i, m64->gpr[i] + 1);
394       set_offset (R_XER, m64->xer + 1);
395       set_offset (R_LR, m64->lr + 1);
396       set_offset (R_CTR, m64->ctr + 1);
397       if (is_vector)
398 	set_offset (R_VRSAVE, &m64->vrsave);
399 
400       /* Sometimes, srr0 points to the instruction that caused the exception,
401 	 and sometimes to the next instruction to be executed; we want
402 	 the latter.  */
403       if (m64->exception == 3 || m64->exception == 4
404 	  || m64->exception == 6
405 	  || (m64->exception == 7 && !(m64->srr1 & 0x10000)))
406 	return_addr = m64->srr0 + 4;
407       else
408 	return_addr = m64->srr0;
409     }
410   else
411     {
412       struct gcc_mcontext32 *m = uctx->mcontext;
413       int i;
414 
415       float_vector_state = &m->fvs;
416 
417       new_cfa = m->gpr[1];
418 
419       set_offset (R_CR2, &m->cr);
420       for (i = 0; i < 32; i++)
421 	set_offset (i, m->gpr + i);
422       set_offset (R_XER, &m->xer);
423       set_offset (R_LR, &m->lr);
424       set_offset (R_CTR, &m->ctr);
425 
426       if (is_vector)
427 	set_offset (R_VRSAVE, &m->vrsave);
428 
429       /* Sometimes, srr0 points to the instruction that caused the exception,
430 	 and sometimes to the next instruction to be executed; we want
431 	 the latter.  */
432       if (m->exception == 3 || m->exception == 4
433 	  || m->exception == 6
434 	  || (m->exception == 7 && !(m->srr1 & 0x10000)))
435 	return_addr = m->srr0 + 4;
436       else
437 	return_addr = m->srr0;
438     }
439 
440   fs->regs.cfa_how = CFA_REG_OFFSET;
441   fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
442   fs->regs.cfa_offset = new_cfa - old_cfa;;
443 
444   /* The choice of column for the return address is somewhat tricky.
445      Fortunately, the actual choice is private to this file, and
446      the space it's reserved from is the GCC register space, not the
447      DWARF2 numbering.  So any free element of the right size is an OK
448      choice.  Thus: */
449   fs->retaddr_column = ARG_POINTER_REGNUM;
450   /* FIXME: this should really be done using a DWARF2 location expression,
451      not using a static variable.  In fact, this entire file should
452      be implemented in DWARF2 expressions.  */
453   set_offset (ARG_POINTER_REGNUM, &return_addr);
454 
455   for (i = 0; i < 32; i++)
456     set_offset (32 + i, float_vector_state->fpregs + i);
457   set_offset (R_SPEFSCR, &float_vector_state->fpscr);
458 
459   if (is_vector)
460     {
461       for (i = 0; i < 32; i++)
462 	set_offset (R_VR0 + i, float_vector_state->save_vr + i);
463       set_offset (R_VSCR, float_vector_state->save_vscr);
464     }
465 
466   return true;
467 }
468 
469 /* This is also prototyped in rs6000/darwin.h, inside the
470    MD_FALLBACK_FRAME_STATE_FOR macro.  */
471 extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
472 					      _Unwind_FrameState *fs);
473 
474 /* Implement the MD_FALLBACK_FRAME_STATE_FOR macro,
475    returning true iff the frame was a sigreturn() frame that we
476    can understand.  */
477 
478 bool
_Unwind_fallback_frame_state_for(struct _Unwind_Context * context,_Unwind_FrameState * fs)479 _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
480 				  _Unwind_FrameState *fs)
481 {
482   reg_unit gprs[32];
483 
484   if (!interpret_libc (gprs, context))
485     return false;
486   return handle_syscall (fs, gprs, _Unwind_GetCFA (context));
487 }
488 #endif
489