1 /* DWARF2 EH unwinding support for DragonFly BSD: AMD x86-64 and x86.
2 Copyright (C) 2014-2016 Free Software Foundation, Inc.
3 Contributed by John Marino <gnugcc@marino.st>
5 This file is part of GCC.
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)
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.
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.
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/>. */
26 /* Do code reading to identify a signal frame, and set the frame
27 state data appropriately. See unwind-dw2.c for the structs. */
29 #include <sys/types.h>
30 #include <sys/sysctl.h>
32 #include <sys/ucontext.h>
33 #include <machine/sigframe.h>
36 #define REG_NAME(reg) sf_uc.uc_mcontext.mc_## reg
39 #define MD_FALLBACK_FRAME_STATE_FOR x86_64_dragonfly_fallback_frame_state
43 x86_64_sigtramp_range (unsigned char **start
, unsigned char **end
)
45 unsigned long ps_strings
;
50 mib
[1] = KERN_PS_STRINGS
;
51 len
= sizeof (ps_strings
);
52 sysctl (mib
, 2, &ps_strings
, &len
, NULL
, 0);
54 *start
= (unsigned char *)ps_strings
- 32;
55 *end
= (unsigned char *)ps_strings
;
59 static _Unwind_Reason_Code
60 x86_64_dragonfly_fallback_frame_state
61 (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
63 unsigned char *pc
= context
->ra
;
64 unsigned char *sigtramp_start
, *sigtramp_end
;
68 x86_64_sigtramp_range(&sigtramp_start
, &sigtramp_end
);
69 if (pc
>= sigtramp_end
|| pc
< sigtramp_start
)
70 return _URC_END_OF_STACK
;
72 sf
= (struct sigframe
*) context
->cfa
;
73 new_cfa
= sf
->REG_NAME(rsp
);
74 fs
->regs
.cfa_how
= CFA_REG_OFFSET
;
75 /* Register 7 is rsp */
77 fs
->regs
.cfa_offset
= new_cfa
- (long) context
->cfa
;
79 /* The SVR4 register numbering macros aren't usable in libgcc. */
80 fs
->regs
.reg
[0].how
= REG_SAVED_OFFSET
;
81 fs
->regs
.reg
[0].loc
.offset
= (long)&sf
->REG_NAME(rax
) - new_cfa
;
82 fs
->regs
.reg
[1].how
= REG_SAVED_OFFSET
;
83 fs
->regs
.reg
[1].loc
.offset
= (long)&sf
->REG_NAME(rdx
) - new_cfa
;
84 fs
->regs
.reg
[2].how
= REG_SAVED_OFFSET
;
85 fs
->regs
.reg
[2].loc
.offset
= (long)&sf
->REG_NAME(rcx
) - new_cfa
;
86 fs
->regs
.reg
[3].how
= REG_SAVED_OFFSET
;
87 fs
->regs
.reg
[3].loc
.offset
= (long)&sf
->REG_NAME(rbx
) - new_cfa
;
88 fs
->regs
.reg
[4].how
= REG_SAVED_OFFSET
;
89 fs
->regs
.reg
[4].loc
.offset
= (long)&sf
->REG_NAME(rsi
) - new_cfa
;
90 fs
->regs
.reg
[5].how
= REG_SAVED_OFFSET
;
91 fs
->regs
.reg
[5].loc
.offset
= (long)&sf
->REG_NAME(rdi
) - new_cfa
;
92 fs
->regs
.reg
[6].how
= REG_SAVED_OFFSET
;
93 fs
->regs
.reg
[6].loc
.offset
= (long)&sf
->REG_NAME(rbp
) - new_cfa
;
94 fs
->regs
.reg
[8].how
= REG_SAVED_OFFSET
;
95 fs
->regs
.reg
[8].loc
.offset
= (long)&sf
->REG_NAME(r8
) - new_cfa
;
96 fs
->regs
.reg
[9].how
= REG_SAVED_OFFSET
;
97 fs
->regs
.reg
[9].loc
.offset
= (long)&sf
->REG_NAME(r9
) - new_cfa
;
98 fs
->regs
.reg
[10].how
= REG_SAVED_OFFSET
;
99 fs
->regs
.reg
[10].loc
.offset
= (long)&sf
->REG_NAME(r10
) - new_cfa
;
100 fs
->regs
.reg
[11].how
= REG_SAVED_OFFSET
;
101 fs
->regs
.reg
[11].loc
.offset
= (long)&sf
->REG_NAME(r11
) - new_cfa
;
102 fs
->regs
.reg
[12].how
= REG_SAVED_OFFSET
;
103 fs
->regs
.reg
[12].loc
.offset
= (long)&sf
->REG_NAME(r12
) - new_cfa
;
104 fs
->regs
.reg
[13].how
= REG_SAVED_OFFSET
;
105 fs
->regs
.reg
[13].loc
.offset
= (long)&sf
->REG_NAME(r13
) - new_cfa
;
106 fs
->regs
.reg
[14].how
= REG_SAVED_OFFSET
;
107 fs
->regs
.reg
[14].loc
.offset
= (long)&sf
->REG_NAME(r14
) - new_cfa
;
108 fs
->regs
.reg
[15].how
= REG_SAVED_OFFSET
;
109 fs
->regs
.reg
[15].loc
.offset
= (long)&sf
->REG_NAME(r15
) - new_cfa
;
110 fs
->regs
.reg
[16].how
= REG_SAVED_OFFSET
;
111 fs
->regs
.reg
[16].loc
.offset
= (long)&sf
->REG_NAME(rip
) - new_cfa
;
112 fs
->retaddr_column
= 16;
113 fs
->signal_frame
= 1;
114 return _URC_NO_REASON
;
117 #else /* Next section is for i386 */
119 #define MD_FALLBACK_FRAME_STATE_FOR x86_dragonfly_fallback_frame_state
123 x86_sigtramp_range (unsigned char **start
, unsigned char **end
)
125 unsigned long ps_strings
;
130 mib
[1] = KERN_PS_STRINGS
;
131 len
= sizeof (ps_strings
);
132 sysctl (mib
, 2, &ps_strings
, &len
, NULL
, 0);
134 *start
= (unsigned char *)ps_strings
- 128;
135 *end
= (unsigned char *)ps_strings
;
139 static _Unwind_Reason_Code
140 x86_dragonfly_fallback_frame_state
141 (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
143 unsigned char *pc
= context
->ra
;
144 unsigned char *sigtramp_start
, *sigtramp_end
;
148 x86_sigtramp_range(&sigtramp_start
, &sigtramp_end
);
150 if (pc
>= sigtramp_end
|| pc
< sigtramp_start
)
151 return _URC_END_OF_STACK
;
153 sf
= (struct sigframe
*) context
->cfa
;
154 new_cfa
= sf
->REG_NAME(esp
);
155 fs
->regs
.cfa_how
= CFA_REG_OFFSET
;
156 fs
->regs
.cfa_reg
= 4;
157 fs
->regs
.cfa_offset
= new_cfa
- (long) context
->cfa
;
159 /* The SVR4 register numbering macros aren't usable in libgcc. */
160 fs
->regs
.reg
[0].how
= REG_SAVED_OFFSET
;
161 fs
->regs
.reg
[0].loc
.offset
= (long)&sf
->REG_NAME(eax
) - new_cfa
;
162 fs
->regs
.reg
[3].how
= REG_SAVED_OFFSET
;
163 fs
->regs
.reg
[3].loc
.offset
= (long)&sf
->REG_NAME(ebx
) - new_cfa
;
164 fs
->regs
.reg
[1].how
= REG_SAVED_OFFSET
;
165 fs
->regs
.reg
[1].loc
.offset
= (long)&sf
->REG_NAME(ecx
) - new_cfa
;
166 fs
->regs
.reg
[2].how
= REG_SAVED_OFFSET
;
167 fs
->regs
.reg
[2].loc
.offset
= (long)&sf
->REG_NAME(edx
) - new_cfa
;
168 fs
->regs
.reg
[6].how
= REG_SAVED_OFFSET
;
169 fs
->regs
.reg
[6].loc
.offset
= (long)&sf
->REG_NAME(esi
) - new_cfa
;
170 fs
->regs
.reg
[7].how
= REG_SAVED_OFFSET
;
171 fs
->regs
.reg
[7].loc
.offset
= (long)&sf
->REG_NAME(edi
) - new_cfa
;
172 fs
->regs
.reg
[5].how
= REG_SAVED_OFFSET
;
173 fs
->regs
.reg
[5].loc
.offset
= (long)&sf
->REG_NAME(ebp
) - new_cfa
;
174 fs
->regs
.reg
[8].how
= REG_SAVED_OFFSET
;
175 fs
->regs
.reg
[8].loc
.offset
= (long)&sf
->REG_NAME(eip
) - new_cfa
;
176 fs
->retaddr_column
= 8;
177 fs
->signal_frame
= 1;
178 return _URC_NO_REASON
;
180 #endif /* ifdef __x86_64__ */