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