Home | History | Annotate | Line # | Download | only in rs6000
darwin-fallback.c revision 1.1.1.5
      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
     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
    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
    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