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