Home | History | Annotate | Line # | Download | only in xtensa
unwind-dw2-xtensa.c revision 1.1.1.1
      1 /* DWARF2 exception handling and frame unwinding for Xtensa.
      2    Copyright (C) 1997-2013 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 #include "tconfig.h"
     26 #include "tsystem.h"
     27 #include "coretypes.h"
     28 #include "tm.h"
     29 #include "libgcc_tm.h"
     30 #include "dwarf2.h"
     31 #include "unwind.h"
     32 #ifdef __USING_SJLJ_EXCEPTIONS__
     33 # define NO_SIZE_OF_ENCODED_VALUE
     34 #endif
     35 #include "unwind-pe.h"
     36 #include "unwind-dw2-fde.h"
     37 #include "unwind-dw2-xtensa.h"
     38 
     39 #ifndef __USING_SJLJ_EXCEPTIONS__
     40 
     41 /* The standard CIE and FDE structures work fine for Xtensa but the
     42    variable-size register window save areas are not a good fit for the rest
     43    of the standard DWARF unwinding mechanism.  Nor is that mechanism
     44    necessary, since the register save areas are always in fixed locations
     45    in each stack frame.  This file is a stripped down and customized version
     46    of the standard DWARF unwinding code.  It needs to be customized to have
     47    builtin logic for finding the save areas and also to track the stack
     48    pointer value (besides the CFA) while unwinding since the primary save
     49    area is located below the stack pointer.  It is stripped down to reduce
     50    code size and ease the maintenance burden of tracking changes in the
     51    standard version of the code.  */
     52 
     53 #ifndef DWARF_REG_TO_UNWIND_COLUMN
     54 #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
     55 #endif
     56 
     57 #define XTENSA_RA_FIELD_MASK 0x3FFFFFFF
     58 
     59 /* This is the register and unwind state for a particular frame.  This
     60    provides the information necessary to unwind up past a frame and return
     61    to its caller.  */
     62 struct _Unwind_Context
     63 {
     64   /* Track register window save areas of 4 registers each, instead of
     65      keeping separate addresses for the individual registers.  */
     66   _Unwind_Word *reg[4];
     67 
     68   void *cfa;
     69   void *sp;
     70   void *ra;
     71 
     72   /* Cache the 2 high bits to replace the window size in return addresses.  */
     73   _Unwind_Word ra_high_bits;
     74 
     75   void *lsda;
     76   struct dwarf_eh_bases bases;
     77   /* Signal frame context.  */
     78 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
     79   _Unwind_Word flags;
     80   /* 0 for now, can be increased when further fields are added to
     81      struct _Unwind_Context.  */
     82   _Unwind_Word version;
     83 };
     84 
     85 
     86 /* Read unaligned data from the instruction buffer.  */
     88 
     89 union unaligned
     90 {
     91   void *p;
     92 } __attribute__ ((packed));
     93 
     94 static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
     95 static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
     96 					       _Unwind_FrameState *);
     97 
     98 static inline void *
     99 read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
    100 
    101 static inline _Unwind_Word
    103 _Unwind_IsSignalFrame (struct _Unwind_Context *context)
    104 {
    105   return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
    106 }
    107 
    108 static inline void
    109 _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
    110 {
    111   if (val)
    112     context->flags |= SIGNAL_FRAME_BIT;
    113   else
    114     context->flags &= ~SIGNAL_FRAME_BIT;
    115 }
    116 
    117 /* Get the value of register INDEX as saved in CONTEXT.  */
    119 
    120 inline _Unwind_Word
    121 _Unwind_GetGR (struct _Unwind_Context *context, int index)
    122 {
    123   _Unwind_Word *ptr;
    124 
    125   index = DWARF_REG_TO_UNWIND_COLUMN (index);
    126   ptr = context->reg[index >> 2] + (index & 3);
    127 
    128   return *ptr;
    129 }
    130 
    131 /* Get the value of the CFA as saved in CONTEXT.  */
    132 
    133 _Unwind_Word
    134 _Unwind_GetCFA (struct _Unwind_Context *context)
    135 {
    136   return (_Unwind_Ptr) context->cfa;
    137 }
    138 
    139 /* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
    140 
    141 inline void
    142 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
    143 {
    144   _Unwind_Word *ptr;
    145 
    146   index = DWARF_REG_TO_UNWIND_COLUMN (index);
    147   ptr = context->reg[index >> 2] + (index & 3);
    148 
    149   *ptr = val;
    150 }
    151 
    152 /* Retrieve the return address for CONTEXT.  */
    153 
    154 inline _Unwind_Ptr
    155 _Unwind_GetIP (struct _Unwind_Context *context)
    156 {
    157   return (_Unwind_Ptr) context->ra;
    158 }
    159 
    160 /* Retrieve the return address and flag whether that IP is before
    161    or after first not yet fully executed instruction.  */
    162 
    163 inline _Unwind_Ptr
    164 _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
    165 {
    166   *ip_before_insn = _Unwind_IsSignalFrame (context);
    167   return (_Unwind_Ptr) context->ra;
    168 }
    169 
    170 /* Overwrite the return address for CONTEXT with VAL.  */
    171 
    172 inline void
    173 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
    174 {
    175   context->ra = (void *) val;
    176 }
    177 
    178 _Unwind_Ptr
    179 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
    180 {
    181   return context->lsda;
    182 }
    183 
    184 _Unwind_Ptr
    185 _Unwind_GetRegionStart (struct _Unwind_Context *context)
    186 {
    187   return (_Unwind_Ptr) context->bases.func;
    188 }
    189 
    190 void *
    191 _Unwind_FindEnclosingFunction (void *pc)
    192 {
    193   struct dwarf_eh_bases bases;
    194   const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
    195   if (fde)
    196     return bases.func;
    197   else
    198     return NULL;
    199 }
    200 
    201 _Unwind_Ptr
    202 _Unwind_GetDataRelBase (struct _Unwind_Context *context)
    203 {
    204   return (_Unwind_Ptr) context->bases.dbase;
    205 }
    206 
    207 _Unwind_Ptr
    208 _Unwind_GetTextRelBase (struct _Unwind_Context *context)
    209 {
    210   return (_Unwind_Ptr) context->bases.tbase;
    211 }
    212 
    213 #include "md-unwind-support.h"
    214 
    215 /* Extract any interesting information from the CIE for the translation
    217    unit F belongs to.  Return a pointer to the byte after the augmentation,
    218    or NULL if we encountered an undecipherable augmentation.  */
    219 
    220 static const unsigned char *
    221 extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
    222 		  _Unwind_FrameState *fs)
    223 {
    224   const unsigned char *aug = cie->augmentation;
    225   const unsigned char *p = aug + strlen ((const char *)aug) + 1;
    226   const unsigned char *ret = NULL;
    227   _uleb128_t utmp;
    228   _sleb128_t stmp;
    229 
    230   /* g++ v2 "eh" has pointer immediately following augmentation string,
    231      so it must be handled first.  */
    232   if (aug[0] == 'e' && aug[1] == 'h')
    233     {
    234       fs->eh_ptr = read_pointer (p);
    235       p += sizeof (void *);
    236       aug += 2;
    237     }
    238 
    239   /* Immediately following the augmentation are the code and
    240      data alignment and return address column.  */
    241   p = read_uleb128 (p, &utmp);
    242   p = read_sleb128 (p, &stmp);
    243   if (cie->version == 1)
    244     fs->retaddr_column = *p++;
    245   else
    246     {
    247       p = read_uleb128 (p, &utmp);
    248       fs->retaddr_column = (_Unwind_Word)utmp;
    249     }
    250   fs->lsda_encoding = DW_EH_PE_omit;
    251 
    252   /* If the augmentation starts with 'z', then a uleb128 immediately
    253      follows containing the length of the augmentation field following
    254      the size.  */
    255   if (*aug == 'z')
    256     {
    257       p = read_uleb128 (p, &utmp);
    258       ret = p + utmp;
    259 
    260       fs->saw_z = 1;
    261       ++aug;
    262     }
    263 
    264   /* Iterate over recognized augmentation subsequences.  */
    265   while (*aug != '\0')
    266     {
    267       /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
    268       if (aug[0] == 'L')
    269 	{
    270 	  fs->lsda_encoding = *p++;
    271 	  aug += 1;
    272 	}
    273 
    274       /* "R" indicates a byte indicating how FDE addresses are encoded.  */
    275       else if (aug[0] == 'R')
    276 	{
    277 	  fs->fde_encoding = *p++;
    278 	  aug += 1;
    279 	}
    280 
    281       /* "P" indicates a personality routine in the CIE augmentation.  */
    282       else if (aug[0] == 'P')
    283 	{
    284 	  _Unwind_Ptr personality;
    285 
    286 	  p = read_encoded_value (context, *p, p + 1, &personality);
    287 	  fs->personality = (_Unwind_Personality_Fn) personality;
    288 	  aug += 1;
    289 	}
    290 
    291       /* "S" indicates a signal frame.  */
    292       else if (aug[0] == 'S')
    293 	{
    294 	  fs->signal_frame = 1;
    295 	  aug += 1;
    296 	}
    297 
    298       /* Otherwise we have an unknown augmentation string.
    299 	 Bail unless we saw a 'z' prefix.  */
    300       else
    301 	return ret;
    302     }
    303 
    304   return ret ? ret : p;
    305 }
    306 
    307 /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
    309    its caller and decode it into FS.  This function also sets the
    310    lsda member of CONTEXT, as it is really information
    311    about the caller's frame.  */
    312 
    313 static _Unwind_Reason_Code
    314 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
    315 {
    316   const struct dwarf_fde *fde;
    317   const struct dwarf_cie *cie;
    318   const unsigned char *aug;
    319   int window_size;
    320   _Unwind_Word *ra_ptr;
    321 
    322   memset (fs, 0, sizeof (*fs));
    323   context->lsda = 0;
    324 
    325   fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
    326 			  &context->bases);
    327   if (fde == NULL)
    328     {
    329 #ifdef MD_FALLBACK_FRAME_STATE_FOR
    330       _Unwind_Reason_Code reason;
    331       /* Couldn't find frame unwind info for this function.  Try a
    332 	 target-specific fallback mechanism.  This will necessarily
    333 	 not provide a personality routine or LSDA.  */
    334       reason = MD_FALLBACK_FRAME_STATE_FOR (context, fs);
    335       if (reason != _URC_END_OF_STACK)
    336 	return reason;
    337 #endif
    338       /* The frame was not recognized and handled by the fallback function,
    339 	 but it is not really the end of the stack.  Fall through here and
    340 	 unwind it anyway.  */
    341     }
    342   else
    343     {
    344       cie = get_cie (fde);
    345       if (extract_cie_info (cie, context, fs) == NULL)
    346 	/* CIE contained unknown augmentation.  */
    347 	return _URC_FATAL_PHASE1_ERROR;
    348 
    349       /* Locate augmentation for the fde.  */
    350       aug = (const unsigned char *) fde + sizeof (*fde);
    351       aug += 2 * size_of_encoded_value (fs->fde_encoding);
    352       if (fs->saw_z)
    353 	{
    354 	  _uleb128_t i;
    355 	  aug = read_uleb128 (aug, &i);
    356 	}
    357       if (fs->lsda_encoding != DW_EH_PE_omit)
    358 	{
    359 	  _Unwind_Ptr lsda;
    360 
    361 	  aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
    362 	  context->lsda = (void *) lsda;
    363 	}
    364     }
    365 
    366   /* Check for the end of the stack.  This needs to be checked after
    367      the MD_FALLBACK_FRAME_STATE_FOR check for signal frames because
    368      the contents of context->reg[0] are undefined at a signal frame,
    369      and register a0 may appear to be zero.  (The return address in
    370      context->ra comes from register a4 or a8).  */
    371   ra_ptr = context->reg[0];
    372   if (ra_ptr && *ra_ptr == 0)
    373     return _URC_END_OF_STACK;
    374 
    375   /* Find the window size from the high bits of the return address.  */
    376   if (ra_ptr)
    377     window_size = (*ra_ptr >> 30) * 4;
    378   else
    379     window_size = 8;
    380 
    381   fs->retaddr_column = window_size;
    382 
    383   return _URC_NO_REASON;
    384 }
    385 
    386 static void
    388 uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
    389 {
    390   struct _Unwind_Context orig_context = *context;
    391   _Unwind_Word *sp, *cfa, *next_cfa;
    392   int i;
    393 
    394   if (fs->signal_regs)
    395     {
    396       cfa = (_Unwind_Word *) fs->signal_regs[1];
    397       next_cfa = (_Unwind_Word *) cfa[-3];
    398 
    399       for (i = 0; i < 4; i++)
    400 	context->reg[i] = fs->signal_regs + (i << 2);
    401     }
    402   else
    403     {
    404       int window_size = fs->retaddr_column >> 2;
    405 
    406       sp = (_Unwind_Word *) orig_context.sp;
    407       cfa = (_Unwind_Word *) orig_context.cfa;
    408       next_cfa = (_Unwind_Word *) cfa[-3];
    409 
    410       /* Registers a0-a3 are in the save area below sp.  */
    411       context->reg[0] = sp - 4;
    412 
    413       /* Find the extra save area below next_cfa.  */
    414       for (i = 1; i < window_size; i++)
    415 	context->reg[i] = next_cfa - 4 * (1 + window_size - i);
    416 
    417       /* Remaining registers rotate from previous save areas.  */
    418       for (i = window_size; i < 4; i++)
    419 	context->reg[i] = orig_context.reg[i - window_size];
    420     }
    421 
    422   context->sp = cfa;
    423   context->cfa = next_cfa;
    424 
    425   _Unwind_SetSignalFrame (context, fs->signal_frame);
    426 }
    427 
    428 /* CONTEXT describes the unwind state for a frame, and FS describes the FDE
    429    of its caller.  Update CONTEXT to refer to the caller as well.  Note
    430    that the lsda member is not updated here, but later in
    431    uw_frame_state_for.  */
    432 
    433 static void
    434 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
    435 {
    436   uw_update_context_1 (context, fs);
    437 
    438   /* Compute the return address now, since the return address column
    439      can change from frame to frame.  */
    440   if (fs->signal_ra != 0)
    441     context->ra = (void *) fs->signal_ra;
    442   else
    443     context->ra = (void *) ((_Unwind_GetGR (context, fs->retaddr_column)
    444 			     & XTENSA_RA_FIELD_MASK) | context->ra_high_bits);
    445 }
    446 
    447 static void
    448 uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
    449 {
    450   uw_update_context (context, fs);
    451 }
    452 
    453 /* Fill in CONTEXT for top-of-stack.  The only valid registers at this
    455    level will be the return address and the CFA.  */
    456 
    457 #define uw_init_context(CONTEXT)					   \
    458   do									   \
    459     {									   \
    460       __builtin_unwind_init ();						   \
    461       uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \
    462 			 __builtin_return_address (0));			   \
    463     }									   \
    464   while (0)
    465 
    466 static void __attribute__((noinline))
    467 uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa,
    468 		   void *outer_ra)
    469 {
    470   void *ra = __builtin_return_address (0);
    471   void *cfa = __builtin_dwarf_cfa ();
    472   _Unwind_FrameState fs;
    473 
    474   memset (context, 0, sizeof (struct _Unwind_Context));
    475   context->ra = ra;
    476 
    477   memset (&fs, 0, sizeof (fs));
    478   fs.retaddr_column = 8;
    479   context->sp = cfa;
    480   context->cfa = outer_cfa;
    481   context->ra_high_bits =
    482     ((_Unwind_Word) uw_init_context_1) & ~XTENSA_RA_FIELD_MASK;
    483   uw_update_context_1 (context, &fs);
    484 
    485   context->ra = outer_ra;
    486 }
    487 
    488 
    489 /* Install TARGET into CURRENT so that we can return to it.  This is a
    490    macro because __builtin_eh_return must be invoked in the context of
    491    our caller.  */
    492 
    493 #define uw_install_context(CURRENT, TARGET)				 \
    494   do									 \
    495     {									 \
    496       long offset = uw_install_context_1 ((CURRENT), (TARGET));		 \
    497       void *handler = __builtin_frob_return_addr ((TARGET)->ra);	 \
    498       __builtin_eh_return (offset, handler);				 \
    499     }									 \
    500   while (0)
    501 
    502 static long
    503 uw_install_context_1 (struct _Unwind_Context *current,
    504 		      struct _Unwind_Context *target)
    505 {
    506   long i;
    507 
    508   /* The eh_return insn assumes a window size of 8, so don't bother copying
    509      the save areas for registers a8-a15 since they won't be reloaded.  */
    510   for (i = 0; i < 2; ++i)
    511     {
    512       void *c = current->reg[i];
    513       void *t = target->reg[i];
    514 
    515       if (t && c && t != c)
    516 	memcpy (c, t, 4 * sizeof (_Unwind_Word));
    517     }
    518 
    519   return 0;
    520 }
    521 
    522 static inline _Unwind_Ptr
    523 uw_identify_context (struct _Unwind_Context *context)
    524 {
    525   return _Unwind_GetCFA (context);
    526 }
    527 
    528 
    529 #include "unwind.inc"
    530 
    531 #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
    532 alias (_Unwind_Backtrace);
    533 alias (_Unwind_DeleteException);
    534 alias (_Unwind_FindEnclosingFunction);
    535 alias (_Unwind_ForcedUnwind);
    536 alias (_Unwind_GetDataRelBase);
    537 alias (_Unwind_GetTextRelBase);
    538 alias (_Unwind_GetCFA);
    539 alias (_Unwind_GetGR);
    540 alias (_Unwind_GetIP);
    541 alias (_Unwind_GetLanguageSpecificData);
    542 alias (_Unwind_GetRegionStart);
    543 alias (_Unwind_RaiseException);
    544 alias (_Unwind_Resume);
    545 alias (_Unwind_Resume_or_Rethrow);
    546 alias (_Unwind_SetGR);
    547 alias (_Unwind_SetIP);
    548 #endif
    549 
    550 #endif /* !USING_SJLJ_EXCEPTIONS */
    551