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