(root)/
gcc-13.2.0/
libgcc/
config/
pa/
hpux-unwind.h
       1  /* DWARF2 EH unwinding support for PA HP-UX.
       2     Copyright (C) 2005-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
       7  it under the terms of the GNU General Public License as published by
       8  the Free Software Foundation; either version 3, or (at your option)
       9  any later version.
      10  
      11  GCC is distributed in the hope that it will be useful,
      12  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14  GNU General Public 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-dw2.c for the structs.  */
      27  
      28  /* Don't use this if inhibit_libc is set.
      29     The build for this target will fail trying to include missing headers. */
      30  #ifndef inhibit_libc
      31  #include <signal.h>
      32  #include <sys/ucontext.h>
      33  #include <unistd.h>
      34  
      35  /* FIXME: We currently ignore the high halves of general, space and
      36     control registers on PA 2.0 machines for applications using the
      37     32-bit runtime.  We don't restore space registers or the floating
      38     point status registers.  */
      39  
      40  #define MD_FALLBACK_FRAME_STATE_FOR pa_fallback_frame_state
      41  
      42  /* HP-UX 10.X doesn't define GetSSReg.  */
      43  #ifndef GetSSReg
      44  #define GetSSReg(ssp, ss_reg) \
      45    ((UseWideRegs (ssp))							\
      46     ? (ssp)->ss_wide.ss_32.ss_reg ## _lo					\
      47     : (ssp)->ss_narrow.ss_reg)
      48  #endif
      49  
      50  #if TARGET_64BIT
      51  #define GetSSRegAddr(ssp, ss_reg) ((long) &((ssp)->ss_wide.ss_64.ss_reg))
      52  #else
      53  #define GetSSRegAddr(ssp, ss_reg) \
      54    ((UseWideRegs (ssp))							\
      55     ? (long) &((ssp)->ss_wide.ss_32.ss_reg ## _lo)			\
      56     : (long) &((ssp)->ss_narrow.ss_reg))
      57  #endif
      58  
      59  #define UPDATE_FS_FOR_SAR(FS, N) \
      60    (FS)->regs.how[N] = REG_SAVED_OFFSET;				\
      61    (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_cr11) - new_cfa
      62  
      63  #define UPDATE_FS_FOR_GR(FS, GRN, N) \
      64    (FS)->regs.how[N] = REG_SAVED_OFFSET;				\
      65    (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_gr##GRN) - new_cfa
      66  
      67  #define UPDATE_FS_FOR_FR(FS, FRN, N) \
      68    (FS)->regs.how[N] = REG_SAVED_OFFSET;				\
      69    (FS)->regs.reg[N].loc.offset = (long) &(mc->ss_fr##FRN) - new_cfa;
      70  
      71  #define UPDATE_FS_FOR_PC(FS, N) \
      72    (FS)->regs.how[N] = REG_SAVED_OFFSET;				\
      73    (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_pcoq_head) - new_cfa
      74  
      75  /* Extract bit field from word using HP's numbering (MSB = 0).  */
      76  #define GET_FIELD(X, FROM, TO) \
      77    ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
      78  
      79  static inline int
      80  sign_extend (int x, int len)
      81  {
      82    int signbit = (1 << (len - 1));
      83    int mask = (signbit << 1) - 1;
      84    return ((x & mask) ^ signbit) - signbit;
      85  }
      86  
      87  /* Extract a 17-bit signed constant from branch instructions.  */
      88  static inline int
      89  extract_17 (unsigned word)
      90  {
      91    return sign_extend (GET_FIELD (word, 19, 28)
      92  		      | GET_FIELD (word, 29, 29) << 10
      93  		      | GET_FIELD (word, 11, 15) << 11
      94  		      | (word & 0x1) << 16, 17);
      95  }
      96  
      97  /* Extract a 22-bit signed constant from branch instructions.  */
      98  static inline int
      99  extract_22 (unsigned word)
     100  {
     101    return sign_extend (GET_FIELD (word, 19, 28)
     102  		      | GET_FIELD (word, 29, 29) << 10
     103  		      | GET_FIELD (word, 11, 15) << 11
     104  		      | GET_FIELD (word, 6, 10) << 16
     105  		      | (word & 0x1) << 21, 22);
     106  }
     107  
     108  static _Unwind_Reason_Code
     109  pa_fallback_frame_state (struct _Unwind_Context *context,
     110  			 _Unwind_FrameState *fs)
     111  {
     112    static long cpu;
     113    unsigned int *pc = (unsigned int *) context->ra;
     114  
     115    if (pc == 0)
     116      return _URC_END_OF_STACK;
     117  
     118    /* Check for relocation of the return value.  */
     119    if (!TARGET_64BIT
     120        && *(pc + 0) == 0x2fd01224		/* fstd,ma fr4,8(sp) */
     121        && *(pc + 1) == 0x0fd9109d		/* ldw -4(sp),ret1 */
     122        && *(pc + 2) == 0x0fd130bc)		/* ldw,mb -8(sp),ret0 */
     123      pc += 3;
     124    else if (!TARGET_64BIT
     125  	   && *(pc + 0) == 0x27d01224		/* fstw,ma fr4,8(sp) */
     126  	   && *(pc + 1) == 0x0fd130bc)		/* ldw,mb -8(sp),ret0 */
     127      pc += 2;
     128    else if (!TARGET_64BIT
     129  	   && *(pc + 0) == 0x0fdc12b0		/* stw,ma ret0,8(sp) */
     130  	   && *(pc + 1) == 0x0fdd1299		/* stw ret1,-4(sp) */
     131  	   && *(pc + 2) == 0x2fd13024)		/* fldd,mb -8(sp),fr4 */
     132      pc += 3;
     133    else if (!TARGET_64BIT
     134  	   && *(pc + 0) == 0x0fdc12b0		/* stw,ma ret0,8(sp) */
     135  	   && *(pc + 1) == 0x27d13024)		/* fldw,mb -8(sp),fr4 */
     136      pc += 2;
     137  
     138    /* Check if the return address points to an export stub (PA 1.1 or 2.0).  */
     139    if ((!TARGET_64BIT
     140         && *(pc + 0) == 0x4bc23fd1		/* ldw -18(sp),rp */
     141         && *(pc + 1) == 0x004010a1		/* ldsid (rp),r1 */
     142         && *(pc + 2) == 0x00011820		/* mtsp r1,sr0 */
     143         && *(pc + 3) == 0xe0400002)		/* be,n 0(sr0,rp) */
     144        ||
     145        (!TARGET_64BIT
     146         && *(pc + 0) == 0x4bc23fd1		/* ldw -18(sp),rp */
     147         && *(pc + 1) == 0xe840d002))		/* bve,n (rp) */
     148      {
     149        fs->regs.cfa_how    = CFA_REG_OFFSET;
     150        fs->regs.cfa_reg    = 30;
     151        fs->regs.cfa_offset = 0;
     152  
     153        fs->retaddr_column = 0;
     154        fs->regs.how[0] = REG_SAVED_OFFSET;
     155        fs->regs.reg[0].loc.offset = -24;
     156  
     157        /* Update context to describe the stub frame.  */
     158        uw_update_context (context, fs);
     159  
     160        /* Set up fs to describe the FDE for the caller of this stub.  */
     161        return uw_frame_state_for (context, fs);
     162      }
     163    /* Check if the return address points to a relocation stub.  */
     164    else if (!TARGET_64BIT
     165  	   && *(pc + 0) == 0x0fd11082		/* ldw -8(sp),rp */
     166  	   && (*(pc + 1) == 0xe840c002		/* bv,n r0(rp) */
     167  	       || *(pc + 1) == 0xe840d002))	/* bve,n (rp) */
     168      {
     169        fs->regs.cfa_how    = CFA_REG_OFFSET;
     170        fs->regs.cfa_reg    = 30;
     171        fs->regs.cfa_offset = 0;
     172  
     173        fs->retaddr_column = 0;
     174        fs->regs.how[0] = REG_SAVED_OFFSET;
     175        fs->regs.reg[0].loc.offset = -8;
     176  
     177        /* Update context to describe the stub frame.  */
     178        uw_update_context (context, fs);
     179  
     180        /* Set up fs to describe the FDE for the caller of this stub.  */
     181        return uw_frame_state_for (context, fs);
     182      }
     183  
     184    /* Check if the return address is an export stub as signal handlers
     185       may return via an export stub.  */
     186    if (!TARGET_64BIT
     187        && (*pc & 0xffe0e002) == 0xe8400000	/* bl x,r2 */
     188        && *(pc + 1) == 0x08000240		/* nop */
     189        && *(pc + 2) == 0x4bc23fd1		/* ldw -18(sp),rp */
     190        && *(pc + 3) == 0x004010a1		/* ldsid (rp),r1 */
     191        && *(pc + 4) == 0x00011820		/* mtsp r1,sr0 */
     192        && *(pc + 5) == 0xe0400002)		/* be,n 0(sr0,rp) */
     193      /* Extract target address from PA 1.x 17-bit branch.  */
     194      pc += extract_17 (*pc) + 2;
     195    else if (!TARGET_64BIT
     196  	   && (*pc & 0xfc00e002) == 0xe800a000	/* b,l x,r2 */
     197  	   && *(pc + 1) == 0x08000240		/* nop */
     198  	   && *(pc + 2) == 0x4bc23fd1		/* ldw -18(sp),rp */
     199  	   && *(pc + 3) == 0xe840d002)		/* bve,n (rp) */
     200      /* Extract target address from PA 2.0 22-bit branch.  */
     201      pc += extract_22 (*pc) + 2;
     202  
     203    /* Now check if the return address is one of the signal handler
     204       returns, _sigreturn or _sigsetreturn.  */
     205    if ((TARGET_64BIT
     206         && *(pc + 0)  == 0x53db3f51		/* ldd -58(sp),dp */
     207         && *(pc + 8)  == 0x34160116		/* ldi 8b,r22 */
     208         && *(pc + 9)  == 0x08360ac1		/* shladd,l r22,3,r1,r1 */
     209         && *(pc + 10) == 0x0c2010c1		/* ldd 0(r1),r1 */
     210         && *(pc + 11) == 0xe4202000)		/* be,l 0(sr4,r1) */
     211        ||
     212        (TARGET_64BIT
     213         && *(pc + 0)  == 0x36dc0000		/* ldo 0(r22),ret0 */
     214         && *(pc + 6)  == 0x341601c0		/* ldi e0,r22 */
     215         && *(pc + 7)  == 0x08360ac1		/* shladd,l r22,3,r1,r1 */
     216         && *(pc + 8)  == 0x0c2010c1		/* ldd 0(r1),r1 */
     217         && *(pc + 9)  == 0xe4202000)		/* be,l 0(sr4,r1) */
     218        ||
     219        (!TARGET_64BIT
     220         && *(pc + 0)  == 0x379a0000		/* ldo 0(ret0),r26 */
     221         && *(pc + 1)  == 0x6bd33fc9		/* stw r19,-1c(sp) */
     222         && *(pc + 2)  == 0x20200801		/* ldil L%-40000000,r1 */
     223         && *(pc + 3)  == 0xe420e008		/* be,l 4(sr7,r1) */
     224         && *(pc + 4)  == 0x34160116)		/* ldi 8b,r22 */
     225        ||
     226        (!TARGET_64BIT
     227         && *(pc + 0)  == 0x6bd33fc9		/* stw r19,-1c(sp) */
     228         && *(pc + 1)  == 0x20200801		/* ldil L%-40000000,r1 */
     229         && *(pc + 2)  == 0xe420e008		/* be,l 4(sr7,r1) */
     230         && *(pc + 3)  == 0x341601c0))		/* ldi e0,r22 */
     231      {
     232        /* The previous stack pointer is saved at (long *)SP - 1.  The
     233  	 ucontext structure is offset from the start of the previous
     234  	 frame by the siglocal_misc structure.  */
     235        struct siglocalx *sl = (struct siglocalx *)
     236  	(*((long *) context->cfa - 1));
     237        mcontext_t *mc = &(sl->sl_uc.uc_mcontext);
     238  
     239        long new_cfa = GetSSReg (mc, ss_sp);
     240  
     241        fs->regs.cfa_how = CFA_REG_OFFSET;
     242        fs->regs.cfa_reg = 30;
     243        fs->regs.cfa_offset = new_cfa - (long) context->cfa;
     244  
     245        UPDATE_FS_FOR_GR (fs, 1, 1);
     246        UPDATE_FS_FOR_GR (fs, 2, 2);
     247        UPDATE_FS_FOR_GR (fs, 3, 3);
     248        UPDATE_FS_FOR_GR (fs, 4, 4);
     249        UPDATE_FS_FOR_GR (fs, 5, 5);
     250        UPDATE_FS_FOR_GR (fs, 6, 6);
     251        UPDATE_FS_FOR_GR (fs, 7, 7);
     252        UPDATE_FS_FOR_GR (fs, 8, 8);
     253        UPDATE_FS_FOR_GR (fs, 9, 9);
     254        UPDATE_FS_FOR_GR (fs, 10, 10);
     255        UPDATE_FS_FOR_GR (fs, 11, 11);
     256        UPDATE_FS_FOR_GR (fs, 12, 12);
     257        UPDATE_FS_FOR_GR (fs, 13, 13);
     258        UPDATE_FS_FOR_GR (fs, 14, 14);
     259        UPDATE_FS_FOR_GR (fs, 15, 15);
     260        UPDATE_FS_FOR_GR (fs, 16, 16);
     261        UPDATE_FS_FOR_GR (fs, 17, 17);
     262        UPDATE_FS_FOR_GR (fs, 18, 18);
     263        UPDATE_FS_FOR_GR (fs, 19, 19);
     264        UPDATE_FS_FOR_GR (fs, 20, 20);
     265        UPDATE_FS_FOR_GR (fs, 21, 21);
     266        UPDATE_FS_FOR_GR (fs, 22, 22);
     267        UPDATE_FS_FOR_GR (fs, 23, 23);
     268        UPDATE_FS_FOR_GR (fs, 24, 24);
     269        UPDATE_FS_FOR_GR (fs, 25, 25);
     270        UPDATE_FS_FOR_GR (fs, 26, 26);
     271        UPDATE_FS_FOR_GR (fs, 27, 27);
     272        UPDATE_FS_FOR_GR (fs, 28, 28);
     273        UPDATE_FS_FOR_GR (fs, 29, 29);
     274        UPDATE_FS_FOR_GR (fs, 30, 30);
     275        UPDATE_FS_FOR_GR (fs, 31, 31);
     276  
     277        if (TARGET_64BIT)
     278  	{
     279  	  UPDATE_FS_FOR_FR (fs, 4, 32);
     280  	  UPDATE_FS_FOR_FR (fs, 5, 33);
     281  	  UPDATE_FS_FOR_FR (fs, 6, 34);
     282  	  UPDATE_FS_FOR_FR (fs, 7, 35);
     283  	  UPDATE_FS_FOR_FR (fs, 8, 36);
     284  	  UPDATE_FS_FOR_FR (fs, 9, 37);
     285  	  UPDATE_FS_FOR_FR (fs, 10, 38);
     286  	  UPDATE_FS_FOR_FR (fs, 11, 39);
     287  	  UPDATE_FS_FOR_FR (fs, 12, 40);
     288  	  UPDATE_FS_FOR_FR (fs, 13, 41);
     289  	  UPDATE_FS_FOR_FR (fs, 14, 42);
     290  	  UPDATE_FS_FOR_FR (fs, 15, 43);
     291  	  UPDATE_FS_FOR_FR (fs, 16, 44);
     292  	  UPDATE_FS_FOR_FR (fs, 17, 45);
     293  	  UPDATE_FS_FOR_FR (fs, 18, 46);
     294  	  UPDATE_FS_FOR_FR (fs, 19, 47);
     295  	  UPDATE_FS_FOR_FR (fs, 20, 48);
     296  	  UPDATE_FS_FOR_FR (fs, 21, 49);
     297  	  UPDATE_FS_FOR_FR (fs, 22, 50);
     298  	  UPDATE_FS_FOR_FR (fs, 23, 51);
     299  	  UPDATE_FS_FOR_FR (fs, 24, 52);
     300  	  UPDATE_FS_FOR_FR (fs, 25, 53);
     301  	  UPDATE_FS_FOR_FR (fs, 26, 54);
     302  	  UPDATE_FS_FOR_FR (fs, 27, 55);
     303  	  UPDATE_FS_FOR_FR (fs, 28, 56);
     304  	  UPDATE_FS_FOR_FR (fs, 29, 57);
     305  	  UPDATE_FS_FOR_FR (fs, 30, 58);
     306  	  UPDATE_FS_FOR_FR (fs, 31, 59);
     307  
     308  	  UPDATE_FS_FOR_SAR (fs, 60);
     309  	}
     310        else
     311  	{
     312  	  UPDATE_FS_FOR_FR (fs, 4, 32);
     313  	  UPDATE_FS_FOR_FR (fs, 5, 34);
     314  	  UPDATE_FS_FOR_FR (fs, 6, 36);
     315  	  UPDATE_FS_FOR_FR (fs, 7, 38);
     316  	  UPDATE_FS_FOR_FR (fs, 8, 40);
     317  	  UPDATE_FS_FOR_FR (fs, 9, 44);
     318  	  UPDATE_FS_FOR_FR (fs, 10, 44);
     319  	  UPDATE_FS_FOR_FR (fs, 11, 46);
     320  	  UPDATE_FS_FOR_FR (fs, 12, 48);
     321  	  UPDATE_FS_FOR_FR (fs, 13, 50);
     322  	  UPDATE_FS_FOR_FR (fs, 14, 52);
     323  	  UPDATE_FS_FOR_FR (fs, 15, 54);
     324  
     325  	  if (!cpu)
     326  	    cpu = sysconf (_SC_CPU_VERSION);
     327  
     328  	  /* PA-RISC 1.0 only has 16 floating point registers.  */
     329  	  if (cpu != CPU_PA_RISC1_0)
     330  	    {
     331  	      UPDATE_FS_FOR_FR (fs, 16, 56);
     332  	      UPDATE_FS_FOR_FR (fs, 17, 58);
     333  	      UPDATE_FS_FOR_FR (fs, 18, 60);
     334  	      UPDATE_FS_FOR_FR (fs, 19, 62);
     335  	      UPDATE_FS_FOR_FR (fs, 20, 64);
     336  	      UPDATE_FS_FOR_FR (fs, 21, 66);
     337  	      UPDATE_FS_FOR_FR (fs, 22, 68);
     338  	      UPDATE_FS_FOR_FR (fs, 23, 70);
     339  	      UPDATE_FS_FOR_FR (fs, 24, 72);
     340  	      UPDATE_FS_FOR_FR (fs, 25, 74);
     341  	      UPDATE_FS_FOR_FR (fs, 26, 76);
     342  	      UPDATE_FS_FOR_FR (fs, 27, 78);
     343  	      UPDATE_FS_FOR_FR (fs, 28, 80);
     344  	      UPDATE_FS_FOR_FR (fs, 29, 82);
     345  	      UPDATE_FS_FOR_FR (fs, 30, 84);
     346  	      UPDATE_FS_FOR_FR (fs, 31, 86);
     347  	    }
     348  
     349  	  UPDATE_FS_FOR_SAR (fs, 88);
     350  	}
     351  
     352        fs->retaddr_column = __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__;
     353        UPDATE_FS_FOR_PC (fs, __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__);
     354        fs->signal_frame = 1;
     355  
     356        return _URC_NO_REASON;
     357      }
     358  
     359    return _URC_END_OF_STACK;
     360  }
     361  #endif /* inhibit_libc */