]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/i386/sol2-unwind.h
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / i386 / sol2-unwind.h
CommitLineData
8d232178 1/* DWARF2 EH unwinding support for AMD x86-64 and x86.
a945c346 2 Copyright (C) 2009-2024 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. */
146e4591 97 fs->regs.how[0] = REG_SAVED_OFFSET;
8d232178 98 fs->regs.reg[0].loc.offset = (long)&mctx->gregs[REG_RAX] - new_cfa;
146e4591 99 fs->regs.how[1] = REG_SAVED_OFFSET;
8d232178 100 fs->regs.reg[1].loc.offset = (long)&mctx->gregs[REG_RDX] - new_cfa;
146e4591 101 fs->regs.how[2] = REG_SAVED_OFFSET;
8d232178 102 fs->regs.reg[2].loc.offset = (long)&mctx->gregs[REG_RCX] - new_cfa;
146e4591 103 fs->regs.how[3] = REG_SAVED_OFFSET;
8d232178 104 fs->regs.reg[3].loc.offset = (long)&mctx->gregs[REG_RBX] - new_cfa;
146e4591 105 fs->regs.how[4] = REG_SAVED_OFFSET;
8d232178 106 fs->regs.reg[4].loc.offset = (long)&mctx->gregs[REG_RSI] - new_cfa;
146e4591 107 fs->regs.how[5] = REG_SAVED_OFFSET;
8d232178 108 fs->regs.reg[5].loc.offset = (long)&mctx->gregs[REG_RDI] - new_cfa;
146e4591 109 fs->regs.how[6] = REG_SAVED_OFFSET;
8d232178 110 fs->regs.reg[6].loc.offset = (long)&mctx->gregs[REG_RBP] - new_cfa;
146e4591 111 fs->regs.how[8] = REG_SAVED_OFFSET;
8d232178 112 fs->regs.reg[8].loc.offset = (long)&mctx->gregs[REG_R8] - new_cfa;
146e4591 113 fs->regs.how[9] = REG_SAVED_OFFSET;
8d232178 114 fs->regs.reg[9].loc.offset = (long)&mctx->gregs[REG_R9] - new_cfa;
146e4591 115 fs->regs.how[10] = REG_SAVED_OFFSET;
8d232178 116 fs->regs.reg[10].loc.offset = (long)&mctx->gregs[REG_R10] - new_cfa;
146e4591 117 fs->regs.how[11] = REG_SAVED_OFFSET;
8d232178 118 fs->regs.reg[11].loc.offset = (long)&mctx->gregs[REG_R11] - new_cfa;
146e4591 119 fs->regs.how[12] = REG_SAVED_OFFSET;
8d232178 120 fs->regs.reg[12].loc.offset = (long)&mctx->gregs[REG_R12] - new_cfa;
146e4591 121 fs->regs.how[13] = REG_SAVED_OFFSET;
8d232178 122 fs->regs.reg[13].loc.offset = (long)&mctx->gregs[REG_R13] - new_cfa;
146e4591 123 fs->regs.how[14] = REG_SAVED_OFFSET;
8d232178 124 fs->regs.reg[14].loc.offset = (long)&mctx->gregs[REG_R14] - new_cfa;
146e4591 125 fs->regs.how[15] = REG_SAVED_OFFSET;
8d232178 126 fs->regs.reg[15].loc.offset = (long)&mctx->gregs[REG_R15] - new_cfa;
146e4591 127 fs->regs.how[16] = REG_SAVED_OFFSET;
8d232178
OH
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
ccd1242e 147 if (/* Solaris 11 since snv_125
ea2d8f12
RO
148 -------------------------
149 <__sighndlr+0> push %ebp
150 <__sighndlr+1> mov %esp,%ebp
151 <__sighndlr+3> and $0xfffffff0,%esp
152 <__sighndlr+6> sub $0x4,%esp
153 <__sighndlr+9> pushl 0x10(%ebp)
154 <__sighndlr+12> pushl 0xc(%ebp)
155 <__sighndlr+15> pushl 0x8(%ebp)
156 <__sighndlr+18> call *0x14(%ebp)
157 <__sighndlr+21> leave <--- PC
158 <__sighndlr+22> ret */
159 (*(unsigned long *)(pc - 21) == 0x83ec8b55
160 && *(unsigned long *)(pc - 17) == 0xec83f0e4
161 && *(unsigned long *)(pc - 13) == 0x1075ff04
162 && *(unsigned long *)(pc - 9) == 0xff0c75ff
163 && *(unsigned long *)(pc - 5) == 0x55ff0875
164 && (*(unsigned long *)(pc - 1) & 0x00ffffff) == 0x00c3c914))
8d232178
OH
165 {
166 struct handler_args {
167 int signo;
168 siginfo_t *sip;
169 ucontext_t *ucontext;
170 } *handler_args = context->cfa;
171 mctx = &handler_args->ucontext->uc_mcontext;
172 }
173 else
174 return _URC_END_OF_STACK;
175
176 new_cfa = mctx->gregs[UESP];
177
178 fs->regs.cfa_how = CFA_REG_OFFSET;
179 fs->regs.cfa_reg = 4;
180 fs->regs.cfa_offset = new_cfa - (long) context->cfa;
181
182 /* The SVR4 register numbering macros aren't usable in libgcc. */
146e4591 183 fs->regs.how[0] = REG_SAVED_OFFSET;
8d232178 184 fs->regs.reg[0].loc.offset = (long)&mctx->gregs[EAX] - new_cfa;
146e4591 185 fs->regs.how[3] = REG_SAVED_OFFSET;
8d232178 186 fs->regs.reg[3].loc.offset = (long)&mctx->gregs[EBX] - new_cfa;
146e4591 187 fs->regs.how[1] = REG_SAVED_OFFSET;
8d232178 188 fs->regs.reg[1].loc.offset = (long)&mctx->gregs[ECX] - new_cfa;
146e4591 189 fs->regs.how[2] = REG_SAVED_OFFSET;
8d232178 190 fs->regs.reg[2].loc.offset = (long)&mctx->gregs[EDX] - new_cfa;
146e4591 191 fs->regs.how[6] = REG_SAVED_OFFSET;
8d232178 192 fs->regs.reg[6].loc.offset = (long)&mctx->gregs[ESI] - new_cfa;
146e4591 193 fs->regs.how[7] = REG_SAVED_OFFSET;
8d232178 194 fs->regs.reg[7].loc.offset = (long)&mctx->gregs[EDI] - new_cfa;
146e4591 195 fs->regs.how[5] = REG_SAVED_OFFSET;
8d232178 196 fs->regs.reg[5].loc.offset = (long)&mctx->gregs[EBP] - new_cfa;
146e4591 197 fs->regs.how[8] = REG_SAVED_OFFSET;
8d232178
OH
198 fs->regs.reg[8].loc.offset = (long)&mctx->gregs[EIP] - new_cfa;
199 fs->retaddr_column = 8;
0ba045df
EB
200
201 /* SIGFPE for IEEE-754 exceptions is delivered after the faulting insn
202 rather than before it, so don't set fs->signal_frame in that case.
203 We test whether the ES field of the Status Register is zero. */
204 if ((mctx->fpregs.fp_reg_set.fpchip_state.status & 0x80) == 0)
205 fs->signal_frame = 1;
8d232178
OH
206
207 return _URC_NO_REASON;
208}
209
210#endif