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