]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/i386/sol2-unwind.h
linux.h (MD_UNWIND_SUPPORT): Remove.
[thirdparty/gcc.git] / libgcc / config / i386 / sol2-unwind.h
CommitLineData
8d232178 1/* DWARF2 EH unwinding support for AMD x86-64 and x86.
ea2d8f12 2 Copyright (C) 2009, 2010 Free Software Foundation, Inc.
8d232178
OH
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
19
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23<http://www.gnu.org/licenses/>. */
24
25/* Do code reading to identify a signal frame, and set the frame
26 state data appropriately. See unwind-dw2.c for the structs. */
27
28#include <ucontext.h>
ea2d8f12 29#include <sys/frame.h>
8d232178
OH
30
31#ifdef __x86_64__
32
33#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state
34
35static _Unwind_Reason_Code
36x86_64_fallback_frame_state (struct _Unwind_Context *context,
37 _Unwind_FrameState *fs)
38{
39 unsigned char *pc = context->ra;
40 mcontext_t *mctx;
41 long new_cfa;
42
ea2d8f12 43 if (/* Solaris 10+
8d232178
OH
44 ------------
45 <__sighndlr+0>: push %rbp
46 <__sighndlr+1>: mov %rsp,%rbp
47 <__sighndlr+4>: callq *%rcx
48 <__sighndlr+6>: leaveq <--- PC
49 <__sighndlr+7>: retq */
50 *(unsigned long *)(pc - 6) == 0xc3c9d1ffe5894855)
ea2d8f12
RO
51
52 /* We need to move up three frames:
53
54 <signal handler> <-- context->cfa
55 __sighndlr
56 call_user_handler
57 sigacthandler
58 <kernel>
59
60 context->cfa points into the frame after the saved frame pointer and
61 saved pc (struct frame).
62
63 The ucontext_t structure is in the kernel frame after the signal
64 number and a siginfo_t *. Since the frame sizes vary even within
65 Solaris 10 updates, we need to walk the stack to get there. */
8d232178 66 {
ea2d8f12
RO
67 struct frame *fp = (struct frame *) context->cfa - 1;
68 struct handler_args {
69 int signo;
70 siginfo_t *sip;
71 ucontext_t ucontext;
72 } *handler_args;
73 ucontext_t *ucp;
74
75 /* Next frame: __sighndlr frame pointer. */
76 fp = (struct frame *) fp->fr_savfp;
77 /* call_user_handler frame pointer. */
78 fp = (struct frame *) fp->fr_savfp;
79 /* sigacthandler frame pointer. */
80 fp = (struct frame *) fp->fr_savfp;
81
82 /* The argument area precedes the struct frame. */
83 handler_args = (struct handler_args *) (fp + 1);
84 ucp = &handler_args->ucontext;
85 mctx = &ucp->uc_mcontext;
8d232178
OH
86 }
87 else
88 return _URC_END_OF_STACK;
89
90 new_cfa = mctx->gregs[REG_RSP];
91
92 fs->regs.cfa_how = CFA_REG_OFFSET;
93 fs->regs.cfa_reg = 7;
94 fs->regs.cfa_offset = new_cfa - (long) context->cfa;
95
96 /* The SVR4 register numbering macros aren't usable in libgcc. */
97 fs->regs.reg[0].how = REG_SAVED_OFFSET;
98 fs->regs.reg[0].loc.offset = (long)&mctx->gregs[REG_RAX] - new_cfa;
99 fs->regs.reg[1].how = REG_SAVED_OFFSET;
100 fs->regs.reg[1].loc.offset = (long)&mctx->gregs[REG_RDX] - new_cfa;
101 fs->regs.reg[2].how = REG_SAVED_OFFSET;
102 fs->regs.reg[2].loc.offset = (long)&mctx->gregs[REG_RCX] - new_cfa;
103 fs->regs.reg[3].how = REG_SAVED_OFFSET;
104 fs->regs.reg[3].loc.offset = (long)&mctx->gregs[REG_RBX] - new_cfa;
105 fs->regs.reg[4].how = REG_SAVED_OFFSET;
106 fs->regs.reg[4].loc.offset = (long)&mctx->gregs[REG_RSI] - new_cfa;
107 fs->regs.reg[5].how = REG_SAVED_OFFSET;
108 fs->regs.reg[5].loc.offset = (long)&mctx->gregs[REG_RDI] - new_cfa;
109 fs->regs.reg[6].how = REG_SAVED_OFFSET;
110 fs->regs.reg[6].loc.offset = (long)&mctx->gregs[REG_RBP] - new_cfa;
111 fs->regs.reg[8].how = REG_SAVED_OFFSET;
112 fs->regs.reg[8].loc.offset = (long)&mctx->gregs[REG_R8] - new_cfa;
113 fs->regs.reg[9].how = REG_SAVED_OFFSET;
114 fs->regs.reg[9].loc.offset = (long)&mctx->gregs[REG_R9] - new_cfa;
115 fs->regs.reg[10].how = REG_SAVED_OFFSET;
116 fs->regs.reg[10].loc.offset = (long)&mctx->gregs[REG_R10] - new_cfa;
117 fs->regs.reg[11].how = REG_SAVED_OFFSET;
118 fs->regs.reg[11].loc.offset = (long)&mctx->gregs[REG_R11] - new_cfa;
119 fs->regs.reg[12].how = REG_SAVED_OFFSET;
120 fs->regs.reg[12].loc.offset = (long)&mctx->gregs[REG_R12] - new_cfa;
121 fs->regs.reg[13].how = REG_SAVED_OFFSET;
122 fs->regs.reg[13].loc.offset = (long)&mctx->gregs[REG_R13] - new_cfa;
123 fs->regs.reg[14].how = REG_SAVED_OFFSET;
124 fs->regs.reg[14].loc.offset = (long)&mctx->gregs[REG_R14] - new_cfa;
125 fs->regs.reg[15].how = REG_SAVED_OFFSET;
126 fs->regs.reg[15].loc.offset = (long)&mctx->gregs[REG_R15] - new_cfa;
127 fs->regs.reg[16].how = REG_SAVED_OFFSET;
128 fs->regs.reg[16].loc.offset = (long)&mctx->gregs[REG_RIP] - new_cfa;
129 fs->retaddr_column = 16;
130 fs->signal_frame = 1;
131
132 return _URC_NO_REASON;
133}
134
135#else
136
137#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state
138
139static _Unwind_Reason_Code
140x86_fallback_frame_state (struct _Unwind_Context *context,
141 _Unwind_FrameState *fs)
142{
143 unsigned char *pc = context->ra;
144 mcontext_t *mctx;
145 long new_cfa;
146
ea2d8f12
RO
147 if (/* Solaris 8 - single-threaded
148 ----------------------------
8d232178
OH
149 <sigacthandler+17>: mov 0x10(%ebp),%esi
150 <sigacthandler+20>: push %esi
151 <sigacthandler+21>: pushl 0xc(%ebp)
152 <sigacthandler+24>: mov 0x8(%ebp),%ecx
153 <sigacthandler+27>: push %ecx
154 <sigacthandler+28>: mov offset(%ebx),%eax
155 <sigacthandler+34>: call *(%eax,%ecx,4)
156 <sigacthandler+37>: add $0xc,%esp <--- PC
157 <sigacthandler+40>: push %esi ... */
158 (*(unsigned long *)(pc - 20) == 0x5610758b
159 && *(unsigned long *)(pc - 16) == 0x8b0c75ff
160 && *(unsigned long *)(pc - 12) == 0x8b51084d
161 && *(unsigned char *)(pc - 8) == 0x83
162 && *(unsigned long *)(pc - 4) == 0x8814ff00
163 && *(unsigned long *)(pc - 0) == 0x560cc483)
164
ea2d8f12 165 || /* Solaris 8 - multi-threaded
8d232178
OH
166 ---------------------------
167 <__sighndlr+0>: push %ebp
168 <__sighndlr+1>: mov %esp,%ebp
169 <__sighndlr+3>: pushl 0x10(%ebp)
170 <__sighndlr+6>: pushl 0xc(%ebp)
171 <__sighndlr+9>: pushl 0x8(%ebp)
172 <__sighndlr+12>: call *0x14(%ebp)
173 <__sighndlr+15>: leave <--- PC */
174 (*(unsigned long *)(pc - 15) == 0xffec8b55
175 && *(unsigned long *)(pc - 11) == 0x75ff1075
176 && *(unsigned long *)(pc - 7) == 0x0875ff0c
177 && *(unsigned long *)(pc - 3) == 0xc91455ff)
178
ea2d8f12
RO
179 || /* Solaris 9 - single-threaded
180 ----------------------------
181 <sigacthandler+16>: mov 0x244(%ebx),%ecx
182 <sigacthandler+22>: mov 0x8(%ebp),%eax
183 <sigacthandler+25>: mov (%ecx,%eax,4),%ecx
184 <sigacthandler+28>: pushl 0x10(%ebp)
185 <sigacthandler+31>: pushl 0xc(%ebp)
186 <sigacthandler+34>: push %eax
187 <sigacthandler+35>: call *%ecx
188 <sigacthandler+37>: add $0xc,%esp <--- PC
189 <sigacthandler+40>: pushl 0x10(%ebp) */
190 (*(unsigned long *)(pc - 21) == 0x2448b8b
191 && *(unsigned long *)(pc - 17) == 0x458b0000
192 && *(unsigned long *)(pc - 13) == 0x810c8b08
193 && *(unsigned long *)(pc - 9) == 0xff1075ff
194 && *(unsigned long *)(pc - 5) == 0xff500c75
195 && *(unsigned long *)(pc - 1) == 0xcc483d1)
196
197 || /* Solaris 9 - multi-threaded, Solaris 10
198 ---------------------------------------
8d232178
OH
199 <__sighndlr+0>: push %ebp
200 <__sighndlr+1>: mov %esp,%ebp
201 <__sighndlr+3>: pushl 0x10(%ebp)
202 <__sighndlr+6>: pushl 0xc(%ebp)
203 <__sighndlr+9>: pushl 0x8(%ebp)
204 <__sighndlr+12>: call *0x14(%ebp)
205 <__sighndlr+15>: add $0xc,%esp <--- PC
206 <__sighndlr+18>: leave
207 <__sighndlr+19>: ret */
208 (*(unsigned long *)(pc - 15) == 0xffec8b55
209 && *(unsigned long *)(pc - 11) == 0x75ff1075
210 && *(unsigned long *)(pc - 7) == 0x0875ff0c
211 && *(unsigned long *)(pc - 3) == 0x831455ff
ea2d8f12
RO
212 && *(unsigned long *)(pc + 1) == 0xc3c90cc4)
213
214 || /* Solaris 11 before snv_125
215 --------------------------
216 <__sighndlr+0> push %ebp
217 <__sighndlr+1> mov %esp,%ebp
218 <__sighndlr+4> pushl 0x10(%ebp)
219 <__sighndlr+6> pushl 0xc(%ebp)
220 <__sighndlr+9> pushl 0x8(%ebp)
221 <__sighndlr+12> call *0x14(%ebp)
222 <__sighndlr+15> add $0xc,%esp
223 <__sighndlr+18> leave <--- PC
224 <__sighndlr+19> ret */
225 (*(unsigned long *)(pc - 18) == 0xffec8b55
226 && *(unsigned long *)(pc - 14) == 0x7fff107f
227 && *(unsigned long *)(pc - 10) == 0x0875ff0c
228 && *(unsigned long *)(pc - 6) == 0x83145fff
229 && *(unsigned long *)(pc - 1) == 0xc3c90cc4)
230
231 || /* Solaris 11 since snv_125
232 -------------------------
233 <__sighndlr+0> push %ebp
234 <__sighndlr+1> mov %esp,%ebp
235 <__sighndlr+3> and $0xfffffff0,%esp
236 <__sighndlr+6> sub $0x4,%esp
237 <__sighndlr+9> pushl 0x10(%ebp)
238 <__sighndlr+12> pushl 0xc(%ebp)
239 <__sighndlr+15> pushl 0x8(%ebp)
240 <__sighndlr+18> call *0x14(%ebp)
241 <__sighndlr+21> leave <--- PC
242 <__sighndlr+22> ret */
243 (*(unsigned long *)(pc - 21) == 0x83ec8b55
244 && *(unsigned long *)(pc - 17) == 0xec83f0e4
245 && *(unsigned long *)(pc - 13) == 0x1075ff04
246 && *(unsigned long *)(pc - 9) == 0xff0c75ff
247 && *(unsigned long *)(pc - 5) == 0x55ff0875
248 && (*(unsigned long *)(pc - 1) & 0x00ffffff) == 0x00c3c914))
8d232178
OH
249 {
250 struct handler_args {
251 int signo;
252 siginfo_t *sip;
253 ucontext_t *ucontext;
254 } *handler_args = context->cfa;
255 mctx = &handler_args->ucontext->uc_mcontext;
256 }
257 else
258 return _URC_END_OF_STACK;
259
260 new_cfa = mctx->gregs[UESP];
261
262 fs->regs.cfa_how = CFA_REG_OFFSET;
263 fs->regs.cfa_reg = 4;
264 fs->regs.cfa_offset = new_cfa - (long) context->cfa;
265
266 /* The SVR4 register numbering macros aren't usable in libgcc. */
267 fs->regs.reg[0].how = REG_SAVED_OFFSET;
268 fs->regs.reg[0].loc.offset = (long)&mctx->gregs[EAX] - new_cfa;
269 fs->regs.reg[3].how = REG_SAVED_OFFSET;
270 fs->regs.reg[3].loc.offset = (long)&mctx->gregs[EBX] - new_cfa;
271 fs->regs.reg[1].how = REG_SAVED_OFFSET;
272 fs->regs.reg[1].loc.offset = (long)&mctx->gregs[ECX] - new_cfa;
273 fs->regs.reg[2].how = REG_SAVED_OFFSET;
274 fs->regs.reg[2].loc.offset = (long)&mctx->gregs[EDX] - new_cfa;
275 fs->regs.reg[6].how = REG_SAVED_OFFSET;
276 fs->regs.reg[6].loc.offset = (long)&mctx->gregs[ESI] - new_cfa;
277 fs->regs.reg[7].how = REG_SAVED_OFFSET;
278 fs->regs.reg[7].loc.offset = (long)&mctx->gregs[EDI] - new_cfa;
279 fs->regs.reg[5].how = REG_SAVED_OFFSET;
280 fs->regs.reg[5].loc.offset = (long)&mctx->gregs[EBP] - new_cfa;
281 fs->regs.reg[8].how = REG_SAVED_OFFSET;
282 fs->regs.reg[8].loc.offset = (long)&mctx->gregs[EIP] - new_cfa;
283 fs->retaddr_column = 8;
284 fs->signal_frame = 1;
285
286 return _URC_NO_REASON;
287}
288
289#endif