Home | History | Annotate | Line # | Download | only in i386
dragonfly-unwind.h revision 1.3
      1  1.1  mrg /* DWARF2 EH unwinding support for DragonFly BSD: AMD x86-64 and x86.
      2  1.3  mrg    Copyright (C) 2014-2017 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by John Marino <gnugcc (at) marino.st>
      4  1.1  mrg 
      5  1.1  mrg This file is part of GCC.
      6  1.1  mrg 
      7  1.1  mrg GCC is free software; you can redistribute it and/or modify
      8  1.1  mrg it under the terms of the GNU General Public License as published by
      9  1.1  mrg the Free Software Foundation; either version 3, or (at your option)
     10  1.1  mrg any later version.
     11  1.1  mrg 
     12  1.1  mrg GCC is distributed in the hope that it will be useful,
     13  1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  mrg GNU General Public License for more details.
     16  1.1  mrg 
     17  1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     18  1.1  mrg permissions described in the GCC Runtime Library Exception, version
     19  1.1  mrg 3.1, as published by the Free Software Foundation.
     20  1.1  mrg 
     21  1.1  mrg You should have received a copy of the GNU General Public License and
     22  1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     23  1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24  1.1  mrg <http://www.gnu.org/licenses/>.  */
     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 
     29  1.1  mrg #include <sys/types.h>
     30  1.1  mrg #include <sys/sysctl.h>
     31  1.3  mrg #include <sys/param.h>
     32  1.1  mrg #include <signal.h>
     33  1.1  mrg #include <sys/ucontext.h>
     34  1.1  mrg #include <machine/sigframe.h>
     35  1.3  mrg #if __DragonFly_version > 400800
     36  1.3  mrg #include <sys/kinfo.h>
     37  1.3  mrg #endif
     38  1.1  mrg 
     39  1.1  mrg 
     40  1.1  mrg #define REG_NAME(reg)	sf_uc.uc_mcontext.mc_## reg
     41  1.1  mrg 
     42  1.1  mrg #ifdef __x86_64__
     43  1.1  mrg #define MD_FALLBACK_FRAME_STATE_FOR x86_64_dragonfly_fallback_frame_state
     44  1.1  mrg 
     45  1.1  mrg 
     46  1.3  mrg static int
     47  1.3  mrg x86_64_outside_sigtramp_range (unsigned char *pc)
     48  1.1  mrg {
     49  1.3  mrg   static int sigtramp_range_determined = 0;
     50  1.3  mrg   static unsigned char *sigtramp_start, *sigtramp_end;
     51  1.1  mrg 
     52  1.3  mrg   if (sigtramp_range_determined == 0)
     53  1.3  mrg     {
     54  1.3  mrg #if __DragonFly_version > 400800
     55  1.3  mrg       struct kinfo_sigtramp kst = {0};
     56  1.3  mrg       size_t len = sizeof (kst);
     57  1.3  mrg       int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP };
     58  1.3  mrg 
     59  1.3  mrg       sigtramp_range_determined = 1;
     60  1.3  mrg       if (sysctl (mib, 3, &kst, &len, NULL, 0) == 0)
     61  1.3  mrg       {
     62  1.3  mrg         sigtramp_range_determined = 2;
     63  1.3  mrg         sigtramp_start = kst.ksigtramp_start;
     64  1.3  mrg         sigtramp_end   = kst.ksigtramp_end;
     65  1.3  mrg       }
     66  1.3  mrg #else
     67  1.3  mrg       unsigned long ps_strings;
     68  1.3  mrg       size_t len = sizeof (ps_strings);
     69  1.3  mrg       int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
     70  1.3  mrg 
     71  1.3  mrg       sigtramp_range_determined = 1;
     72  1.3  mrg       if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
     73  1.3  mrg       {
     74  1.3  mrg         sigtramp_range_determined = 2;
     75  1.3  mrg         sigtramp_start = (unsigned char *)ps_strings - 32;
     76  1.3  mrg         sigtramp_end   = (unsigned char *)ps_strings;
     77  1.3  mrg       }
     78  1.3  mrg #endif
     79  1.3  mrg     }
     80  1.3  mrg   if (sigtramp_range_determined < 2)  /* sysctl failed if < 2 */
     81  1.3  mrg     return 1;
     82  1.1  mrg 
     83  1.3  mrg   return (pc < sigtramp_start || pc >= sigtramp_end );
     84  1.1  mrg }
     85  1.1  mrg 
     86  1.1  mrg 
     87  1.1  mrg static _Unwind_Reason_Code
     88  1.1  mrg x86_64_dragonfly_fallback_frame_state
     89  1.1  mrg (struct _Unwind_Context *context, _Unwind_FrameState *fs)
     90  1.1  mrg {
     91  1.1  mrg   struct sigframe *sf;
     92  1.1  mrg   long new_cfa;
     93  1.1  mrg 
     94  1.3  mrg   if (x86_64_outside_sigtramp_range(context->ra))
     95  1.1  mrg     return _URC_END_OF_STACK;
     96  1.1  mrg 
     97  1.1  mrg   sf = (struct sigframe *) context->cfa;
     98  1.1  mrg   new_cfa = sf->REG_NAME(rsp);
     99  1.1  mrg   fs->regs.cfa_how = CFA_REG_OFFSET;
    100  1.1  mrg   /* Register 7 is rsp  */
    101  1.1  mrg   fs->regs.cfa_reg = 7;
    102  1.1  mrg   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
    103  1.1  mrg 
    104  1.1  mrg   /* The SVR4 register numbering macros aren't usable in libgcc.  */
    105  1.1  mrg   fs->regs.reg[0].how = REG_SAVED_OFFSET;
    106  1.1  mrg   fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(rax) - new_cfa;
    107  1.1  mrg   fs->regs.reg[1].how = REG_SAVED_OFFSET;
    108  1.1  mrg   fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(rdx) - new_cfa;
    109  1.1  mrg   fs->regs.reg[2].how = REG_SAVED_OFFSET;
    110  1.1  mrg   fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(rcx) - new_cfa;
    111  1.1  mrg   fs->regs.reg[3].how = REG_SAVED_OFFSET;
    112  1.1  mrg   fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(rbx) - new_cfa;
    113  1.1  mrg   fs->regs.reg[4].how = REG_SAVED_OFFSET;
    114  1.1  mrg   fs->regs.reg[4].loc.offset = (long)&sf->REG_NAME(rsi) - new_cfa;
    115  1.1  mrg   fs->regs.reg[5].how = REG_SAVED_OFFSET;
    116  1.1  mrg   fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(rdi) - new_cfa;
    117  1.1  mrg   fs->regs.reg[6].how = REG_SAVED_OFFSET;
    118  1.1  mrg   fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(rbp) - new_cfa;
    119  1.1  mrg   fs->regs.reg[8].how = REG_SAVED_OFFSET;
    120  1.1  mrg   fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(r8) - new_cfa;
    121  1.1  mrg   fs->regs.reg[9].how = REG_SAVED_OFFSET;
    122  1.1  mrg   fs->regs.reg[9].loc.offset = (long)&sf->REG_NAME(r9) - new_cfa;
    123  1.1  mrg   fs->regs.reg[10].how = REG_SAVED_OFFSET;
    124  1.1  mrg   fs->regs.reg[10].loc.offset = (long)&sf->REG_NAME(r10) - new_cfa;
    125  1.1  mrg   fs->regs.reg[11].how = REG_SAVED_OFFSET;
    126  1.1  mrg   fs->regs.reg[11].loc.offset = (long)&sf->REG_NAME(r11) - new_cfa;
    127  1.1  mrg   fs->regs.reg[12].how = REG_SAVED_OFFSET;
    128  1.1  mrg   fs->regs.reg[12].loc.offset = (long)&sf->REG_NAME(r12) - new_cfa;
    129  1.1  mrg   fs->regs.reg[13].how = REG_SAVED_OFFSET;
    130  1.1  mrg   fs->regs.reg[13].loc.offset = (long)&sf->REG_NAME(r13) - new_cfa;
    131  1.1  mrg   fs->regs.reg[14].how = REG_SAVED_OFFSET;
    132  1.1  mrg   fs->regs.reg[14].loc.offset = (long)&sf->REG_NAME(r14) - new_cfa;
    133  1.1  mrg   fs->regs.reg[15].how = REG_SAVED_OFFSET;
    134  1.1  mrg   fs->regs.reg[15].loc.offset = (long)&sf->REG_NAME(r15) - new_cfa;
    135  1.1  mrg   fs->regs.reg[16].how = REG_SAVED_OFFSET;
    136  1.1  mrg   fs->regs.reg[16].loc.offset = (long)&sf->REG_NAME(rip) - new_cfa;
    137  1.1  mrg   fs->retaddr_column = 16;
    138  1.1  mrg   fs->signal_frame = 1;
    139  1.1  mrg   return _URC_NO_REASON;
    140  1.1  mrg }
    141  1.1  mrg 
    142  1.1  mrg #else /* Next section is for i386  */
    143  1.1  mrg 
    144  1.1  mrg #define MD_FALLBACK_FRAME_STATE_FOR x86_dragonfly_fallback_frame_state
    145  1.1  mrg 
    146  1.1  mrg 
    147  1.1  mrg static void
    148  1.1  mrg x86_sigtramp_range (unsigned char **start, unsigned char **end)
    149  1.1  mrg {
    150  1.1  mrg   unsigned long ps_strings;
    151  1.1  mrg   int mib[2];
    152  1.1  mrg   size_t len;
    153  1.1  mrg 
    154  1.1  mrg   mib[0] = CTL_KERN;
    155  1.1  mrg   mib[1] = KERN_PS_STRINGS;
    156  1.1  mrg   len = sizeof (ps_strings);
    157  1.1  mrg   sysctl (mib, 2, &ps_strings, &len, NULL, 0);
    158  1.1  mrg 
    159  1.1  mrg   *start = (unsigned char *)ps_strings - 128;
    160  1.1  mrg   *end   = (unsigned char *)ps_strings;
    161  1.1  mrg }
    162  1.1  mrg 
    163  1.1  mrg 
    164  1.1  mrg static _Unwind_Reason_Code
    165  1.1  mrg x86_dragonfly_fallback_frame_state
    166  1.1  mrg (struct _Unwind_Context *context, _Unwind_FrameState *fs)
    167  1.1  mrg {
    168  1.1  mrg   unsigned char *pc = context->ra;
    169  1.1  mrg   unsigned char *sigtramp_start, *sigtramp_end;
    170  1.1  mrg   struct sigframe *sf;
    171  1.1  mrg   long new_cfa;
    172  1.1  mrg 
    173  1.1  mrg   x86_sigtramp_range(&sigtramp_start, &sigtramp_end);
    174  1.1  mrg 
    175  1.1  mrg   if (pc >= sigtramp_end || pc < sigtramp_start)
    176  1.1  mrg     return _URC_END_OF_STACK;
    177  1.1  mrg 
    178  1.1  mrg   sf = (struct sigframe *) context->cfa;
    179  1.1  mrg   new_cfa = sf->REG_NAME(esp);
    180  1.1  mrg   fs->regs.cfa_how = CFA_REG_OFFSET;
    181  1.1  mrg   fs->regs.cfa_reg = 4;
    182  1.1  mrg   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
    183  1.1  mrg 
    184  1.1  mrg   /* The SVR4 register numbering macros aren't usable in libgcc.  */
    185  1.1  mrg   fs->regs.reg[0].how = REG_SAVED_OFFSET;
    186  1.1  mrg   fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(eax) - new_cfa;
    187  1.1  mrg   fs->regs.reg[3].how = REG_SAVED_OFFSET;
    188  1.1  mrg   fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(ebx) - new_cfa;
    189  1.1  mrg   fs->regs.reg[1].how = REG_SAVED_OFFSET;
    190  1.1  mrg   fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(ecx) - new_cfa;
    191  1.1  mrg   fs->regs.reg[2].how = REG_SAVED_OFFSET;
    192  1.1  mrg   fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(edx) - new_cfa;
    193  1.1  mrg   fs->regs.reg[6].how = REG_SAVED_OFFSET;
    194  1.1  mrg   fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(esi) - new_cfa;
    195  1.1  mrg   fs->regs.reg[7].how = REG_SAVED_OFFSET;
    196  1.1  mrg   fs->regs.reg[7].loc.offset = (long)&sf->REG_NAME(edi) - new_cfa;
    197  1.1  mrg   fs->regs.reg[5].how = REG_SAVED_OFFSET;
    198  1.1  mrg   fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(ebp) - new_cfa;
    199  1.1  mrg   fs->regs.reg[8].how = REG_SAVED_OFFSET;
    200  1.1  mrg   fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(eip) - new_cfa;
    201  1.1  mrg   fs->retaddr_column = 8;
    202  1.1  mrg   fs->signal_frame = 1;
    203  1.1  mrg   return _URC_NO_REASON;
    204  1.1  mrg }
    205  1.1  mrg #endif /* ifdef __x86_64__  */
    206