ReactOS  0.4.15-dev-2977-ge996662
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 */
5 __asm__(
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  } \
162 }
163 
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")