(root)/
gcc-13.2.0/
libgcc/
config/
xtensa/
linux-unwind.h
       1  /* DWARF2 EH unwinding support for Xtensa.
       2     Copyright (C) 2008-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-xtensa.c for the structs.
      27     Don't use this at all if inhibit_libc is used.  */
      28  
      29  #ifndef inhibit_libc
      30  
      31  #include <signal.h>
      32  #include <sys/ucontext.h>
      33  
      34  /* Encoded bytes for Xtensa instructions:
      35  	movi a2, __NR_rt_sigreturn
      36  	syscall
      37  	entry (first byte only)
      38     Some of the bytes are endian-dependent.  */
      39  
      40  #define MOVI_BYTE0 0x22
      41  #define MOVI_BYTE2 225 /* __NR_rt_sigreturn */
      42  #define SYSC_BYTE0 0
      43  #define SYSC_BYTE2 0
      44  
      45  #ifdef __XTENSA_EB__
      46  #define MOVI_BYTE1 0x0a
      47  #define SYSC_BYTE1 0x05
      48  #define ENTRY_BYTE 0x6c
      49  #else
      50  #define MOVI_BYTE1 0xa0
      51  #define SYSC_BYTE1 0x50
      52  #define ENTRY_BYTE 0x36
      53  #endif
      54  
      55  #define MD_FALLBACK_FRAME_STATE_FOR xtensa_fallback_frame_state
      56  
      57  static _Unwind_Reason_Code
      58  xtensa_fallback_frame_state (struct _Unwind_Context *context,
      59  			     _Unwind_FrameState *fs)
      60  {
      61    unsigned char *pc = context->ra;
      62    struct sigcontext *sc;
      63  #if defined(__XTENSA_CALL0_ABI__)
      64    _Unwind_Ptr new_cfa;
      65    int i;
      66  #endif
      67  
      68    struct rt_sigframe {
      69      siginfo_t info;
      70      ucontext_t uc;
      71    } *rt_;
      72  
      73    /* movi a2, __NR_rt_sigreturn; syscall */
      74    if (pc[0] != MOVI_BYTE0
      75        || pc[1] != MOVI_BYTE1
      76        || pc[2] != MOVI_BYTE2
      77        || pc[3] != SYSC_BYTE0
      78        || pc[4] != SYSC_BYTE1
      79        || pc[5] != SYSC_BYTE2)
      80      return _URC_END_OF_STACK;
      81  
      82  #if defined(__XTENSA_WINDOWED_ABI__)
      83    rt_ = context->sp;
      84    sc = &rt_->uc.uc_mcontext;
      85    fs->signal_regs = (_Unwind_Word *) sc->sc_a;
      86  
      87    /* If the signal arrived just before an ENTRY instruction, find the return
      88       address and pretend the signal arrived before executing the CALL.  */
      89    if (*(unsigned char *) sc->sc_pc == ENTRY_BYTE)
      90     {
      91       unsigned callinc = (sc->sc_ps >> 16) & 3;
      92       fs->signal_ra = ((sc->sc_a[callinc << 2] & XTENSA_RA_FIELD_MASK)
      93  		      | context->ra_high_bits) - 3;
      94     }
      95    else
      96      fs->signal_ra = sc->sc_pc;
      97  #elif defined(__XTENSA_CALL0_ABI__)
      98    rt_ = context->cfa;
      99    sc = &rt_->uc.uc_mcontext;
     100  
     101    new_cfa = (_Unwind_Ptr) sc;
     102    fs->regs.cfa_how = CFA_REG_OFFSET;
     103    fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
     104    fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
     105  
     106    for (i = 0; i < 16; i++)
     107      {
     108        fs->regs.how[i] = REG_SAVED_OFFSET;
     109        fs->regs.reg[i].loc.offset = (_Unwind_Ptr) &(sc->sc_a[i]) - new_cfa;
     110      }
     111  
     112    fs->regs.how[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__] =
     113      REG_SAVED_VAL_OFFSET;
     114    fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].loc.offset =
     115      (_Unwind_Ptr) (sc->sc_pc) - new_cfa;
     116    fs->retaddr_column = __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__;
     117  #else
     118  #error Unsupported Xtensa ABI
     119  #endif
     120  
     121    fs->signal_frame = 1;
     122    return _URC_NO_REASON;
     123  }
     124  
     125  
     126  #endif /* ifdef inhibit_libc  */