(root)/
gcc-13.2.0/
libgcc/
config/
i386/
dragonfly-unwind.h
       1  /* DWARF2 EH unwinding support for DragonFly BSD: AMD x86-64 and x86.
       2     Copyright (C) 2014-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  /* Do code reading to identify a signal frame, and set the frame
      27     state data appropriately.  See unwind-dw2.c for the structs. */
      28  
      29  #include <sys/types.h>
      30  #include <sys/sysctl.h>
      31  #include <sys/param.h>
      32  #include <signal.h>
      33  #include <sys/ucontext.h>
      34  #include <machine/sigframe.h>
      35  #if __DragonFly_version > 400800
      36  #include <sys/kinfo.h>
      37  #endif
      38  
      39  
      40  #define REG_NAME(reg)	sf_uc.uc_mcontext.mc_## reg
      41  
      42  #ifdef __x86_64__
      43  #define MD_FALLBACK_FRAME_STATE_FOR x86_64_dragonfly_fallback_frame_state
      44  
      45  
      46  static int
      47  x86_64_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  #if __DragonFly_version > 400800
      55        struct kinfo_sigtramp kst = {0};
      56        size_t len = sizeof (kst);
      57        int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP };
      58  
      59        sigtramp_range_determined = 1;
      60        if (sysctl (mib, 3, &kst, &len, NULL, 0) == 0)
      61        {
      62          sigtramp_range_determined = 2;
      63          sigtramp_start = kst.ksigtramp_start;
      64          sigtramp_end   = kst.ksigtramp_end;
      65        }
      66  #else
      67        unsigned long ps_strings;
      68        size_t len = sizeof (ps_strings);
      69        int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
      70  
      71        sigtramp_range_determined = 1;
      72        if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
      73        {
      74          sigtramp_range_determined = 2;
      75          sigtramp_start = (unsigned char *)ps_strings - 32;
      76          sigtramp_end   = (unsigned char *)ps_strings;
      77        }
      78  #endif
      79      }
      80    if (sigtramp_range_determined < 2)  /* sysctl failed if < 2 */
      81      return 1;
      82  
      83    return (pc < sigtramp_start || pc >= sigtramp_end );
      84  }
      85  
      86  
      87  static _Unwind_Reason_Code
      88  x86_64_dragonfly_fallback_frame_state
      89  (struct _Unwind_Context *context, _Unwind_FrameState *fs)
      90  {
      91    struct sigframe *sf;
      92    long new_cfa;
      93  
      94    if (x86_64_outside_sigtramp_range(context->ra))
      95      return _URC_END_OF_STACK;
      96  
      97    sf = (struct sigframe *) context->cfa;
      98    new_cfa = sf->REG_NAME(rsp);
      99    fs->regs.cfa_how = CFA_REG_OFFSET;
     100    /* Register 7 is rsp  */
     101    fs->regs.cfa_reg = 7;
     102    fs->regs.cfa_offset = new_cfa - (long) context->cfa;
     103  
     104    /* The SVR4 register numbering macros aren't usable in libgcc.  */
     105    fs->regs.how[0] = REG_SAVED_OFFSET;
     106    fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(rax) - new_cfa;
     107    fs->regs.how[1] = REG_SAVED_OFFSET;
     108    fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(rdx) - new_cfa;
     109    fs->regs.how[2] = REG_SAVED_OFFSET;
     110    fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(rcx) - new_cfa;
     111    fs->regs.how[3] = REG_SAVED_OFFSET;
     112    fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(rbx) - new_cfa;
     113    fs->regs.how[4] = REG_SAVED_OFFSET;
     114    fs->regs.reg[4].loc.offset = (long)&sf->REG_NAME(rsi) - new_cfa;
     115    fs->regs.how[5] = REG_SAVED_OFFSET;
     116    fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(rdi) - new_cfa;
     117    fs->regs.how[6] = REG_SAVED_OFFSET;
     118    fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(rbp) - new_cfa;
     119    fs->regs.how[8] = REG_SAVED_OFFSET;
     120    fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(r8) - new_cfa;
     121    fs->regs.how[9] = REG_SAVED_OFFSET;
     122    fs->regs.reg[9].loc.offset = (long)&sf->REG_NAME(r9) - new_cfa;
     123    fs->regs.how[10] = REG_SAVED_OFFSET;
     124    fs->regs.reg[10].loc.offset = (long)&sf->REG_NAME(r10) - new_cfa;
     125    fs->regs.how[11] = REG_SAVED_OFFSET;
     126    fs->regs.reg[11].loc.offset = (long)&sf->REG_NAME(r11) - new_cfa;
     127    fs->regs.how[12] = REG_SAVED_OFFSET;
     128    fs->regs.reg[12].loc.offset = (long)&sf->REG_NAME(r12) - new_cfa;
     129    fs->regs.how[13] = REG_SAVED_OFFSET;
     130    fs->regs.reg[13].loc.offset = (long)&sf->REG_NAME(r13) - new_cfa;
     131    fs->regs.how[14] = REG_SAVED_OFFSET;
     132    fs->regs.reg[14].loc.offset = (long)&sf->REG_NAME(r14) - new_cfa;
     133    fs->regs.how[15] = REG_SAVED_OFFSET;
     134    fs->regs.reg[15].loc.offset = (long)&sf->REG_NAME(r15) - new_cfa;
     135    fs->regs.how[16] = REG_SAVED_OFFSET;
     136    fs->regs.reg[16].loc.offset = (long)&sf->REG_NAME(rip) - new_cfa;
     137    fs->retaddr_column = 16;
     138    fs->signal_frame = 1;
     139    return _URC_NO_REASON;
     140  }
     141  
     142  #else /* Next section is for i386  */
     143  
     144  #define MD_FALLBACK_FRAME_STATE_FOR x86_dragonfly_fallback_frame_state
     145  
     146  
     147  static void
     148  x86_sigtramp_range (unsigned char **start, unsigned char **end)
     149  {
     150    unsigned long ps_strings;
     151    int mib[2];
     152    size_t len;
     153  
     154    mib[0] = CTL_KERN;
     155    mib[1] = KERN_PS_STRINGS;
     156    len = sizeof (ps_strings);
     157    sysctl (mib, 2, &ps_strings, &len, NULL, 0);
     158  
     159    *start = (unsigned char *)ps_strings - 128;
     160    *end   = (unsigned char *)ps_strings;
     161  }
     162  
     163  
     164  static _Unwind_Reason_Code
     165  x86_dragonfly_fallback_frame_state
     166  (struct _Unwind_Context *context, _Unwind_FrameState *fs)
     167  {
     168    unsigned char *pc = context->ra;
     169    unsigned char *sigtramp_start, *sigtramp_end;
     170    struct sigframe *sf;
     171    long new_cfa;
     172  
     173    x86_sigtramp_range(&sigtramp_start, &sigtramp_end);
     174  
     175    if (pc >= sigtramp_end || pc < sigtramp_start)
     176      return _URC_END_OF_STACK;
     177  
     178    sf = (struct sigframe *) context->cfa;
     179    new_cfa = sf->REG_NAME(esp);
     180    fs->regs.cfa_how = CFA_REG_OFFSET;
     181    fs->regs.cfa_reg = 4;
     182    fs->regs.cfa_offset = new_cfa - (long) context->cfa;
     183  
     184    /* The SVR4 register numbering macros aren't usable in libgcc.  */
     185    fs->regs.how[0] = REG_SAVED_OFFSET;
     186    fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(eax) - new_cfa;
     187    fs->regs.how[3] = REG_SAVED_OFFSET;
     188    fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(ebx) - new_cfa;
     189    fs->regs.how[1] = REG_SAVED_OFFSET;
     190    fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(ecx) - new_cfa;
     191    fs->regs.how[2] = REG_SAVED_OFFSET;
     192    fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(edx) - new_cfa;
     193    fs->regs.how[6] = REG_SAVED_OFFSET;
     194    fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(esi) - new_cfa;
     195    fs->regs.how[7] = REG_SAVED_OFFSET;
     196    fs->regs.reg[7].loc.offset = (long)&sf->REG_NAME(edi) - new_cfa;
     197    fs->regs.how[5] = REG_SAVED_OFFSET;
     198    fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(ebp) - new_cfa;
     199    fs->regs.how[8] = REG_SAVED_OFFSET;
     200    fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(eip) - new_cfa;
     201    fs->retaddr_column = 8;
     202    fs->signal_frame = 1;
     203    return _URC_NO_REASON;
     204  }
     205  #endif /* ifdef __x86_64__  */