Home | History | Annotate | Line # | Download | only in sh
      1       1.1  mrg /* DWARF2 EH unwinding support for SH Linux.
      2  1.1.1.13  mrg    Copyright (C) 2004-2024 Free Software Foundation, Inc.
      3       1.1  mrg 
      4       1.1  mrg This file is part of GCC.
      5       1.1  mrg 
      6       1.1  mrg GCC is free software; you can redistribute it and/or modify
      7       1.1  mrg it under the terms of the GNU General Public License as published by
      8       1.1  mrg the Free Software Foundation; either version 3, or (at your option)
      9       1.1  mrg any later version.
     10       1.1  mrg 
     11       1.1  mrg GCC is distributed in the hope that it will be useful,
     12       1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     13       1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14       1.1  mrg GNU General Public License for more details.
     15       1.1  mrg 
     16       1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     17       1.1  mrg permissions described in the GCC Runtime Library Exception, version
     18       1.1  mrg 3.1, as published by the Free Software Foundation.
     19       1.1  mrg 
     20       1.1  mrg You should have received a copy of the GNU General Public License and
     21       1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     22       1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23       1.1  mrg <http://www.gnu.org/licenses/>.  */
     24       1.1  mrg 
     25       1.1  mrg 
     26       1.1  mrg /* Do code reading to identify a signal frame, and set the frame
     27       1.1  mrg    state data appropriately.  See unwind-dw2.c for the structs.
     28       1.1  mrg    Don't use this at all if inhibit_libc is used.  */
     29       1.1  mrg 
     30       1.1  mrg #ifndef inhibit_libc
     31       1.1  mrg 
     32       1.1  mrg #include <signal.h>
     33       1.1  mrg #include <sys/ucontext.h>
     34       1.1  mrg #include "insn-constants.h"
     35       1.1  mrg 
     36       1.1  mrg #define SH_DWARF_FRAME_GP0	0
     37       1.1  mrg #define SH_DWARF_FRAME_FP0	25
     38       1.1  mrg #define SH_DWARF_FRAME_XD0	87
     39       1.1  mrg #define SH_DWARF_FRAME_PR	17
     40       1.1  mrg #define SH_DWARF_FRAME_GBR	18
     41       1.1  mrg #define SH_DWARF_FRAME_MACH	20
     42       1.1  mrg #define SH_DWARF_FRAME_MACL	21
     43       1.1  mrg #define SH_DWARF_FRAME_PC	16
     44       1.1  mrg #define SH_DWARF_FRAME_SR	22
     45       1.1  mrg #define SH_DWARF_FRAME_FPUL	23
     46       1.1  mrg #define SH_DWARF_FRAME_FPSCR	24
     47       1.1  mrg 
     48       1.1  mrg #define MD_FALLBACK_FRAME_STATE_FOR sh_fallback_frame_state
     49       1.1  mrg 
     50       1.1  mrg static _Unwind_Reason_Code
     51       1.1  mrg sh_fallback_frame_state (struct _Unwind_Context *context,
     52       1.1  mrg 			 _Unwind_FrameState *fs)
     53       1.1  mrg {
     54       1.1  mrg   unsigned char *pc = context->ra;
     55       1.1  mrg   struct sigcontext *sc;
     56       1.1  mrg   long new_cfa;
     57       1.1  mrg   int i;
     58       1.1  mrg #if defined (__SH3E__) || defined (__SH4__)
     59       1.1  mrg   int r;
     60       1.1  mrg #endif
     61       1.1  mrg 
     62       1.1  mrg   /* mov.w 1f,r3; trapa #0x10; 1: .short 0x77  (sigreturn)  */
     63       1.1  mrg   /* mov.w 1f,r3; trapa #0x10; 1: .short 0xad  (rt_sigreturn)  */
     64       1.1  mrg   /* Newer kernel uses pad instructions to avoid an SH-4 core bug.  */
     65       1.1  mrg   /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;
     66       1.1  mrg      or r0,r0; 1: .short 0x77  (sigreturn)  */
     67       1.1  mrg   /* mov.w 1f,r3; trapa #0x10; or r0,r0; or r0,r0; or r0,r0; or r0,r0;
     68       1.1  mrg      or r0,r0; 1: .short 0xad  (rt_sigreturn)  */
     69       1.1  mrg   if (((*(unsigned short *) (pc+0)  == 0x9300)
     70       1.1  mrg        && (*(unsigned short *) (pc+2)  == 0xc310)
     71       1.1  mrg        && (*(unsigned short *) (pc+4)  == 0x0077))
     72       1.1  mrg       || (((*(unsigned short *) (pc+0)  == 0x9305)
     73       1.1  mrg 	   && (*(unsigned short *) (pc+2)  == 0xc310)
     74       1.1  mrg 	   && (*(unsigned short *) (pc+14)  == 0x0077))))
     75       1.1  mrg     sc = context->cfa;
     76       1.1  mrg   else if (((*(unsigned short *) (pc+0) == 0x9300)
     77       1.1  mrg 	    && (*(unsigned short *) (pc+2)  == 0xc310)
     78       1.1  mrg 	    && (*(unsigned short *) (pc+4)  == 0x00ad))
     79       1.1  mrg 	   || (((*(unsigned short *) (pc+0) == 0x9305)
     80       1.1  mrg 		&& (*(unsigned short *) (pc+2)  == 0xc310)
     81       1.1  mrg 		&& (*(unsigned short *) (pc+14)  == 0x00ad))))
     82       1.1  mrg     {
     83       1.1  mrg       struct rt_sigframe {
     84       1.1  mrg 	siginfo_t info;
     85   1.1.1.5  mrg 	ucontext_t uc;
     86       1.1  mrg       } *rt_ = context->cfa;
     87       1.1  mrg       /* The void * cast is necessary to avoid an aliasing warning.
     88       1.1  mrg          The aliasing warning is correct, but should not be a problem
     89       1.1  mrg          because it does not alias anything.  */
     90       1.1  mrg       sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext;
     91       1.1  mrg     }
     92       1.1  mrg   else
     93       1.1  mrg     return _URC_END_OF_STACK;
     94       1.1  mrg 
     95       1.1  mrg   new_cfa = sc->sc_regs[15];
     96       1.1  mrg   fs->regs.cfa_how = CFA_REG_OFFSET;
     97       1.1  mrg   fs->regs.cfa_reg = 15;
     98       1.1  mrg   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
     99       1.1  mrg 
    100       1.1  mrg   for (i = 0; i < 15; i++)
    101       1.1  mrg     {
    102  1.1.1.13  mrg       fs->regs.how[i] = REG_SAVED_OFFSET;
    103       1.1  mrg       fs->regs.reg[i].loc.offset
    104       1.1  mrg 	= (long)&(sc->sc_regs[i]) - new_cfa;
    105       1.1  mrg     }
    106       1.1  mrg 
    107  1.1.1.13  mrg   fs->regs.how[SH_DWARF_FRAME_PR] = REG_SAVED_OFFSET;
    108       1.1  mrg   fs->regs.reg[SH_DWARF_FRAME_PR].loc.offset
    109       1.1  mrg     = (long)&(sc->sc_pr) - new_cfa;
    110  1.1.1.13  mrg   fs->regs.how[SH_DWARF_FRAME_SR] = REG_SAVED_OFFSET;
    111       1.1  mrg   fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset
    112       1.1  mrg     = (long)&(sc->sc_sr) - new_cfa;
    113  1.1.1.13  mrg   fs->regs.how[SH_DWARF_FRAME_GBR] = REG_SAVED_OFFSET;
    114       1.1  mrg   fs->regs.reg[SH_DWARF_FRAME_GBR].loc.offset
    115       1.1  mrg     = (long)&(sc->sc_gbr) - new_cfa;
    116  1.1.1.13  mrg   fs->regs.how[SH_DWARF_FRAME_MACH] = REG_SAVED_OFFSET;
    117       1.1  mrg   fs->regs.reg[SH_DWARF_FRAME_MACH].loc.offset
    118       1.1  mrg     = (long)&(sc->sc_mach) - new_cfa;
    119  1.1.1.13  mrg   fs->regs.how[SH_DWARF_FRAME_MACL] = REG_SAVED_OFFSET;
    120       1.1  mrg   fs->regs.reg[SH_DWARF_FRAME_MACL].loc.offset
    121       1.1  mrg     = (long)&(sc->sc_macl) - new_cfa;
    122       1.1  mrg 
    123       1.1  mrg #if defined (__SH3E__) || defined (__SH4__)
    124       1.1  mrg   r = SH_DWARF_FRAME_FP0;
    125       1.1  mrg   for (i = 0; i < 16; i++)
    126       1.1  mrg     {
    127  1.1.1.13  mrg       fs->regs.how[r+i] = REG_SAVED_OFFSET;
    128       1.1  mrg       fs->regs.reg[r+i].loc.offset
    129       1.1  mrg 	= (long)&(sc->sc_fpregs[i]) - new_cfa;
    130       1.1  mrg     }
    131       1.1  mrg 
    132       1.1  mrg   r = SH_DWARF_FRAME_XD0;
    133       1.1  mrg   for (i = 0; i < 8; i++)
    134       1.1  mrg     {
    135  1.1.1.13  mrg       fs->regs.how[r+i] = REG_SAVED_OFFSET;
    136       1.1  mrg       fs->regs.reg[r+i].loc.offset
    137       1.1  mrg 	= (long)&(sc->sc_xfpregs[2*i]) - new_cfa;
    138       1.1  mrg     }
    139       1.1  mrg 
    140  1.1.1.13  mrg   fs->regs.how[SH_DWARF_FRAME_FPUL] = REG_SAVED_OFFSET;
    141       1.1  mrg   fs->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset
    142       1.1  mrg     = (long)&(sc->sc_fpul) - new_cfa;
    143  1.1.1.13  mrg   fs->regs.how[SH_DWARF_FRAME_FPSCR] = REG_SAVED_OFFSET;
    144       1.1  mrg   fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset
    145       1.1  mrg     = (long)&(sc->sc_fpscr) - new_cfa;
    146       1.1  mrg #endif
    147       1.1  mrg 
    148  1.1.1.13  mrg   fs->regs.how[SH_DWARF_FRAME_PC] = REG_SAVED_OFFSET;
    149       1.1  mrg   fs->regs.reg[SH_DWARF_FRAME_PC].loc.offset
    150       1.1  mrg     = (long)&(sc->sc_pc) - new_cfa;
    151       1.1  mrg   fs->retaddr_column = SH_DWARF_FRAME_PC;
    152       1.1  mrg   fs->signal_frame = 1;
    153       1.1  mrg   return _URC_NO_REASON;
    154       1.1  mrg }
    155       1.1  mrg 
    156       1.1  mrg #endif /* inhibit_libc */
    157