2 * Support functions for Wine exception handling
4 * Copyright (c) 1999, 2010 Alexandre Julliard
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.
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.
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
24 #include "wine/exception.h"
26 #if defined(__x86_64__) && defined(__ASM_GLOBAL_FUNC)
27 extern void __wine_unwind_trampoline(void);
28 /* we need an extra call to make sure the stack is correctly aligned */
29 __ASM_GLOBAL_FUNC( __wine_unwind_trampoline
, "callq *%rax" );
32 /* wrapper for RtlUnwind since it clobbers registers on Windows */
33 void __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD
* frame
, EXCEPTION_RECORD
*record
,
34 void (*target
)(void) )
36 #if defined(__GNUC__) && defined(__i386__)
37 int dummy1
, dummy2
, dummy3
, dummy4
;
38 __asm__
__volatile__("pushl %%ebp\n\t"
47 : "=a" (dummy1
), "=S" (dummy2
), "=D" (dummy3
), "=c" (dummy4
)
48 : "0" (RtlUnwind
), "1" (frame
), "2" (target
), "3" (record
)
50 #elif defined(__x86_64__) && defined(__ASM_GLOBAL_FUNC)
51 RtlUnwind( frame
, __wine_unwind_trampoline
, record
, target
);
53 RtlUnwind( frame
, target
, record
, 0 );
58 static void DECLSPEC_NORETURN
unwind_target(void)
60 __WINE_FRAME
*wine_frame
= (__WINE_FRAME
*)__wine_get_frame();
61 __wine_pop_frame( &wine_frame
->frame
);
62 siglongjmp( wine_frame
->jmp
, 1 );
65 static void DECLSPEC_NORETURN
unwind_frame( EXCEPTION_RECORD
*record
,
66 EXCEPTION_REGISTRATION_RECORD
*frame
)
68 __WINE_FRAME
*wine_frame
= (__WINE_FRAME
*)frame
;
70 /* hack to make GetExceptionCode() work in handler */
71 wine_frame
->ExceptionCode
= record
->ExceptionCode
;
72 wine_frame
->ExceptionRecord
= wine_frame
;
74 __wine_rtl_unwind( frame
, record
, unwind_target
);
77 DWORD
__wine_exception_handler( EXCEPTION_RECORD
*record
,
78 EXCEPTION_REGISTRATION_RECORD
*frame
,
80 EXCEPTION_REGISTRATION_RECORD
**pdispatcher
)
82 __WINE_FRAME
*wine_frame
= (__WINE_FRAME
*)frame
;
83 EXCEPTION_POINTERS ptrs
;
85 if (record
->ExceptionFlags
& (EH_UNWINDING
| EH_EXIT_UNWIND
| EH_NESTED_CALL
))
86 return ExceptionContinueSearch
;
88 ptrs
.ExceptionRecord
= record
;
89 ptrs
.ContextRecord
= context
;
90 switch(wine_frame
->u
.filter( &ptrs
))
92 case EXCEPTION_CONTINUE_SEARCH
:
93 return ExceptionContinueSearch
;
94 case EXCEPTION_CONTINUE_EXECUTION
:
95 return ExceptionContinueExecution
;
96 case EXCEPTION_EXECUTE_HANDLER
:
99 unwind_frame( record
, frame
);
102 DWORD
__wine_exception_ctx_handler( EXCEPTION_RECORD
*record
,
103 EXCEPTION_REGISTRATION_RECORD
*frame
,
105 EXCEPTION_REGISTRATION_RECORD
**pdispatcher
)
107 __WINE_FRAME
*wine_frame
= (__WINE_FRAME
*)frame
;
108 EXCEPTION_POINTERS ptrs
;
110 if (record
->ExceptionFlags
& (EH_UNWINDING
| EH_EXIT_UNWIND
| EH_NESTED_CALL
))
111 return ExceptionContinueSearch
;
113 ptrs
.ExceptionRecord
= record
;
114 ptrs
.ContextRecord
= context
;
115 switch(wine_frame
->u
.filter_ctx( &ptrs
, wine_frame
->ctx
))
117 case EXCEPTION_CONTINUE_SEARCH
:
118 return ExceptionContinueSearch
;
119 case EXCEPTION_CONTINUE_EXECUTION
:
120 return ExceptionContinueExecution
;
121 case EXCEPTION_EXECUTE_HANDLER
:
124 unwind_frame( record
, frame
);
127 DWORD
__wine_exception_handler_page_fault( EXCEPTION_RECORD
*record
,
128 EXCEPTION_REGISTRATION_RECORD
*frame
,
130 EXCEPTION_REGISTRATION_RECORD
**pdispatcher
)
132 if (record
->ExceptionFlags
& (EH_UNWINDING
| EH_EXIT_UNWIND
| EH_NESTED_CALL
))
133 return ExceptionContinueSearch
;
134 if (record
->ExceptionCode
!= STATUS_ACCESS_VIOLATION
)
135 return ExceptionContinueSearch
;
136 unwind_frame( record
, frame
);
139 DWORD
__wine_exception_handler_all( EXCEPTION_RECORD
*record
,
140 EXCEPTION_REGISTRATION_RECORD
*frame
,
142 EXCEPTION_REGISTRATION_RECORD
**pdispatcher
)
144 if (record
->ExceptionFlags
& (EH_UNWINDING
| EH_EXIT_UNWIND
| EH_NESTED_CALL
))
145 return ExceptionContinueSearch
;
146 unwind_frame( record
, frame
);
149 DWORD
__wine_finally_handler( EXCEPTION_RECORD
*record
,
150 EXCEPTION_REGISTRATION_RECORD
*frame
,
152 EXCEPTION_REGISTRATION_RECORD
**pdispatcher
)
154 if (record
->ExceptionFlags
& (EH_UNWINDING
| EH_EXIT_UNWIND
))
156 __WINE_FRAME
*wine_frame
= (__WINE_FRAME
*)frame
;
157 wine_frame
->u
.finally_func( FALSE
);
159 return ExceptionContinueSearch
;
162 DWORD
__wine_finally_ctx_handler( EXCEPTION_RECORD
*record
,
163 EXCEPTION_REGISTRATION_RECORD
*frame
,
165 EXCEPTION_REGISTRATION_RECORD
**pdispatcher
)
167 if (record
->ExceptionFlags
& (EH_UNWINDING
| EH_EXIT_UNWIND
))
169 __WINE_FRAME
*wine_frame
= (__WINE_FRAME
*)frame
;
170 wine_frame
->u
.finally_func_ctx( FALSE
, wine_frame
->ctx
);
172 return ExceptionContinueSearch
;