(root)/
gcc-13.2.0/
libgcc/
config/
aarch64/
freebsd-unwind.h
       1  /* DWARF2 EH unwinding support for FreeBSD/ARM64 (aarch64).
       2     Copyright (C) 2017-2023 Free Software Foundation, Inc.
       3     Contributed by John Marino <gnugcc@marino.st>
       4  
       5  This file is part of GCC.
       6  
       7  GCC is free software; you can redistribute it and/or modify
       8  it under the terms of the GNU General Public License as published by
       9  the Free Software Foundation; either version 3, or (at your option)
      10  any later version.
      11  
      12  GCC is distributed in the hope that it will be useful,
      13  but WITHOUT ANY WARRANTY; without even the implied warranty of
      14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15  GNU General Public License for more details.
      16  
      17  Under Section 7 of GPL version 3, you are granted additional
      18  permissions described in the GCC Runtime Library Exception, version
      19  3.1, as published by the Free Software Foundation.
      20  
      21  You should have received a copy of the GNU General Public License and
      22  a copy of the GCC Runtime Library Exception along with this program;
      23  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      24  <http://www.gnu.org/licenses/>.  */
      25  
      26  /* Identify a signal frame, and set the frame state data appropriately.
      27     See unwind-dw2.c for the structs. */
      28  
      29  /* Always include AArch64 unwinder header file.  */
      30  #include "config/aarch64/aarch64-unwind.h"
      31  
      32  #include <sys/types.h>
      33  #include <signal.h>
      34  #include <unistd.h>
      35  #include <sys/ucontext.h>
      36  #include <machine/frame.h>
      37  #include <sys/user.h>
      38  #include <sys/sysctl.h>
      39  
      40  #define REG_NAME(reg)   mc_gpregs.gp_## reg
      41  #define XREG(num)       mc_gpregs.gp_x[num]
      42  #define DARC            __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__
      43  
      44  #define MD_FALLBACK_FRAME_STATE_FOR aarch64_freebsd_fallback_frame_state
      45  
      46  static int
      47  aarch64_outside_sigtramp_range (unsigned char *pc)
      48  {
      49    static int sigtramp_range_determined = 0;
      50    static unsigned char *sigtramp_start, *sigtramp_end;
      51  
      52    if (sigtramp_range_determined == 0)
      53      {
      54        struct kinfo_sigtramp kst = {0};
      55        size_t len = sizeof (kst);
      56        int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP, getpid() };
      57  
      58        sigtramp_range_determined = 1;
      59        if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0)
      60        {
      61          sigtramp_range_determined = 2;
      62          sigtramp_start = kst.ksigtramp_start;
      63          sigtramp_end   = kst.ksigtramp_end;
      64        }
      65      }
      66    if (sigtramp_range_determined < 2)  /* sysctl failed if < 2 */
      67      return 1;
      68  
      69    return (pc < sigtramp_start || pc >= sigtramp_end);
      70  }
      71  
      72  static _Unwind_Reason_Code
      73  aarch64_freebsd_fallback_frame_state
      74  (struct _Unwind_Context *context, _Unwind_FrameState *fs)
      75  {
      76    int n;
      77    struct sigframe *sf;
      78    mcontext_t *sc;
      79    _Unwind_Ptr new_cfa;
      80  
      81    if (aarch64_outside_sigtramp_range(context->ra))
      82      return _URC_END_OF_STACK;
      83  
      84    sf = (struct sigframe *) context->cfa;
      85    sc = &sf->sf_uc.uc_mcontext;
      86  
      87    new_cfa = (_Unwind_Ptr) sc;
      88    fs->regs.cfa_how = CFA_REG_OFFSET;
      89    fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
      90    fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
      91  
      92    for (n = 0; n < 32; n++)
      93      fs->regs.how[n] = REG_SAVED_OFFSET;
      94  
      95    for (n = 0; n < 30; n++)
      96      fs->regs.reg[n].loc.offset = (_Unwind_Ptr) &(sc->XREG(n)) - new_cfa;
      97  
      98    fs->regs.reg[30].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(lr)) - new_cfa;
      99    fs->regs.reg[31].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(sp)) - new_cfa;
     100  
     101    fs->regs.how[DARC] = REG_SAVED_OFFSET;
     102    fs->regs.reg[DARC].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(elr)) - new_cfa;
     103  
     104    fs->retaddr_column = DARC;
     105    fs->signal_frame = 1;
     106  
     107    return _URC_NO_REASON;
     108  }