Home | History | Annotate | Line # | Download | only in i386
dragonfly-unwind.h revision 1.1
      1  1.1  mrg /* DWARF2 EH unwinding support for DragonFly BSD: AMD x86-64 and x86.
      2  1.1  mrg    Copyright (C) 2014-2015 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.1  mrg #include <signal.h>
     32  1.1  mrg #include <sys/ucontext.h>
     33  1.1  mrg #include <machine/sigframe.h>
     34  1.1  mrg 
     35  1.1  mrg 
     36  1.1  mrg #define REG_NAME(reg)	sf_uc.uc_mcontext.mc_## reg
     37  1.1  mrg 
     38  1.1  mrg #ifdef __x86_64__
     39  1.1  mrg #define MD_FALLBACK_FRAME_STATE_FOR x86_64_dragonfly_fallback_frame_state
     40  1.1  mrg 
     41  1.1  mrg 
     42  1.1  mrg static void
     43  1.1  mrg x86_64_sigtramp_range (unsigned char **start, unsigned char **end)
     44  1.1  mrg {
     45  1.1  mrg   unsigned long ps_strings;
     46  1.1  mrg   int mib[2];
     47  1.1  mrg   size_t len;
     48  1.1  mrg 
     49  1.1  mrg   mib[0] = CTL_KERN;
     50  1.1  mrg   mib[1] = KERN_PS_STRINGS;
     51  1.1  mrg   len = sizeof (ps_strings);
     52  1.1  mrg   sysctl (mib, 2, &ps_strings, &len, NULL, 0);
     53  1.1  mrg 
     54  1.1  mrg   *start = (unsigned char *)ps_strings - 32;
     55  1.1  mrg   *end   = (unsigned char *)ps_strings;
     56  1.1  mrg }
     57  1.1  mrg 
     58  1.1  mrg 
     59  1.1  mrg static _Unwind_Reason_Code
     60  1.1  mrg x86_64_dragonfly_fallback_frame_state
     61  1.1  mrg (struct _Unwind_Context *context, _Unwind_FrameState *fs)
     62  1.1  mrg {
     63  1.1  mrg   unsigned char *pc = context->ra;
     64  1.1  mrg   unsigned char *sigtramp_start, *sigtramp_end;
     65  1.1  mrg   struct sigframe *sf;
     66  1.1  mrg   long new_cfa;
     67  1.1  mrg 
     68  1.1  mrg   x86_64_sigtramp_range(&sigtramp_start, &sigtramp_end);
     69  1.1  mrg   if (pc >= sigtramp_end || pc < sigtramp_start)
     70  1.1  mrg     return _URC_END_OF_STACK;
     71  1.1  mrg 
     72  1.1  mrg   sf = (struct sigframe *) context->cfa;
     73  1.1  mrg   new_cfa = sf->REG_NAME(rsp);
     74  1.1  mrg   fs->regs.cfa_how = CFA_REG_OFFSET;
     75  1.1  mrg   /* Register 7 is rsp  */
     76  1.1  mrg   fs->regs.cfa_reg = 7;
     77  1.1  mrg   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
     78  1.1  mrg 
     79  1.1  mrg   /* The SVR4 register numbering macros aren't usable in libgcc.  */
     80  1.1  mrg   fs->regs.reg[0].how = REG_SAVED_OFFSET;
     81  1.1  mrg   fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(rax) - new_cfa;
     82  1.1  mrg   fs->regs.reg[1].how = REG_SAVED_OFFSET;
     83  1.1  mrg   fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(rdx) - new_cfa;
     84  1.1  mrg   fs->regs.reg[2].how = REG_SAVED_OFFSET;
     85  1.1  mrg   fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(rcx) - new_cfa;
     86  1.1  mrg   fs->regs.reg[3].how = REG_SAVED_OFFSET;
     87  1.1  mrg   fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(rbx) - new_cfa;
     88  1.1  mrg   fs->regs.reg[4].how = REG_SAVED_OFFSET;
     89  1.1  mrg   fs->regs.reg[4].loc.offset = (long)&sf->REG_NAME(rsi) - new_cfa;
     90  1.1  mrg   fs->regs.reg[5].how = REG_SAVED_OFFSET;
     91  1.1  mrg   fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(rdi) - new_cfa;
     92  1.1  mrg   fs->regs.reg[6].how = REG_SAVED_OFFSET;
     93  1.1  mrg   fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(rbp) - new_cfa;
     94  1.1  mrg   fs->regs.reg[8].how = REG_SAVED_OFFSET;
     95  1.1  mrg   fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(r8) - new_cfa;
     96  1.1  mrg   fs->regs.reg[9].how = REG_SAVED_OFFSET;
     97  1.1  mrg   fs->regs.reg[9].loc.offset = (long)&sf->REG_NAME(r9) - new_cfa;
     98  1.1  mrg   fs->regs.reg[10].how = REG_SAVED_OFFSET;
     99  1.1  mrg   fs->regs.reg[10].loc.offset = (long)&sf->REG_NAME(r10) - new_cfa;
    100  1.1  mrg   fs->regs.reg[11].how = REG_SAVED_OFFSET;
    101  1.1  mrg   fs->regs.reg[11].loc.offset = (long)&sf->REG_NAME(r11) - new_cfa;
    102  1.1  mrg   fs->regs.reg[12].how = REG_SAVED_OFFSET;
    103  1.1  mrg   fs->regs.reg[12].loc.offset = (long)&sf->REG_NAME(r12) - new_cfa;
    104  1.1  mrg   fs->regs.reg[13].how = REG_SAVED_OFFSET;
    105  1.1  mrg   fs->regs.reg[13].loc.offset = (long)&sf->REG_NAME(r13) - new_cfa;
    106  1.1  mrg   fs->regs.reg[14].how = REG_SAVED_OFFSET;
    107  1.1  mrg   fs->regs.reg[14].loc.offset = (long)&sf->REG_NAME(r14) - new_cfa;
    108  1.1  mrg   fs->regs.reg[15].how = REG_SAVED_OFFSET;
    109  1.1  mrg   fs->regs.reg[15].loc.offset = (long)&sf->REG_NAME(r15) - new_cfa;
    110  1.1  mrg   fs->regs.reg[16].how = REG_SAVED_OFFSET;
    111  1.1  mrg   fs->regs.reg[16].loc.offset = (long)&sf->REG_NAME(rip) - new_cfa;
    112  1.1  mrg   fs->retaddr_column = 16;
    113  1.1  mrg   fs->signal_frame = 1;
    114  1.1  mrg   return _URC_NO_REASON;
    115  1.1  mrg }
    116  1.1  mrg 
    117  1.1  mrg #else /* Next section is for i386  */
    118  1.1  mrg 
    119  1.1  mrg #define MD_FALLBACK_FRAME_STATE_FOR x86_dragonfly_fallback_frame_state
    120  1.1  mrg 
    121  1.1  mrg 
    122  1.1  mrg static void
    123  1.1  mrg x86_sigtramp_range (unsigned char **start, unsigned char **end)
    124  1.1  mrg {
    125  1.1  mrg   unsigned long ps_strings;
    126  1.1  mrg   int mib[2];
    127  1.1  mrg   size_t len;
    128  1.1  mrg 
    129  1.1  mrg   mib[0] = CTL_KERN;
    130  1.1  mrg   mib[1] = KERN_PS_STRINGS;
    131  1.1  mrg   len = sizeof (ps_strings);
    132  1.1  mrg   sysctl (mib, 2, &ps_strings, &len, NULL, 0);
    133  1.1  mrg 
    134  1.1  mrg   *start = (unsigned char *)ps_strings - 128;
    135  1.1  mrg   *end   = (unsigned char *)ps_strings;
    136  1.1  mrg }
    137  1.1  mrg 
    138  1.1  mrg 
    139  1.1  mrg static _Unwind_Reason_Code
    140  1.1  mrg x86_dragonfly_fallback_frame_state
    141  1.1  mrg (struct _Unwind_Context *context, _Unwind_FrameState *fs)
    142  1.1  mrg {
    143  1.1  mrg   unsigned char *pc = context->ra;
    144  1.1  mrg   unsigned char *sigtramp_start, *sigtramp_end;
    145  1.1  mrg   struct sigframe *sf;
    146  1.1  mrg   long new_cfa;
    147  1.1  mrg 
    148  1.1  mrg   x86_sigtramp_range(&sigtramp_start, &sigtramp_end);
    149  1.1  mrg 
    150  1.1  mrg   if (pc >= sigtramp_end || pc < sigtramp_start)
    151  1.1  mrg     return _URC_END_OF_STACK;
    152  1.1  mrg 
    153  1.1  mrg   sf = (struct sigframe *) context->cfa;
    154  1.1  mrg   new_cfa = sf->REG_NAME(esp);
    155  1.1  mrg   fs->regs.cfa_how = CFA_REG_OFFSET;
    156  1.1  mrg   fs->regs.cfa_reg = 4;
    157  1.1  mrg   fs->regs.cfa_offset = new_cfa - (long) context->cfa;
    158  1.1  mrg 
    159  1.1  mrg   /* The SVR4 register numbering macros aren't usable in libgcc.  */
    160  1.1  mrg   fs->regs.reg[0].how = REG_SAVED_OFFSET;
    161  1.1  mrg   fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(eax) - new_cfa;
    162  1.1  mrg   fs->regs.reg[3].how = REG_SAVED_OFFSET;
    163  1.1  mrg   fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(ebx) - new_cfa;
    164  1.1  mrg   fs->regs.reg[1].how = REG_SAVED_OFFSET;
    165  1.1  mrg   fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(ecx) - new_cfa;
    166  1.1  mrg   fs->regs.reg[2].how = REG_SAVED_OFFSET;
    167  1.1  mrg   fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(edx) - new_cfa;
    168  1.1  mrg   fs->regs.reg[6].how = REG_SAVED_OFFSET;
    169  1.1  mrg   fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(esi) - new_cfa;
    170  1.1  mrg   fs->regs.reg[7].how = REG_SAVED_OFFSET;
    171  1.1  mrg   fs->regs.reg[7].loc.offset = (long)&sf->REG_NAME(edi) - new_cfa;
    172  1.1  mrg   fs->regs.reg[5].how = REG_SAVED_OFFSET;
    173  1.1  mrg   fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(ebp) - new_cfa;
    174  1.1  mrg   fs->regs.reg[8].how = REG_SAVED_OFFSET;
    175  1.1  mrg   fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(eip) - new_cfa;
    176  1.1  mrg   fs->retaddr_column = 8;
    177  1.1  mrg   fs->signal_frame = 1;
    178  1.1  mrg   return _URC_NO_REASON;
    179  1.1  mrg }
    180  1.1  mrg #endif /* ifdef __x86_64__  */
    181