(root)/
gcc-13.2.0/
libgcc/
config/
sh/
linux-unwind.h
       1  /* DWARF2 EH unwinding support for SH 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
       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  
      26  /* Do code reading to identify a signal frame, and set the frame
      27     state data appropriately.  See unwind-dw2.c for the structs.
      28     Don't use this at all if inhibit_libc is used.  */
      29  
      30  #ifndef inhibit_libc
      31  
      32  #include <signal.h>
      33  #include <sys/ucontext.h>
      34  #include "insn-constants.h"
      35  
      36  #define SH_DWARF_FRAME_GP0	0
      37  #define SH_DWARF_FRAME_FP0	25
      38  #define SH_DWARF_FRAME_XD0	87
      39  #define SH_DWARF_FRAME_PR	17
      40  #define SH_DWARF_FRAME_GBR	18
      41  #define SH_DWARF_FRAME_MACH	20
      42  #define SH_DWARF_FRAME_MACL	21
      43  #define SH_DWARF_FRAME_PC	16
      44  #define SH_DWARF_FRAME_SR	22
      45  #define SH_DWARF_FRAME_FPUL	23
      46  #define SH_DWARF_FRAME_FPSCR	24
      47  
      48  #define MD_FALLBACK_FRAME_STATE_FOR sh_fallback_frame_state
      49  
      50  static _Unwind_Reason_Code
      51  sh_fallback_frame_state (struct _Unwind_Context *context,
      52  			 _Unwind_FrameState *fs)
      53  {
      54    unsigned char *pc = context->ra;
      55    struct sigcontext *sc;
      56    long new_cfa;
      57    int i;
      58  #if defined (__SH3E__) || defined (__SH4__)
      59    int r;
      60  #endif
      61  
      62    /* mov.w 1f,r3; trapa #0x10; 1: .short 0x77  (sigreturn)  */
      63    /* mov.w 1f,r3; trapa #0x10; 1: .short 0xad  (rt_sigreturn)  */
      64    /* Newer kernel uses pad instructions to avoid an SH-4 core bug.  */
      65    /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;
      66       or r0,r0; 1: .short 0x77  (sigreturn)  */
      67    /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;
      68       or r0,r0; 1: .short 0xad  (rt_sigreturn)  */
      69    if (((*(unsigned short *) (pc+0)  == 0x9300)
      70         && (*(unsigned short *) (pc+2)  == 0xc310)
      71         && (*(unsigned short *) (pc+4)  == 0x0077))
      72        || (((*(unsigned short *) (pc+0)  == 0x9305)
      73  	   && (*(unsigned short *) (pc+2)  == 0xc310)
      74  	   && (*(unsigned short *) (pc+14)  == 0x0077))))
      75      sc = context->cfa;
      76    else if (((*(unsigned short *) (pc+0) == 0x9300)
      77  	    && (*(unsigned short *) (pc+2)  == 0xc310)
      78  	    && (*(unsigned short *) (pc+4)  == 0x00ad))
      79  	   || (((*(unsigned short *) (pc+0) == 0x9305)
      80  		&& (*(unsigned short *) (pc+2)  == 0xc310)
      81  		&& (*(unsigned short *) (pc+14)  == 0x00ad))))
      82      {
      83        struct rt_sigframe {
      84  	siginfo_t info;
      85  	ucontext_t uc;
      86        } *rt_ = context->cfa;
      87        /* The void * cast is necessary to avoid an aliasing warning.
      88           The aliasing warning is correct, but should not be a problem
      89           because it does not alias anything.  */
      90        sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext;
      91      }
      92    else
      93      return _URC_END_OF_STACK;
      94  
      95    new_cfa = sc->sc_regs[15];
      96    fs->regs.cfa_how = CFA_REG_OFFSET;
      97    fs->regs.cfa_reg = 15;
      98    fs->regs.cfa_offset = new_cfa - (long) context->cfa;
      99  
     100    for (i = 0; i < 15; i++)
     101      {
     102        fs->regs.how[i] = REG_SAVED_OFFSET;
     103        fs->regs.reg[i].loc.offset
     104  	= (long)&(sc->sc_regs[i]) - new_cfa;
     105      }
     106  
     107    fs->regs.how[SH_DWARF_FRAME_PR] = REG_SAVED_OFFSET;
     108    fs->regs.reg[SH_DWARF_FRAME_PR].loc.offset
     109      = (long)&(sc->sc_pr) - new_cfa;
     110    fs->regs.how[SH_DWARF_FRAME_SR] = REG_SAVED_OFFSET;
     111    fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset
     112      = (long)&(sc->sc_sr) - new_cfa;
     113    fs->regs.how[SH_DWARF_FRAME_GBR] = REG_SAVED_OFFSET;
     114    fs->regs.reg[SH_DWARF_FRAME_GBR].loc.offset
     115      = (long)&(sc->sc_gbr) - new_cfa;
     116    fs->regs.how[SH_DWARF_FRAME_MACH] = REG_SAVED_OFFSET;
     117    fs->regs.reg[SH_DWARF_FRAME_MACH].loc.offset
     118      = (long)&(sc->sc_mach) - new_cfa;
     119    fs->regs.how[SH_DWARF_FRAME_MACL] = REG_SAVED_OFFSET;
     120    fs->regs.reg[SH_DWARF_FRAME_MACL].loc.offset
     121      = (long)&(sc->sc_macl) - new_cfa;
     122  
     123  #if defined (__SH3E__) || defined (__SH4__)
     124    r = SH_DWARF_FRAME_FP0;
     125    for (i = 0; i < 16; i++)
     126      {
     127        fs->regs.how[r+i] = REG_SAVED_OFFSET;
     128        fs->regs.reg[r+i].loc.offset
     129  	= (long)&(sc->sc_fpregs[i]) - new_cfa;
     130      }
     131  
     132    r = SH_DWARF_FRAME_XD0;
     133    for (i = 0; i < 8; i++)
     134      {
     135        fs->regs.how[r+i] = REG_SAVED_OFFSET;
     136        fs->regs.reg[r+i].loc.offset
     137  	= (long)&(sc->sc_xfpregs[2*i]) - new_cfa;
     138      }
     139  
     140    fs->regs.how[SH_DWARF_FRAME_FPUL] = REG_SAVED_OFFSET;
     141    fs->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset
     142      = (long)&(sc->sc_fpul) - new_cfa;
     143    fs->regs.how[SH_DWARF_FRAME_FPSCR] = REG_SAVED_OFFSET;
     144    fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset
     145      = (long)&(sc->sc_fpscr) - new_cfa;
     146  #endif
     147  
     148    fs->regs.how[SH_DWARF_FRAME_PC] = REG_SAVED_OFFSET;
     149    fs->regs.reg[SH_DWARF_FRAME_PC].loc.offset
     150      = (long)&(sc->sc_pc) - new_cfa;
     151    fs->retaddr_column = SH_DWARF_FRAME_PC;
     152    fs->signal_frame = 1;
     153    return _URC_NO_REASON;
     154  }
     155  
     156  #endif /* inhibit_libc */