(root)/
gcc-13.2.0/
libgcc/
config/
arm/
unwind-arm.c
       1  /* ARM EABI compliant unwinding routines.
       2     Copyright (C) 2004-2023 Free Software Foundation, Inc.
       3     Contributed by Paul Brook
       4  
       5     This file is free software; you can redistribute it and/or modify it
       6     under the terms of the GNU General Public License as published by the
       7     Free Software Foundation; either version 3, or (at your option) any
       8     later version.
       9  
      10     This file is distributed in the hope that it will be useful, but
      11     WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     General Public License for more details.
      14  
      15     Under Section 7 of GPL version 3, you are granted additional
      16     permissions described in the GCC Runtime Library Exception, version
      17     3.1, as published by the Free Software Foundation.
      18  
      19     You should have received a copy of the GNU General Public License and
      20     a copy of the GCC Runtime Library Exception along with this program;
      21     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      22     <http://www.gnu.org/licenses/>.  */
      23  
      24  #pragma GCC target ("general-regs-only")
      25  #include "unwind.h"
      26  
      27  /* Misc constants.  */
      28  #define R_IP	12
      29  #define R_SP	13
      30  #define R_LR	14
      31  #define R_PC	15
      32  
      33  #define VRS_PC(vrs) ((vrs)->core.r[R_PC])
      34  #define VRS_SP(vrs) ((vrs)->core.r[R_SP])
      35  #define VRS_RETURN(vrs) ((vrs)->core.r[R_LR])
      36  
      37  struct core_regs
      38  {
      39    _uw r[16];
      40  };
      41  
      42  /* We use normal integer types here to avoid the compiler generating
      43     coprocessor instructions.  */
      44  struct vfp_regs
      45  {
      46    _uw64 d[16];
      47    _uw pad;
      48  };
      49  
      50  struct vfpv3_regs
      51  {
      52    /* Always populated via VSTM, so no need for the "pad" field from
      53       vfp_regs (which is used to store the format word for FSTMX).  */
      54    _uw64 d[16];
      55  };
      56  
      57  struct wmmxd_regs
      58  {
      59    _uw64 wd[16];
      60  };
      61  
      62  struct wmmxc_regs
      63  {
      64    _uw wc[4];
      65  };
      66  
      67  /*  Holds value of pseudo registers eg. PAC.  */
      68  struct pseudo_regs
      69  {
      70    _uw pac;
      71  };
      72  
      73  /* The ABI specifies that the unwind routines may only use core registers,
      74     except when actually manipulating coprocessor state.  This allows
      75     us to write one implementation that works on all platforms by
      76     demand-saving coprocessor registers.
      77  
      78     During unwinding we hold the coprocessor state in the actual hardware
      79     registers and allocate demand-save areas for use during phase1
      80     unwinding.  */
      81  
      82  typedef struct
      83  {
      84    /* The first fields must be the same as a phase2_vrs.  */
      85    _uw demand_save_flags;
      86    struct core_regs core;
      87    /* Armv8.1-M Mainline PAC/AUTH values.  This field should be in the same field
      88       order as phase2_vrs.  */
      89    struct pseudo_regs pseudo;
      90    _uw prev_sp; /* Only valid during forced unwinding.  */
      91    struct vfp_regs vfp;
      92    struct vfpv3_regs vfp_regs_16_to_31;
      93    struct wmmxd_regs wmmxd;
      94    struct wmmxc_regs wmmxc;
      95  } phase1_vrs;
      96  
      97  #define DEMAND_SAVE_VFP 1	/* VFP state has been saved if not set */
      98  #define DEMAND_SAVE_VFP_D 2	/* VFP state is for FLDMD/FSTMD if set */
      99  #define DEMAND_SAVE_VFP_V3 4    /* VFPv3 state for regs 16 .. 31 has
     100                                     been saved if not set */
     101  #define DEMAND_SAVE_WMMXD 8	/* iWMMXt data registers have been
     102  				   saved if not set.  */
     103  #define DEMAND_SAVE_WMMXC 16	/* iWMMXt control registers have been
     104  				   saved if not set.  */
     105  
     106  /* This must match the structure created by the assembly wrappers.  */
     107  typedef struct
     108  {
     109    _uw demand_save_flags;
     110    struct core_regs core;
     111    struct pseudo_regs pac;
     112  } phase2_vrs;
     113  
     114  /* Coprocessor register state manipulation functions.  */
     115  
     116  /* Routines for FLDMX/FSTMX format...  */
     117  void __gnu_Unwind_Save_VFP (struct vfp_regs * p);
     118  void __gnu_Unwind_Restore_VFP (struct vfp_regs * p);
     119  void __gnu_Unwind_Save_WMMXD (struct wmmxd_regs * p);
     120  void __gnu_Unwind_Restore_WMMXD (struct wmmxd_regs * p);
     121  void __gnu_Unwind_Save_WMMXC (struct wmmxc_regs * p);
     122  void __gnu_Unwind_Restore_WMMXC (struct wmmxc_regs * p);
     123  
     124  /* ...and those for FLDMD/FSTMD format...  */
     125  void __gnu_Unwind_Save_VFP_D (struct vfp_regs * p);
     126  void __gnu_Unwind_Restore_VFP_D (struct vfp_regs * p);
     127  
     128  /* ...and those for VLDM/VSTM format, saving/restoring only registers
     129     16 through 31.  */
     130  void __gnu_Unwind_Save_VFP_D_16_to_31 (struct vfpv3_regs * p);
     131  void __gnu_Unwind_Restore_VFP_D_16_to_31 (struct vfpv3_regs * p);
     132  
     133  /* Restore coprocessor state after phase1 unwinding.  */
     134  static void
     135  restore_non_core_regs (phase1_vrs * vrs)
     136  {
     137    if ((vrs->demand_save_flags & DEMAND_SAVE_VFP) == 0)
     138      {
     139        if (vrs->demand_save_flags & DEMAND_SAVE_VFP_D)
     140          __gnu_Unwind_Restore_VFP_D (&vrs->vfp);
     141        else
     142          __gnu_Unwind_Restore_VFP (&vrs->vfp);
     143      }
     144  
     145    if ((vrs->demand_save_flags & DEMAND_SAVE_VFP_V3) == 0)
     146      __gnu_Unwind_Restore_VFP_D_16_to_31 (&vrs->vfp_regs_16_to_31);
     147  
     148    if ((vrs->demand_save_flags & DEMAND_SAVE_WMMXD) == 0)
     149      __gnu_Unwind_Restore_WMMXD (&vrs->wmmxd);
     150    if ((vrs->demand_save_flags & DEMAND_SAVE_WMMXC) == 0)
     151      __gnu_Unwind_Restore_WMMXC (&vrs->wmmxc);
     152  }
     153  
     154  #include "unwind-arm-common.inc"
     155  
     156  /* ABI defined personality routines.  */
     157  extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0 (_Unwind_State,
     158      _Unwind_Control_Block *, _Unwind_Context *);// __attribute__((weak));
     159  extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1 (_Unwind_State,
     160      _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
     161  extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2 (_Unwind_State,
     162      _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
     163  
     164  /* ABI defined routine to store a virtual register to memory.  */
     165  
     166  _Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
     167  				    _Unwind_VRS_RegClass regclass,
     168  				    _uw regno,
     169  				    _Unwind_VRS_DataRepresentation representation,
     170  				    void *valuep)
     171  {
     172    phase1_vrs *vrs = (phase1_vrs *) context;
     173  
     174    switch (regclass)
     175      {
     176      case _UVRSC_CORE:
     177        if (representation != _UVRSD_UINT32
     178  	  || regno > 15)
     179  	return _UVRSR_FAILED;
     180        *(_uw *) valuep = vrs->core.r[regno];
     181        return _UVRSR_OK;
     182  
     183      case _UVRSC_VFP:
     184      case _UVRSC_WMMXD:
     185      case _UVRSC_WMMXC:
     186        return _UVRSR_NOT_IMPLEMENTED;
     187  
     188      case _UVRSC_PAC:
     189        *(_uw *) valuep = vrs->pseudo.pac;
     190        return _UVRSR_OK;
     191  
     192      default:
     193        return _UVRSR_FAILED;
     194      }
     195  }
     196  
     197  
     198  /* ABI defined function to load a virtual register from memory.  */
     199  
     200  _Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
     201  				    _Unwind_VRS_RegClass regclass,
     202  				    _uw regno,
     203  				    _Unwind_VRS_DataRepresentation representation,
     204  				    void *valuep)
     205  {
     206    phase1_vrs *vrs = (phase1_vrs *) context;
     207  
     208    switch (regclass)
     209      {
     210      case _UVRSC_CORE:
     211        if (representation != _UVRSD_UINT32
     212  	  || regno > 15)
     213  	return _UVRSR_FAILED;
     214  
     215        vrs->core.r[regno] = *(_uw *) valuep;
     216        return _UVRSR_OK;
     217  
     218      case _UVRSC_VFP:
     219      case _UVRSC_WMMXD:
     220      case _UVRSC_WMMXC:
     221        return _UVRSR_NOT_IMPLEMENTED;
     222  
     223      case _UVRSC_PAC:
     224        vrs->pseudo.pac = *(_uw *) valuep;
     225        return _UVRSR_OK;
     226  
     227      default:
     228        return _UVRSR_FAILED;
     229      }
     230  }
     231  
     232  
     233  /* ABI defined function to pop registers off the stack.  */
     234  
     235  _Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
     236  				    _Unwind_VRS_RegClass regclass,
     237  				    _uw discriminator,
     238  				    _Unwind_VRS_DataRepresentation representation)
     239  {
     240    phase1_vrs *vrs = (phase1_vrs *) context;
     241  
     242    switch (regclass)
     243      {
     244      case _UVRSC_CORE:
     245        {
     246  	_uw *ptr;
     247  	_uw mask;
     248  	int i;
     249  
     250  	if (representation != _UVRSD_UINT32)
     251  	  return _UVRSR_FAILED;
     252  
     253  	mask = discriminator & 0xffff;
     254  	ptr = (_uw *) vrs->core.r[R_SP];
     255  	/* Pop the requested registers.  */
     256  	for (i = 0; i < 16; i++)
     257  	  {
     258  	    if (mask & (1 << i))
     259  	      vrs->core.r[i] = *(ptr++);
     260  	  }
     261  	/* Writeback the stack pointer value if it wasn't restored.  */
     262  	if ((mask & (1 << R_SP)) == 0)
     263  	  vrs->core.r[R_SP] = (_uw) ptr;
     264        }
     265        return _UVRSR_OK;
     266  
     267      case _UVRSC_PAC:
     268        {
     269  	_uw *ptr = (_uw *) vrs->core.r[R_SP];
     270  	if (discriminator != 0)
     271  	  return _UVRSR_FAILED;
     272  	vrs->pseudo.pac = *(ptr++);
     273  	vrs->core.r[R_SP] = (_uw) ptr;
     274  	return _UVRSR_OK;
     275        }
     276  
     277      case _UVRSC_VFP:
     278        {
     279  	_uw start = discriminator >> 16;
     280  	_uw count = discriminator & 0xffff;
     281  	struct vfp_regs tmp;
     282  	struct vfpv3_regs tmp_16_to_31;
     283  	int tmp_count;
     284  	_uw *sp;
     285  	_uw *dest;
     286          int num_vfpv3_regs = 0;
     287  
     288          /* We use an approximation here by bounding _UVRSD_DOUBLE
     289             register numbers at 32 always, since we can't detect if
     290             VFPv3 isn't present (in such a case the upper limit is 16).  */
     291  	if ((representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
     292              || start + count > (representation == _UVRSD_VFPX ? 16 : 32)
     293              || (representation == _UVRSD_VFPX && start >= 16))
     294  	  return _UVRSR_FAILED;
     295  
     296          /* Check if we're being asked to pop VFPv3-only registers
     297             (numbers 16 through 31).  */
     298  	if (start >= 16)
     299            num_vfpv3_regs = count;
     300          else if (start + count > 16)
     301            num_vfpv3_regs = start + count - 16;
     302  
     303          if (num_vfpv3_regs && representation != _UVRSD_DOUBLE)
     304            return _UVRSR_FAILED;
     305  
     306  	/* Demand-save coprocessor registers for stage1.  */
     307  	if (start < 16 && (vrs->demand_save_flags & DEMAND_SAVE_VFP))
     308  	  {
     309  	    vrs->demand_save_flags &= ~DEMAND_SAVE_VFP;
     310  
     311              if (representation == _UVRSD_DOUBLE)
     312                {
     313                  /* Save in FLDMD/FSTMD format.  */
     314  	        vrs->demand_save_flags |= DEMAND_SAVE_VFP_D;
     315  	        __gnu_Unwind_Save_VFP_D (&vrs->vfp);
     316                }
     317              else
     318                {
     319                  /* Save in FLDMX/FSTMX format.  */
     320  	        vrs->demand_save_flags &= ~DEMAND_SAVE_VFP_D;
     321  	        __gnu_Unwind_Save_VFP (&vrs->vfp);
     322                }
     323  	  }
     324  
     325          if (num_vfpv3_regs > 0
     326              && (vrs->demand_save_flags & DEMAND_SAVE_VFP_V3))
     327  	  {
     328  	    vrs->demand_save_flags &= ~DEMAND_SAVE_VFP_V3;
     329              __gnu_Unwind_Save_VFP_D_16_to_31 (&vrs->vfp_regs_16_to_31);
     330  	  }
     331  
     332  	/* Restore the registers from the stack.  Do this by saving the
     333  	   current VFP registers to a memory area, moving the in-memory
     334  	   values into that area, and restoring from the whole area.
     335  	   For _UVRSD_VFPX we assume FSTMX standard format 1.  */
     336          if (representation == _UVRSD_VFPX)
     337    	  __gnu_Unwind_Save_VFP (&tmp);
     338          else
     339            {
     340  	    /* Save registers 0 .. 15 if required.  */
     341              if (start < 16)
     342                __gnu_Unwind_Save_VFP_D (&tmp);
     343  
     344  	    /* Save VFPv3 registers 16 .. 31 if required.  */
     345              if (num_vfpv3_regs)
     346    	      __gnu_Unwind_Save_VFP_D_16_to_31 (&tmp_16_to_31);
     347            }
     348  
     349  	/* Work out how many registers below register 16 need popping.  */
     350  	tmp_count = num_vfpv3_regs > 0 ? 16 - start : count;
     351  
     352  	/* Copy registers below 16, if needed.
     353  	   The stack address is only guaranteed to be word aligned, so
     354  	   we can't use doubleword copies.  */
     355  	sp = (_uw *) vrs->core.r[R_SP];
     356          if (tmp_count > 0)
     357            {
     358  	    tmp_count *= 2;
     359  	    dest = (_uw *) &tmp.d[start];
     360  	    while (tmp_count--)
     361  	      *(dest++) = *(sp++);
     362            }
     363  
     364  	/* Copy VFPv3 registers numbered >= 16, if needed.  */
     365          if (num_vfpv3_regs > 0)
     366            {
     367              /* num_vfpv3_regs is needed below, so copy it.  */
     368              int tmp_count_2 = num_vfpv3_regs * 2;
     369              int vfpv3_start = start < 16 ? 16 : start;
     370  
     371  	    dest = (_uw *) &tmp_16_to_31.d[vfpv3_start - 16];
     372  	    while (tmp_count_2--)
     373  	      *(dest++) = *(sp++);
     374            }
     375  
     376  	/* Skip the format word space if using FLDMX/FSTMX format.  */
     377  	if (representation == _UVRSD_VFPX)
     378  	  sp++;
     379  
     380  	/* Set the new stack pointer.  */
     381  	vrs->core.r[R_SP] = (_uw) sp;
     382  
     383  	/* Reload the registers.  */
     384          if (representation == _UVRSD_VFPX)
     385    	  __gnu_Unwind_Restore_VFP (&tmp);
     386          else
     387            {
     388  	    /* Restore registers 0 .. 15 if required.  */
     389              if (start < 16)
     390                __gnu_Unwind_Restore_VFP_D (&tmp);
     391  
     392  	    /* Restore VFPv3 registers 16 .. 31 if required.  */
     393              if (num_vfpv3_regs > 0)
     394    	      __gnu_Unwind_Restore_VFP_D_16_to_31 (&tmp_16_to_31);
     395            }
     396        }
     397        return _UVRSR_OK;
     398  
     399      case _UVRSC_WMMXD:
     400        {
     401  	_uw start = discriminator >> 16;
     402  	_uw count = discriminator & 0xffff;
     403  	struct wmmxd_regs tmp;
     404  	_uw *sp;
     405  	_uw *dest;
     406  
     407  	if ((representation != _UVRSD_UINT64) || start + count > 16)
     408  	  return _UVRSR_FAILED;
     409  
     410  	if (vrs->demand_save_flags & DEMAND_SAVE_WMMXD)
     411  	  {
     412  	    /* Demand-save resisters for stage1.  */
     413  	    vrs->demand_save_flags &= ~DEMAND_SAVE_WMMXD;
     414  	    __gnu_Unwind_Save_WMMXD (&vrs->wmmxd);
     415  	  }
     416  
     417  	/* Restore the registers from the stack.  Do this by saving the
     418  	   current WMMXD registers to a memory area, moving the in-memory
     419  	   values into that area, and restoring from the whole area.  */
     420  	__gnu_Unwind_Save_WMMXD (&tmp);
     421  
     422  	/* The stack address is only guaranteed to be word aligned, so
     423  	   we can't use doubleword copies.  */
     424  	sp = (_uw *) vrs->core.r[R_SP];
     425  	dest = (_uw *) &tmp.wd[start];
     426  	count *= 2;
     427  	while (count--)
     428  	  *(dest++) = *(sp++);
     429  
     430  	/* Set the new stack pointer.  */
     431  	vrs->core.r[R_SP] = (_uw) sp;
     432  
     433  	/* Reload the registers.  */
     434  	__gnu_Unwind_Restore_WMMXD (&tmp);
     435        }
     436        return _UVRSR_OK;
     437  
     438      case _UVRSC_WMMXC:
     439        {
     440  	int i;
     441  	struct wmmxc_regs tmp;
     442  	_uw *sp;
     443  
     444  	if ((representation != _UVRSD_UINT32) || discriminator > 16)
     445  	  return _UVRSR_FAILED;
     446  
     447  	if (vrs->demand_save_flags & DEMAND_SAVE_WMMXC)
     448  	  {
     449  	    /* Demand-save resisters for stage1.  */
     450  	    vrs->demand_save_flags &= ~DEMAND_SAVE_WMMXC;
     451  	    __gnu_Unwind_Save_WMMXC (&vrs->wmmxc);
     452  	  }
     453  
     454  	/* Restore the registers from the stack.  Do this by saving the
     455  	   current WMMXC registers to a memory area, moving the in-memory
     456  	   values into that area, and restoring from the whole area.  */
     457  	__gnu_Unwind_Save_WMMXC (&tmp);
     458  
     459  	sp = (_uw *) vrs->core.r[R_SP];
     460  	for (i = 0; i < 4; i++)
     461  	  if (discriminator & (1 << i))
     462  	    tmp.wc[i] = *(sp++);
     463  
     464  	/* Set the new stack pointer.  */
     465  	vrs->core.r[R_SP] = (_uw) sp;
     466  
     467  	/* Reload the registers.  */
     468  	__gnu_Unwind_Restore_WMMXC (&tmp);
     469        }
     470        return _UVRSR_OK;
     471  
     472      default:
     473        return _UVRSR_FAILED;
     474      }
     475  }
     476  
     477  
     478  /* Core unwinding functions.  */
     479  
     480  /* Calculate the address encoded by a 31-bit self-relative offset at address
     481     P.  */
     482  static inline _uw
     483  selfrel_offset31 (const _uw *p)
     484  {
     485    _uw offset;
     486  
     487    offset = *p;
     488    /* Sign extend to 32 bits.  */
     489    if (offset & (1 << 30))
     490      offset |= 1u << 31;
     491    else
     492      offset &= ~(1u << 31);
     493  
     494    return offset + (_uw) p;
     495  }
     496  
     497  static _uw
     498  __gnu_unwind_get_pr_addr (int idx)
     499  {
     500    switch (idx)
     501      {
     502      case 0:
     503        return (_uw) &__aeabi_unwind_cpp_pr0;
     504  
     505      case 1:
     506        return (_uw) &__aeabi_unwind_cpp_pr1;
     507  
     508      case 2:
     509        return (_uw) &__aeabi_unwind_cpp_pr2;
     510  
     511      default:
     512        return 0;
     513      } 
     514  }
     515  
     516  /* ABI defined personality routine entry points.  */
     517  
     518  _Unwind_Reason_Code
     519  __aeabi_unwind_cpp_pr0 (_Unwind_State state,
     520  			_Unwind_Control_Block *ucbp,
     521  			_Unwind_Context *context)
     522  {
     523    return __gnu_unwind_pr_common (state, ucbp, context, 0);
     524  }
     525  
     526  _Unwind_Reason_Code
     527  __aeabi_unwind_cpp_pr1 (_Unwind_State state,
     528  			_Unwind_Control_Block *ucbp,
     529  			_Unwind_Context *context)
     530  {
     531    return __gnu_unwind_pr_common (state, ucbp, context, 1);
     532  }
     533  
     534  _Unwind_Reason_Code
     535  __aeabi_unwind_cpp_pr2 (_Unwind_State state,
     536  			_Unwind_Control_Block *ucbp,
     537  			_Unwind_Context *context)
     538  {
     539    return __gnu_unwind_pr_common (state, ucbp, context, 2);
     540  }
     541  
     542  #ifdef __FreeBSD__
     543  /* FreeBSD expects these to be functions */
     544  inline _Unwind_Ptr
     545  _Unwind_GetIP (struct _Unwind_Context *context)
     546  {
     547    return _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1;
     548  }
     549  
     550  inline _Unwind_Ptr
     551  _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
     552  {
     553    *ip_before_insn = 0;
     554    return _Unwind_GetIP (context);
     555  }
     556  
     557  inline void
     558  _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
     559  {
     560    _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1));
     561  }
     562  #endif