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