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