dragonfly-unwind.h revision 1.1.1.2
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>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see 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 <signal.h>
32#include <sys/ucontext.h>
33#include <machine/sigframe.h>
34
35
36#define REG_NAME(reg)	sf_uc.uc_mcontext.mc_## reg
37
38#ifdef __x86_64__
39#define MD_FALLBACK_FRAME_STATE_FOR x86_64_dragonfly_fallback_frame_state
40
41
42static void
43x86_64_sigtramp_range (unsigned char **start, unsigned char **end)
44{
45  unsigned long ps_strings;
46  int mib[2];
47  size_t len;
48
49  mib[0] = CTL_KERN;
50  mib[1] = KERN_PS_STRINGS;
51  len = sizeof (ps_strings);
52  sysctl (mib, 2, &ps_strings, &len, NULL, 0);
53
54  *start = (unsigned char *)ps_strings - 32;
55  *end   = (unsigned char *)ps_strings;
56}
57
58
59static _Unwind_Reason_Code
60x86_64_dragonfly_fallback_frame_state
61(struct _Unwind_Context *context, _Unwind_FrameState *fs)
62{
63  unsigned char *pc = context->ra;
64  unsigned char *sigtramp_start, *sigtramp_end;
65  struct sigframe *sf;
66  long new_cfa;
67
68  x86_64_sigtramp_range(&sigtramp_start, &sigtramp_end);
69  if (pc >= sigtramp_end || pc < sigtramp_start)
70    return _URC_END_OF_STACK;
71
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  */
76  fs->regs.cfa_reg = 7;
77  fs->regs.cfa_offset = new_cfa - (long) context->cfa;
78
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;
115}
116
117#else /* Next section is for i386  */
118
119#define MD_FALLBACK_FRAME_STATE_FOR x86_dragonfly_fallback_frame_state
120
121
122static void
123x86_sigtramp_range (unsigned char **start, unsigned char **end)
124{
125  unsigned long ps_strings;
126  int mib[2];
127  size_t len;
128
129  mib[0] = CTL_KERN;
130  mib[1] = KERN_PS_STRINGS;
131  len = sizeof (ps_strings);
132  sysctl (mib, 2, &ps_strings, &len, NULL, 0);
133
134  *start = (unsigned char *)ps_strings - 128;
135  *end   = (unsigned char *)ps_strings;
136}
137
138
139static _Unwind_Reason_Code
140x86_dragonfly_fallback_frame_state
141(struct _Unwind_Context *context, _Unwind_FrameState *fs)
142{
143  unsigned char *pc = context->ra;
144  unsigned char *sigtramp_start, *sigtramp_end;
145  struct sigframe *sf;
146  long new_cfa;
147
148  x86_sigtramp_range(&sigtramp_start, &sigtramp_end);
149
150  if (pc >= sigtramp_end || pc < sigtramp_start)
151    return _URC_END_OF_STACK;
152
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;
158
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;
179}
180#endif /* ifdef __x86_64__  */
181