ReactOS 0.4.16-dev-2473-gb34a1f1
pseh2_64.h
Go to the documentation of this file.
1
2#pragma once
3
5{
6 unsigned long ExceptionCode;
7 unsigned long ExceptionFlags;
10 unsigned long NumberParameters;
11 unsigned long long ExceptionInformation[15];
12};
13
15{
18};
19
20/* Declare our global trampoline function for filter and unwinder */
22 ".p2align 4, 0x90\n"
23 ".seh_proc __seh2_global_filter_func\n"
24 "__seh2_global_filter_func:\n"
25 /* r8 is rbp - frame-offset. Calculate the negative frame-offset */
26 "\tsub %rbp, %rax\n"
27 /* Save all callee-saved registers that the funclet may clobber */
28 "\tpush %rbp\n"
29 "\t.seh_pushreg %rbp\n"
30 "\tpush %rbx\n"
31 "\t.seh_pushreg %rbx\n"
32 "\tpush %rdi\n"
33 "\t.seh_pushreg %rdi\n"
34 "\tpush %rsi\n"
35 "\t.seh_pushreg %rsi\n"
36 "\tpush %r12\n"
37 "\t.seh_pushreg %r12\n"
38 "\tpush %r13\n"
39 "\t.seh_pushreg %r13\n"
40 "\tpush %r14\n"
41 "\t.seh_pushreg %r14\n"
42 "\tpush %r15\n"
43 "\t.seh_pushreg %r15\n"
44 "\tsub $40, %rsp\n"
45 "\t.seh_stackalloc 40\n"
46 "\t.seh_endprologue\n"
47 /* rdx is the original stack pointer, fix it up to be the frame pointer */
48 "\tsub %rax, %rdx\n"
49 /* Restore frame pointer. */
50 "\tmov %rdx, %rbp\n"
51 /* Actually execute the filter funclet */
52 "\tjmp *%r8\n"
53 "__seh2_global_filter_func_exit:\n"
54 "\t.p2align 4\n"
55 "\tadd $40, %rsp\n"
56 "\tpop %r15\n"
57 "\tpop %r14\n"
58 "\tpop %r13\n"
59 "\tpop %r12\n"
60 "\tpop %rsi\n"
61 "\tpop %rdi\n"
62 "\tpop %rbx\n"
63 "\tpop %rbp\n"
64 "\tret\n"
65 "\t.seh_endproc");
66
67#define STRINGIFY(a) #a
68#define EMIT_PRAGMA_(params) \
69 _Pragma( STRINGIFY(params) )
70#define EMIT_PRAGMA(type,line) \
71 EMIT_PRAGMA_(REACTOS seh(type,line))
72
73#define _SEH3$_EMIT_DEFS_AND_PRAGMA__(Line, Type) \
74 /* Emit assembler constants with line number to be individual */ \
75 __asm__ __volatile__ goto ("\n" \
76 "\t__seh2$$begin_try__" #Line "=%l0\n" /* Begin of tried code */ \
77 "\t__seh2$$end_try__" #Line "=%l1 + 1\n" /* End of tried code */ \
78 "\t__seh2$$filter__" #Line "=%l2\n" /* Filter function */ \
79 "\t__seh2$$begin_except__" #Line "=%l3\n" /* Called on except */ \
80 : /* No output */ \
81 : /* No input */ \
82 : /* No clobber */ \
83 : __seh2$$begin_try__, \
84 __seh2$$end_try__, \
85 __seh2$$filter__, \
86 __seh2$$begin_except__); \
87 /* Call our home-made pragma */ \
88 EMIT_PRAGMA(Type,Line)
89
90#define _SEH3$_EMIT_DEFS_AND_PRAGMA_(Line, Type) _SEH3$_EMIT_DEFS_AND_PRAGMA__(Line, Type)
91#define _SEH3$_EMIT_DEFS_AND_PRAGMA(Type) _SEH3$_EMIT_DEFS_AND_PRAGMA_(__LINE__, Type)
92
93#define _SEH2_TRY \
94{ \
95 __label__ __seh2$$filter__; \
96 __label__ __seh2$$begin_except__; \
97 __label__ __seh2$$begin_try__; \
98 __label__ __seh2$$end_try__; \
99 /* \
100 * We close the current SEH block for this function and install our own. \
101 * At this point GCC emitted its prologue, and if it saves more \
102 * registers, the relevant instruction will be valid for our scope as well. \
103 * We also count the number of try blocks at assembly level \
104 * to properly set the handler data when we're done. \
105 */ \
106__seh2$$begin_try__: \
107 { \
108 __label__ __seh2$$leave_scope__;
109
110#define _SEH2_EXCEPT(...) \
111__seh2$$leave_scope__: __MINGW_ATTRIB_UNUSED; \
112 } \
113__seh2$$end_try__:(void)0; \
114 /* Call our home-made pragma */ \
115 _SEH3$_EMIT_DEFS_AND_PRAGMA(__seh$$except); \
116 if (0) \
117 { \
118 __label__ __seh2$$leave_scope__; \
119 long __MINGW_ATTRIB_UNUSED __seh2$$exception_code__; \
120 /* Add our handlers to the list */ \
121 if (0) \
122 { \
123 /* Jump to the global filter. Tell it where the filter funclet lies */ \
124 __label__ __seh2$$filter_funclet__; \
125 __seh2$$filter__: \
126 __asm__ __volatile__ goto( \
127 "\tleaq %l1(%%rip), %%r8\n" \
128 "\tjmp __seh2_global_filter_func\n" \
129 : /* No output */ \
130 : "a"(__builtin_frame_address(0)) \
131 : "%r8" \
132 : __seh2$$filter_funclet__); \
133 /* Actually declare our filter funclet */ \
134 struct _SEH$$_EXCEPTION_POINTERS* __seh2$$exception_ptr__; \
135 __seh2$$filter_funclet__: \
136 /* At this point, the compiler can't count on any register being valid */ \
137 __asm__ __volatile__("" \
138 : "=c"(__seh2$$exception_ptr__) /* First argument of the filter function */ \
139 : /* No input */ \
140 : /* Everything */ \
141 "%rax", "%rbx","%rdx", "%rdi", "%rsi", \
142 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"); \
143 /* Save exception code */ \
144 __seh2$$exception_code__ = __seh2$$exception_ptr__->ExceptionRecord->ExceptionCode; \
145 /* Actually evaluate our filter and return via eax */ \
146 long __seh2$$filter_funclet_ret = ((__VA_ARGS__)); \
147 /* Go back to the global filter function with result in eax */ \
148 __asm__ __volatile__("jmp __seh2_global_filter_func_exit" \
149 : /* No output */ \
150 : "a"(__seh2$$filter_funclet_ret)); \
151 } \
152 /* Protect us from emitting instructions to jump back to the filter function */ \
153 enum \
154 { \
155 __seh2$$abnormal_termination__ = 0 \
156 }; \
157 __seh2$$begin_except__:
158
159#define _SEH2_FINALLY \
160__seh2$$leave_scope__: __MINGW_ATTRIB_UNUSED; \
161 } \
162__seh2$$end_try__: \
163__seh2$$begin_except__: __MINGW_ATTRIB_UNUSED; \
164 /* Call our home-made pragma */ \
165 _SEH3$_EMIT_DEFS_AND_PRAGMA(__seh$$finally); \
166 if (1) \
167 { \
168 __label__ __seh2$$finally__; \
169 __label__ __seh2$$begin_finally__; \
170 __label__ __seh2$$leave_scope__; \
171 __asm__ __volatile__ goto("" : : : : __seh2$$finally__); \
172 int __seh2$$abnormal_termination__; \
173 if (0) \
174 { \
175 /* Jump to the global trampoline. Tell it where the unwind code really lies */ \
176 __seh2$$filter__: __MINGW_ATTRIB_UNUSED; \
177 __seh2$$finally__: __MINGW_ATTRIB_UNUSED; \
178 __asm__ __volatile__ goto( \
179 "\t\n" \
180 "\tleaq %l1(%%rip), %%r8\n" \
181 "\tjmp __seh2_global_filter_func\n" \
182 : /* No output */ \
183 : "a"(__builtin_frame_address(0)) \
184 : "%r8" \
185 : __seh2$$begin_finally__); \
186 } \
187 \
188 /* Zero-out rcx to indicate normal termination */ \
189 __asm__ __volatile__("xor %%rcx, %%rcx" \
190 : /* No output */ \
191 : /* No input */ \
192 : /* Everything - We might come from __C_specific_handler here */ \
193 "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%rsi", \
194 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"); \
195 /* Actually declare our finally funclet */ \
196 __seh2$$begin_finally__: \
197 __asm__ __volatile__("" \
198 : "=c" (__seh2$$abnormal_termination__));
199
200#define _SEH2_END \
201 __seh2$$leave_scope__: __MINGW_ATTRIB_UNUSED; \
202 if (__seh2$$abnormal_termination__) \
203 { \
204 __asm__("jmp __seh2_global_filter_func_exit"); \
205 } \
206 } \
209#define _SEH2_GetExceptionInformation() ((struct _EXCEPTION_POINTERS*)__seh2$$exception_ptr__)
210#define _SEH2_GetExceptionCode() __seh2$$exception_code__
211#define _SEH2_AbnormalTermination() __seh2$$abnormal_termination__
212#define _SEH2_LEAVE goto __seh2$$leave_scope__
213#define _SEH2_YIELD(__stmt) __stmt
214#define _SEH2_VOLATILE volatile
216#undef __try // undef from GCC's stl
217#define __try _SEH2_TRY
218#define __except _SEH2_EXCEPT
219#define __finally _SEH2_FINALLY
220#define __endtry _SEH2_END
221#define __leave goto __seh2$$leave_scope__
222#define _exception_info() ((struct _EXCEPTION_POINTERS*)__seh2$$exception_ptr__)
223#define _exception_code() __seh2$$exception_code__
224#define _abnormal_termination() __seh2$$abnormal_termination__
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tpush %rbx\n" "\t.seh_pushreg %rbx\n" "\tpush %rdi\n" "\t.seh_pushreg %rdi\n" "\tpush %rsi\n" "\t.seh_pushreg %rsi\n" "\tpush %r12\n" "\t.seh_pushreg %r12\n" "\tpush %r13\n" "\t.seh_pushreg %r13\n" "\tpush %r14\n" "\t.seh_pushreg %r14\n" "\tpush %r15\n" "\t.seh_pushreg %r15\n" "\tsub $40, %rsp\n" "\t.seh_stackalloc 40\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $40, %rsp\n" "\tpop %r15\n" "\tpop %r14\n" "\tpop %r13\n" "\tpop %r12\n" "\tpop %rsi\n" "\tpop %rdi\n" "\tpop %rbx\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
struct _SEH$$_EXCEPTION_RECORD * ExceptionRecord
Definition: pseh2_64.h:16
struct _CONTEXT * ContextRecord
Definition: pseh2_64.h:17
unsigned long long ExceptionInformation[15]
Definition: pseh2_64.h:11
unsigned long ExceptionCode
Definition: pseh2_64.h:6
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: pseh2_64.h:8
unsigned long ExceptionFlags
Definition: pseh2_64.h:7
unsigned long NumberParameters
Definition: pseh2_64.h:10