1 /* DWARF2 EH unwinding support for DragonFly BSD: AMD x86-64 and x86. 2 Copyright (C) 2010 John Marino <draco@marino.st> */ 3 4 /* Do code reading to identify a signal frame, and set the frame 5 state data appropriately. See unwind-dw2.c for the structs. */ 6 7 #include <sys/types.h> 8 #include <sys/sysctl.h> 9 #include <signal.h> 10 #include <sys/ucontext.h> 11 #include <machine/sigframe.h> 12 13 14 #define REG_NAME(reg) sf_uc.uc_mcontext.mc_## reg 15 16 #ifdef __x86_64__ 17 #define MD_FALLBACK_FRAME_STATE_FOR x86_64_dragonfly_fallback_frame_state 18 19 20 static void 21 x86_64_sigtramp_range (unsigned char **start, unsigned char **end) 22 { 23 unsigned long ps_strings; 24 int mib[2]; 25 size_t len; 26 27 mib[0] = CTL_KERN; 28 mib[1] = KERN_PS_STRINGS; 29 len = sizeof (ps_strings); 30 sysctl (mib, 2, &ps_strings, &len, NULL, 0); 31 32 *start = (unsigned char *)ps_strings - 32; 33 *end = (unsigned char *)ps_strings; 34 } 35 36 37 static _Unwind_Reason_Code 38 x86_64_dragonfly_fallback_frame_state 39 (struct _Unwind_Context *context, _Unwind_FrameState *fs) 40 { 41 unsigned char *pc = context->ra; 42 unsigned char *sigtramp_start, *sigtramp_end; 43 struct sigframe *sf; 44 long new_cfa; 45 46 x86_64_sigtramp_range(&sigtramp_start, &sigtramp_end); 47 if (pc >= sigtramp_end || pc < sigtramp_start) 48 return _URC_END_OF_STACK; 49 50 sf = (struct sigframe *) context->cfa; 51 new_cfa = sf->REG_NAME(rsp); 52 fs->regs.cfa_how = CFA_REG_OFFSET; 53 /* Register 7 is rsp */ 54 fs->regs.cfa_reg = 7; 55 fs->regs.cfa_offset = new_cfa - (long) context->cfa; 56 57 /* The SVR4 register numbering macros aren't usable in libgcc. */ 58 fs->regs.reg[0].how = REG_SAVED_OFFSET; 59 fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(rax) - new_cfa; 60 fs->regs.reg[1].how = REG_SAVED_OFFSET; 61 fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(rdx) - new_cfa; 62 fs->regs.reg[2].how = REG_SAVED_OFFSET; 63 fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(rcx) - new_cfa; 64 fs->regs.reg[3].how = REG_SAVED_OFFSET; 65 fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(rbx) - new_cfa; 66 fs->regs.reg[4].how = REG_SAVED_OFFSET; 67 fs->regs.reg[4].loc.offset = (long)&sf->REG_NAME(rsi) - new_cfa; 68 fs->regs.reg[5].how = REG_SAVED_OFFSET; 69 fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(rdi) - new_cfa; 70 fs->regs.reg[6].how = REG_SAVED_OFFSET; 71 fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(rbp) - new_cfa; 72 fs->regs.reg[8].how = REG_SAVED_OFFSET; 73 fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(r8) - new_cfa; 74 fs->regs.reg[9].how = REG_SAVED_OFFSET; 75 fs->regs.reg[9].loc.offset = (long)&sf->REG_NAME(r9) - new_cfa; 76 fs->regs.reg[10].how = REG_SAVED_OFFSET; 77 fs->regs.reg[10].loc.offset = (long)&sf->REG_NAME(r10) - new_cfa; 78 fs->regs.reg[11].how = REG_SAVED_OFFSET; 79 fs->regs.reg[11].loc.offset = (long)&sf->REG_NAME(r11) - new_cfa; 80 fs->regs.reg[12].how = REG_SAVED_OFFSET; 81 fs->regs.reg[12].loc.offset = (long)&sf->REG_NAME(r12) - new_cfa; 82 fs->regs.reg[13].how = REG_SAVED_OFFSET; 83 fs->regs.reg[13].loc.offset = (long)&sf->REG_NAME(r13) - new_cfa; 84 fs->regs.reg[14].how = REG_SAVED_OFFSET; 85 fs->regs.reg[14].loc.offset = (long)&sf->REG_NAME(r14) - new_cfa; 86 fs->regs.reg[15].how = REG_SAVED_OFFSET; 87 fs->regs.reg[15].loc.offset = (long)&sf->REG_NAME(r15) - new_cfa; 88 fs->regs.reg[16].how = REG_SAVED_OFFSET; 89 fs->regs.reg[16].loc.offset = (long)&sf->REG_NAME(rip) - new_cfa; 90 fs->retaddr_column = 16; 91 fs->signal_frame = 1; 92 return _URC_NO_REASON; 93 } 94 95 #else /* Next section is for i386 */ 96 97 #define MD_FALLBACK_FRAME_STATE_FOR x86_dragonfly_fallback_frame_state 98 99 100 static void 101 x86_sigtramp_range (unsigned char **start, unsigned char **end) 102 { 103 unsigned long ps_strings; 104 int mib[2]; 105 size_t len; 106 107 mib[0] = CTL_KERN; 108 mib[1] = KERN_PS_STRINGS; 109 len = sizeof (ps_strings); 110 sysctl (mib, 2, &ps_strings, &len, NULL, 0); 111 112 *start = (unsigned char *)ps_strings - 128; 113 *end = (unsigned char *)ps_strings; 114 } 115 116 117 static _Unwind_Reason_Code 118 x86_dragonfly_fallback_frame_state 119 (struct _Unwind_Context *context, _Unwind_FrameState *fs) 120 { 121 unsigned char *pc = context->ra; 122 unsigned char *sigtramp_start, *sigtramp_end; 123 struct sigframe *sf; 124 long new_cfa; 125 126 x86_sigtramp_range(&sigtramp_start, &sigtramp_end); 127 128 if (pc >= sigtramp_end || pc < sigtramp_start) 129 return _URC_END_OF_STACK; 130 131 sf = (struct sigframe *) context->cfa; 132 new_cfa = sf->REG_NAME(esp); 133 fs->regs.cfa_how = CFA_REG_OFFSET; 134 fs->regs.cfa_reg = 4; 135 fs->regs.cfa_offset = new_cfa - (long) context->cfa; 136 137 /* The SVR4 register numbering macros aren't usable in libgcc. */ 138 fs->regs.reg[0].how = REG_SAVED_OFFSET; 139 fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(eax) - new_cfa; 140 fs->regs.reg[3].how = REG_SAVED_OFFSET; 141 fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(ebx) - new_cfa; 142 fs->regs.reg[1].how = REG_SAVED_OFFSET; 143 fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(ecx) - new_cfa; 144 fs->regs.reg[2].how = REG_SAVED_OFFSET; 145 fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(edx) - new_cfa; 146 fs->regs.reg[6].how = REG_SAVED_OFFSET; 147 fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(esi) - new_cfa; 148 fs->regs.reg[7].how = REG_SAVED_OFFSET; 149 fs->regs.reg[7].loc.offset = (long)&sf->REG_NAME(edi) - new_cfa; 150 fs->regs.reg[5].how = REG_SAVED_OFFSET; 151 fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(ebp) - new_cfa; 152 fs->regs.reg[8].how = REG_SAVED_OFFSET; 153 fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(eip) - new_cfa; 154 fs->retaddr_column = 8; 155 fs->signal_frame = 1; 156 return _URC_NO_REASON; 157 } 158 #endif /* ifdef __x86_64__ */ 159