(root)/
gcc-13.2.0/
libgcc/
config/
i386/
sol2-unwind.h
       1  /* DWARF2 EH unwinding support for AMD x86-64 and x86.
       2     Copyright (C) 2009-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  #include <ucontext.h>
      29  #include <sys/frame.h>
      30  
      31  #ifdef __x86_64__
      32  
      33  #define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state
      34  
      35  static _Unwind_Reason_Code
      36  x86_64_fallback_frame_state (struct _Unwind_Context *context,
      37  			     _Unwind_FrameState *fs)
      38  {
      39    unsigned char *pc = context->ra;
      40    mcontext_t *mctx;
      41    long new_cfa;
      42  
      43    if (/* Solaris 10+
      44  	------------
      45  	<__sighndlr+0>:      push   %rbp
      46  	<__sighndlr+1>:      mov    %rsp,%rbp
      47  	<__sighndlr+4>:      callq  *%rcx
      48  	<__sighndlr+6>:      leaveq           <--- PC
      49  	<__sighndlr+7>:      retq  */
      50        *(unsigned long *)(pc - 6) == 0xc3c9d1ffe5894855)
      51  
      52      /* We need to move up three frames:
      53  
      54  		<signal handler>	<-- context->cfa
      55  		__sighndlr
      56  		call_user_handler
      57  		sigacthandler
      58  		<kernel>
      59  
      60         context->cfa points into the frame after the saved frame pointer and
      61         saved pc (struct frame).
      62  
      63         The ucontext_t structure is in the kernel frame after the signal
      64         number and a siginfo_t *.  Since the frame sizes vary even within
      65         Solaris 10 updates, we need to walk the stack to get there.  */
      66      {
      67        struct frame *fp = (struct frame *) context->cfa - 1;
      68        struct handler_args {
      69  	int signo;
      70  	siginfo_t *sip;
      71  	ucontext_t ucontext;
      72        } *handler_args;
      73        ucontext_t *ucp;
      74  
      75        /* Next frame: __sighndlr frame pointer.  */
      76        fp = (struct frame *) fp->fr_savfp;
      77        /* call_user_handler frame pointer.  */
      78        fp = (struct frame *) fp->fr_savfp;
      79        /* sigacthandler frame pointer.  */
      80        fp = (struct frame *) fp->fr_savfp;
      81  
      82        /* The argument area precedes the struct frame.  */
      83        handler_args = (struct handler_args *) (fp + 1);
      84        ucp = &handler_args->ucontext;
      85        mctx = &ucp->uc_mcontext;
      86      }
      87    else
      88      return _URC_END_OF_STACK;
      89  
      90    new_cfa = mctx->gregs[REG_RSP];
      91  
      92    fs->regs.cfa_how = CFA_REG_OFFSET;
      93    fs->regs.cfa_reg = 7;
      94    fs->regs.cfa_offset = new_cfa - (long) context->cfa;
      95  
      96    /* The SVR4 register numbering macros aren't usable in libgcc.  */
      97    fs->regs.how[0] = REG_SAVED_OFFSET;
      98    fs->regs.reg[0].loc.offset = (long)&mctx->gregs[REG_RAX] - new_cfa;
      99    fs->regs.how[1] = REG_SAVED_OFFSET;
     100    fs->regs.reg[1].loc.offset = (long)&mctx->gregs[REG_RDX] - new_cfa;
     101    fs->regs.how[2] = REG_SAVED_OFFSET;
     102    fs->regs.reg[2].loc.offset = (long)&mctx->gregs[REG_RCX] - new_cfa;
     103    fs->regs.how[3] = REG_SAVED_OFFSET;
     104    fs->regs.reg[3].loc.offset = (long)&mctx->gregs[REG_RBX] - new_cfa;
     105    fs->regs.how[4] = REG_SAVED_OFFSET;
     106    fs->regs.reg[4].loc.offset = (long)&mctx->gregs[REG_RSI] - new_cfa;
     107    fs->regs.how[5] = REG_SAVED_OFFSET;
     108    fs->regs.reg[5].loc.offset = (long)&mctx->gregs[REG_RDI] - new_cfa;
     109    fs->regs.how[6] = REG_SAVED_OFFSET;
     110    fs->regs.reg[6].loc.offset = (long)&mctx->gregs[REG_RBP] - new_cfa;
     111    fs->regs.how[8] = REG_SAVED_OFFSET;
     112    fs->regs.reg[8].loc.offset = (long)&mctx->gregs[REG_R8] - new_cfa;
     113    fs->regs.how[9] = REG_SAVED_OFFSET;
     114    fs->regs.reg[9].loc.offset = (long)&mctx->gregs[REG_R9] - new_cfa;
     115    fs->regs.how[10] = REG_SAVED_OFFSET;
     116    fs->regs.reg[10].loc.offset = (long)&mctx->gregs[REG_R10] - new_cfa;
     117    fs->regs.how[11] = REG_SAVED_OFFSET;
     118    fs->regs.reg[11].loc.offset = (long)&mctx->gregs[REG_R11] - new_cfa;
     119    fs->regs.how[12] = REG_SAVED_OFFSET;
     120    fs->regs.reg[12].loc.offset = (long)&mctx->gregs[REG_R12] - new_cfa;
     121    fs->regs.how[13] = REG_SAVED_OFFSET;
     122    fs->regs.reg[13].loc.offset = (long)&mctx->gregs[REG_R13] - new_cfa;
     123    fs->regs.how[14] = REG_SAVED_OFFSET;
     124    fs->regs.reg[14].loc.offset = (long)&mctx->gregs[REG_R14] - new_cfa;
     125    fs->regs.how[15] = REG_SAVED_OFFSET;
     126    fs->regs.reg[15].loc.offset = (long)&mctx->gregs[REG_R15] - new_cfa;
     127    fs->regs.how[16] = REG_SAVED_OFFSET;
     128    fs->regs.reg[16].loc.offset = (long)&mctx->gregs[REG_RIP] - new_cfa;
     129    fs->retaddr_column = 16;
     130    fs->signal_frame = 1;
     131  
     132    return _URC_NO_REASON;
     133  }
     134  
     135  #else
     136  
     137  #define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state
     138  
     139  static _Unwind_Reason_Code
     140  x86_fallback_frame_state (struct _Unwind_Context *context,
     141  			  _Unwind_FrameState *fs)
     142  {
     143    unsigned char *pc = context->ra;
     144    mcontext_t *mctx;
     145    long new_cfa;
     146  
     147    if (/* Solaris 11 since snv_125
     148  	   -------------------------
     149  	  <__sighndlr+0>       	push   %ebp
     150  	  <__sighndlr+1>       	mov    %esp,%ebp
     151  	  <__sighndlr+3>       	and    $0xfffffff0,%esp
     152  	  <__sighndlr+6>       	sub    $0x4,%esp
     153  	  <__sighndlr+9>      	pushl  0x10(%ebp)
     154  	  <__sighndlr+12>      	pushl  0xc(%ebp)
     155  	  <__sighndlr+15>      	pushl  0x8(%ebp)
     156  	  <__sighndlr+18>      	call   *0x14(%ebp)
     157  	  <__sighndlr+21>      	leave                <--- PC
     158  	  <__sighndlr+22>      	ret  */
     159  	 (*(unsigned long *)(pc - 21) == 0x83ec8b55
     160  	  && *(unsigned long *)(pc - 17) == 0xec83f0e4
     161  	  && *(unsigned long *)(pc - 13)  == 0x1075ff04
     162  	  && *(unsigned long *)(pc - 9)  == 0xff0c75ff
     163  	  && *(unsigned long *)(pc - 5)  == 0x55ff0875
     164  	  && (*(unsigned long *)(pc - 1) & 0x00ffffff) == 0x00c3c914))
     165      {
     166        struct handler_args {
     167  	int signo;
     168  	siginfo_t *sip;
     169  	ucontext_t *ucontext;
     170        } *handler_args = context->cfa;
     171        mctx = &handler_args->ucontext->uc_mcontext;
     172      }
     173    else
     174      return _URC_END_OF_STACK;
     175  
     176    new_cfa = mctx->gregs[UESP];
     177  
     178    fs->regs.cfa_how = CFA_REG_OFFSET;
     179    fs->regs.cfa_reg = 4;
     180    fs->regs.cfa_offset = new_cfa - (long) context->cfa;
     181  
     182    /* The SVR4 register numbering macros aren't usable in libgcc.  */
     183    fs->regs.how[0] = REG_SAVED_OFFSET;
     184    fs->regs.reg[0].loc.offset = (long)&mctx->gregs[EAX] - new_cfa;
     185    fs->regs.how[3] = REG_SAVED_OFFSET;
     186    fs->regs.reg[3].loc.offset = (long)&mctx->gregs[EBX] - new_cfa;
     187    fs->regs.how[1] = REG_SAVED_OFFSET;
     188    fs->regs.reg[1].loc.offset = (long)&mctx->gregs[ECX] - new_cfa;
     189    fs->regs.how[2] = REG_SAVED_OFFSET;
     190    fs->regs.reg[2].loc.offset = (long)&mctx->gregs[EDX] - new_cfa;
     191    fs->regs.how[6] = REG_SAVED_OFFSET;
     192    fs->regs.reg[6].loc.offset = (long)&mctx->gregs[ESI] - new_cfa;
     193    fs->regs.how[7] = REG_SAVED_OFFSET;
     194    fs->regs.reg[7].loc.offset = (long)&mctx->gregs[EDI] - new_cfa;
     195    fs->regs.how[5] = REG_SAVED_OFFSET;
     196    fs->regs.reg[5].loc.offset = (long)&mctx->gregs[EBP] - new_cfa;
     197    fs->regs.how[8] = REG_SAVED_OFFSET;
     198    fs->regs.reg[8].loc.offset = (long)&mctx->gregs[EIP] - new_cfa;
     199    fs->retaddr_column = 8;
     200  
     201    /* SIGFPE for IEEE-754 exceptions is delivered after the faulting insn
     202       rather than before it, so don't set fs->signal_frame in that case.
     203       We test whether the ES field of the Status Register is zero.  */
     204    if ((mctx->fpregs.fp_reg_set.fpchip_state.status & 0x80) == 0)
     205      fs->signal_frame = 1;
     206  
     207    return _URC_NO_REASON;
     208  }
     209  
     210  #endif