(root)/
gcc-13.2.0/
libgcc/
config/
ia64/
linux-unwind.h
       1  /* DWARF2 EH unwinding support for IA64 Linux.
       2     Copyright (C) 2004-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of GCC.
       5  
       6     GCC is free software; you can redistribute it and/or modify it
       7     under the terms of the GNU General Public License as published
       8     by the Free Software Foundation; either version 3, or (at your
       9     option) any later version.
      10  
      11     GCC is distributed in the hope that it will be useful, but WITHOUT
      12     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      13     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      14     License for more details.
      15  
      16     Under Section 7 of GPL version 3, you are granted additional
      17     permissions described in the GCC Runtime Library Exception, version
      18     3.1, as published by the Free Software Foundation.
      19  
      20     You should have received a copy of the GNU General Public License and
      21     a copy of the GCC Runtime Library Exception along with this program;
      22     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      23     <http://www.gnu.org/licenses/>.  */
      24  
      25  /* Do code reading to identify a signal frame, and set the frame
      26     state data appropriately.  See unwind-ia64.c for the structs.  */
      27  
      28  /* This works only for glibc-2.3 and later, because sigcontext is different
      29     in glibc-2.2.4.  */
      30  
      31  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
      32  #include <signal.h>
      33  #include <sys/ucontext.h>
      34  
      35  #define IA64_GATE_AREA_START 0xa000000000000100LL
      36  #define IA64_GATE_AREA_END   0xa000000000030000LL
      37  
      38  #define MD_FALLBACK_FRAME_STATE_FOR ia64_fallback_frame_state
      39  
      40  static _Unwind_Reason_Code
      41  ia64_fallback_frame_state (struct _Unwind_Context *context,
      42  			   _Unwind_FrameState *fs)
      43  {
      44    if (context->rp >= IA64_GATE_AREA_START
      45        && context->rp < IA64_GATE_AREA_END)
      46      {
      47        struct sigframe {
      48  	char scratch[16];
      49  	unsigned long sig_number;
      50  	siginfo_t *info;
      51  	struct sigcontext *sc;
      52        } *frame_ = (struct sigframe *)context->psp;
      53        struct sigcontext *sc = frame_->sc;
      54  
      55        /* Restore scratch registers in case the unwinder needs to
      56  	 refer to a value stored in one of them.  */
      57        {
      58  	int i;
      59  
      60  	for (i = 2; i < 4; i++)
      61  	  context->ireg[i - 2].loc = &sc->sc_gr[i];
      62  	for (i = 8; i < 12; i++)
      63  	  context->ireg[i - 2].loc = &sc->sc_gr[i];
      64  	for (i = 14; i < 32; i++)
      65  	  context->ireg[i - 2].loc = &sc->sc_gr[i];
      66        }
      67  
      68        context->fpsr_loc = &(sc->sc_ar_fpsr);
      69        context->signal_pfs_loc = &(sc->sc_ar_pfs);
      70        context->lc_loc = &(sc->sc_ar_lc);
      71        context->unat_loc = &(sc->sc_ar_unat);
      72        context->br_loc[0] = &(sc->sc_br[0]);
      73        context->br_loc[6] = &(sc->sc_br[6]);
      74        context->br_loc[7] = &(sc->sc_br[7]);
      75        context->pr = sc->sc_pr;
      76        context->psp = sc->sc_gr[12];
      77        context->gp = sc->sc_gr[1];
      78        /* Signal frame doesn't have an associated reg. stack frame
      79           other than what we adjust for below.	  */
      80        fs -> no_reg_stack_frame = 1;
      81  
      82        if (sc->sc_rbs_base)
      83  	{
      84  	  /* Need to switch from alternate register backing store.  */
      85  	  long ndirty, loadrs = sc->sc_loadrs >> 16;
      86  	  unsigned long alt_bspstore = context->bsp - loadrs;
      87  	  unsigned long bspstore;
      88  	  unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp);
      89  
      90  	  ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore,
      91  				      (unsigned long *) context->bsp);
      92  	  bspstore = (unsigned long)
      93  	    ia64_rse_skip_regs (ar_bsp, -ndirty);
      94  	  ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs,
      95  			 sc->sc_ar_rnat);
      96  	}
      97  
      98        /* Don't touch the branch registers o.t. b0, b6 and b7.
      99  	 The kernel doesn't pass the preserved branch registers
     100  	 in the sigcontext but leaves them intact, so there's no
     101  	 need to do anything with them here.  */
     102        {
     103  	unsigned long sof = sc->sc_cfm & 0x7f;
     104  	context->bsp = (unsigned long)
     105  	  ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
     106        }
     107  
     108        /* Account for use of br.ret to resume execution of user code.  */
     109        fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL;
     110        fs->curr.reg[UNW_REG_RP].val
     111  	= (unsigned long)&(sc->sc_ip) - context->psp;
     112        fs->curr.reg[UNW_REG_RP].when = -1;
     113  
     114        fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_SPREL;
     115        fs->curr.reg[UNW_REG_PFS].val
     116  	= (unsigned long)&(sc->sc_cfm) - context->psp;
     117        fs ->curr.reg[UNW_REG_PFS].when = -1;
     118  
     119        return _URC_NO_REASON;
     120      }
     121    return _URC_END_OF_STACK;
     122  }
     123  
     124  #define MD_HANDLE_UNWABI ia64_handle_unwabi
     125  
     126  #define ABI_MARKER_OLD_LINUX_SIGTRAMP	((0 << 8) | 's')
     127  #define ABI_MARKER_OLD_LINUX_INTERRUPT	((0 << 8) | 'i')
     128  #define ABI_MARKER_LINUX_SIGTRAMP	((3 << 8) | 's')
     129  #define ABI_MARKER_LINUX_INTERRUPT	((3 << 8) | 'i')
     130  
     131  static void
     132  ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs)
     133  {
     134    if (fs->unwabi == ABI_MARKER_LINUX_SIGTRAMP
     135        || fs->unwabi == ABI_MARKER_OLD_LINUX_SIGTRAMP)
     136      {
     137        struct sigframe {
     138  	char scratch[16];
     139  	unsigned long sig_number;
     140  	siginfo_t *info;
     141  	struct sigcontext *sc;
     142        } *frame = (struct sigframe *)context->psp;
     143        struct sigcontext *sc = frame->sc;
     144  
     145        /* Restore scratch registers in case the unwinder needs to
     146  	 refer to a value stored in one of them.  */
     147        {
     148  	int i;
     149  
     150  	for (i = 2; i < 4; i++)
     151  	  context->ireg[i - 2].loc = &sc->sc_gr[i];
     152  	for (i = 8; i < 12; i++)
     153  	  context->ireg[i - 2].loc = &sc->sc_gr[i];
     154  	for (i = 14; i < 32; i++)
     155  	  context->ireg[i - 2].loc = &sc->sc_gr[i];
     156        }
     157  
     158        context->signal_pfs_loc = &(sc->sc_ar_pfs);
     159        context->lc_loc = &(sc->sc_ar_lc);
     160        context->unat_loc = &(sc->sc_ar_unat);
     161        context->br_loc[0] = &(sc->sc_br[0]);
     162        context->br_loc[6] = &(sc->sc_br[6]);
     163        context->br_loc[7] = &(sc->sc_br[7]);
     164        context->pr = sc->sc_pr;
     165        context->gp = sc->sc_gr[1];
     166        /* Signal frame doesn't have an associated reg. stack frame
     167           other than what we adjust for below.	  */
     168        fs -> no_reg_stack_frame = 1;
     169  
     170        if (sc->sc_rbs_base)
     171  	{
     172  	  /* Need to switch from alternate register backing store.  */
     173  	  long ndirty, loadrs = sc->sc_loadrs >> 16;
     174  	  unsigned long alt_bspstore = context->bsp - loadrs;
     175  	  unsigned long bspstore;
     176  	  unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp);
     177  
     178  	  ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore,
     179  				      (unsigned long *) context->bsp);
     180  	  bspstore = (unsigned long) ia64_rse_skip_regs (ar_bsp, -ndirty);
     181  	  ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs,
     182  			 sc->sc_ar_rnat);
     183  	}
     184  
     185        /* Don't touch the branch registers o.t. b0, b6 and b7.
     186  	 The kernel doesn't pass the preserved branch registers
     187  	 in the sigcontext but leaves them intact, so there's no
     188  	 need to do anything with them here.  */
     189        {
     190  	unsigned long sof = sc->sc_cfm & 0x7f;
     191  	context->bsp = (unsigned long)
     192  	  ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
     193        }
     194  
     195        /* The use of br.ret to resume execution of user code is already
     196  	 accounted for in the unwind ABI.  */
     197      }
     198  }
     199  #endif /* glibc-2.3 or better */