Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/winecrt0/exception.c
12343 views
1
/*
2
* Support functions for Wine exception handling
3
*
4
* Copyright (c) 1999, 2010 Alexandre Julliard
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include <stdarg.h>
22
#include "excpt.h"
23
#undef USE_COMPILER_EXCEPTIONS
24
#undef GetExceptionInformation
25
#undef GetExceptionCode
26
#undef AbnormalTermination
27
#include "winternl.h"
28
#include "wine/exception.h"
29
#include "wine/asm.h"
30
31
#if defined(__GNUC__) || defined(__clang__)
32
33
#if defined(__i386__)
34
35
__ASM_GLOBAL_FUNC( __wine_rtl_unwind,
36
"pushl %ebp\n\t"
37
__ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
38
__ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
39
"movl %esp,%ebp\n\t"
40
__ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
41
"subl $8,%esp\n\t"
42
"pushl $0\n\t" /* retval */
43
"pushl 12(%ebp)\n\t" /* record */
44
"pushl 16(%ebp)\n\t" /* target */
45
"pushl 8(%ebp)\n\t" /* frame */
46
"call " __ASM_STDCALL("RtlUnwind",16) "\n\t"
47
"call *16(%ebp)" )
48
49
#elif defined(__x86_64__) && !defined(__arm64ec__)
50
51
__ASM_GLOBAL_FUNC( __wine_rtl_unwind,
52
"pushq %rbp\n\t"
53
__ASM_SEH(".seh_pushreg %rbp\n\t")
54
__ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
55
__ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
56
"movq %rsp,%rbp\n\t"
57
__ASM_SEH(".seh_setframe %rbp,0\n\t")
58
__ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
59
"subq $0x20,%rsp\n\t"
60
__ASM_SEH(".seh_stackalloc 0x20\n\t")
61
__ASM_SEH(".seh_endprologue\n\t")
62
"movq %r8,%r9\n\t" /* retval = final target */
63
"movq %rdx,%r8\n\t" /* record */
64
"leaq __wine_unwind_trampoline(%rip),%rdx\n\t" /* target = trampoline */
65
"call " __ASM_NAME("RtlUnwind") "\n"
66
"__wine_unwind_trampoline:\n\t"
67
/* we need an extra call to make sure the stack is correctly aligned */
68
"callq *%rax" )
69
70
#else
71
72
void __cdecl __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame, EXCEPTION_RECORD *record,
73
void (*target)(void) )
74
{
75
RtlUnwind( frame, target, record, 0 );
76
for (;;) target();
77
}
78
79
#endif
80
81
static void DECLSPEC_NORETURN unwind_target(void)
82
{
83
__WINE_FRAME *wine_frame = (__WINE_FRAME *)__wine_get_frame();
84
__wine_pop_frame( &wine_frame->frame );
85
for (;;) __wine_longjmp( &wine_frame->jmp, 1 );
86
}
87
88
static void DECLSPEC_NORETURN unwind_frame( EXCEPTION_RECORD *record,
89
EXCEPTION_REGISTRATION_RECORD *frame )
90
{
91
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
92
93
/* hack to make GetExceptionCode() work in handler */
94
wine_frame->ExceptionCode = record->ExceptionCode;
95
wine_frame->ExceptionRecord = wine_frame;
96
97
__wine_rtl_unwind( frame, record, unwind_target );
98
}
99
100
DWORD __cdecl __wine_exception_handler( EXCEPTION_RECORD *record,
101
EXCEPTION_REGISTRATION_RECORD *frame,
102
CONTEXT *context,
103
EXCEPTION_REGISTRATION_RECORD **pdispatcher )
104
{
105
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
106
EXCEPTION_POINTERS ptrs;
107
108
if (record->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | EXCEPTION_NESTED_CALL))
109
return ExceptionContinueSearch;
110
111
ptrs.ExceptionRecord = record;
112
ptrs.ContextRecord = context;
113
switch(wine_frame->u.filter( &ptrs ))
114
{
115
case EXCEPTION_CONTINUE_SEARCH:
116
return ExceptionContinueSearch;
117
case EXCEPTION_CONTINUE_EXECUTION:
118
return ExceptionContinueExecution;
119
case EXCEPTION_EXECUTE_HANDLER:
120
break;
121
}
122
unwind_frame( record, frame );
123
}
124
125
DWORD __cdecl __wine_exception_ctx_handler( EXCEPTION_RECORD *record,
126
EXCEPTION_REGISTRATION_RECORD *frame,
127
CONTEXT *context,
128
EXCEPTION_REGISTRATION_RECORD **pdispatcher )
129
{
130
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
131
EXCEPTION_POINTERS ptrs;
132
133
if (record->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | EXCEPTION_NESTED_CALL))
134
return ExceptionContinueSearch;
135
136
ptrs.ExceptionRecord = record;
137
ptrs.ContextRecord = context;
138
switch(wine_frame->u.filter_ctx( &ptrs, wine_frame->ctx ))
139
{
140
case EXCEPTION_CONTINUE_SEARCH:
141
return ExceptionContinueSearch;
142
case EXCEPTION_CONTINUE_EXECUTION:
143
return ExceptionContinueExecution;
144
case EXCEPTION_EXECUTE_HANDLER:
145
break;
146
}
147
unwind_frame( record, frame );
148
}
149
150
DWORD __cdecl __wine_exception_handler_page_fault( EXCEPTION_RECORD *record,
151
EXCEPTION_REGISTRATION_RECORD *frame,
152
CONTEXT *context,
153
EXCEPTION_REGISTRATION_RECORD **pdispatcher )
154
{
155
if (record->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | EXCEPTION_NESTED_CALL))
156
return ExceptionContinueSearch;
157
if (record->ExceptionCode != STATUS_ACCESS_VIOLATION)
158
return ExceptionContinueSearch;
159
unwind_frame( record, frame );
160
}
161
162
DWORD __cdecl __wine_exception_handler_all( EXCEPTION_RECORD *record,
163
EXCEPTION_REGISTRATION_RECORD *frame,
164
CONTEXT *context,
165
EXCEPTION_REGISTRATION_RECORD **pdispatcher )
166
{
167
if (record->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | EXCEPTION_NESTED_CALL))
168
return ExceptionContinueSearch;
169
unwind_frame( record, frame );
170
}
171
172
DWORD __cdecl __wine_finally_handler( EXCEPTION_RECORD *record,
173
EXCEPTION_REGISTRATION_RECORD *frame,
174
CONTEXT *context,
175
EXCEPTION_REGISTRATION_RECORD **pdispatcher )
176
{
177
if (record->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
178
{
179
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
180
wine_frame->u.finally_func( FALSE );
181
}
182
return ExceptionContinueSearch;
183
}
184
185
DWORD __cdecl __wine_finally_ctx_handler( EXCEPTION_RECORD *record,
186
EXCEPTION_REGISTRATION_RECORD *frame,
187
CONTEXT *context,
188
EXCEPTION_REGISTRATION_RECORD **pdispatcher )
189
{
190
if (record->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
191
{
192
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
193
wine_frame->u.finally_func_ctx( FALSE, wine_frame->ctx );
194
}
195
return ExceptionContinueSearch;
196
}
197
198
#endif /* __GNUC__ || __clang__ */
199
200