Sync to trunk head (r42241)
[reactos.git] / reactos / include / reactos / libs / pseh / pseh2.h
1 /*
2 Copyright (c) 2008 KJK::Hyperion
3
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files (the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 DEALINGS IN THE SOFTWARE.
21 */
22 #ifdef _M_AMD64
23 #include "pseh2_64.h"
24 #else
25
26 #ifndef KJK_PSEH2_H_
27 #define KJK_PSEH2_H_
28
29 #if !defined (__arm__)
30
31 #if defined(__GNUC__)
32 struct _EXCEPTION_RECORD;
33 struct _EXCEPTION_POINTERS;
34 struct _CONTEXT;
35
36 typedef int (__cdecl * _SEH2FrameHandler_t)
37 (
38 struct _EXCEPTION_RECORD *,
39 void *,
40 struct _CONTEXT *,
41 void *
42 );
43
44 typedef struct __SEH2Registration
45 {
46 struct __SEH2Registration * SER_Prev;
47 _SEH2FrameHandler_t SER_Handler;
48 }
49 _SEH2Registration_t;
50
51 typedef struct __SEH2Frame
52 {
53 _SEH2Registration_t SF_Registration;
54 volatile struct __SEH2TryLevel * volatile SF_TopTryLevel;
55 volatile unsigned long SF_Code;
56 }
57 _SEH2Frame_t;
58
59 typedef struct __SEH2TryLevel
60 {
61 volatile struct __SEH2TryLevel * ST_Next;
62 void * ST_Filter;
63 void * ST_Body;
64 }
65 _SEH2TryLevel_t;
66
67 typedef struct __SEH2HandleTryLevel
68 {
69 _SEH2TryLevel_t SHT_Common;
70 void * volatile SHT_Esp;
71 void * volatile SHT_Ebp;
72 void * volatile SHT_Ebx;
73 void * volatile SHT_Esi;
74 void * volatile SHT_Edi;
75 }
76 _SEH2HandleTryLevel_t;
77
78 #ifdef __cplusplus
79 extern "C"
80 {
81 #endif
82
83 extern int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);
84 extern __attribute__((returns_twice)) int __cdecl _SEH2EnterFrameAndHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
85 extern __attribute__((returns_twice)) int __cdecl _SEH2EnterHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
86 extern void __cdecl _SEH2LeaveFrame(void);
87 extern void __cdecl _SEH2Return(void);
88
89 #ifdef __cplusplus
90 }
91 #endif
92
93 #if defined(__i386__)
94 typedef struct __SEHTrampoline
95 {
96 unsigned char STR_MovEcx;
97 unsigned char STR_Closure[4];
98 unsigned char STR_Jmp;
99 unsigned char STR_Function[4];
100 }
101 _SEHTrampoline_t;
102
103 static
104 __inline__
105 __attribute__((always_inline))
106 int _SEHIsTrampoline(_SEHTrampoline_t * trampoline_)
107 {
108 return trampoline_->STR_MovEcx == 0xb9 && trampoline_->STR_Jmp == 0xe9;
109 }
110
111 static
112 __inline__
113 __attribute__((always_inline))
114 void * _SEHFunctionFromTrampoline(_SEHTrampoline_t * trampoline_)
115 {
116 return (void *)(*(int *)(&trampoline_->STR_Function[0]) + (int)(trampoline_ + 1));
117 }
118
119 static
120 __inline__
121 __attribute__((always_inline))
122 void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
123 {
124 return (void *)*(int *)(&trampoline_->STR_Closure[0]);
125 }
126 #else
127 #error TODO
128 #endif
129
130 /* A no-op side effect that scares GCC */
131 #define __SEH_SIDE_EFFECT __asm__ __volatile__("#")
132
133 /* A no-op without any real side effects, but silences warnings */
134 #define __SEH_PRETEND_SIDE_EFFECT (void)0
135
136 /* Forces GCC to consider the specified label reachable */
137 #define __SEH_USE_LABEL(L_) if(__SEH_VOLATILE_FALSE) goto L_;
138
139 /* Makes GCC pretend the specified label is reachable, to silence warnings */
140 #define __SEH_PRETEND_USE_LABEL(L_) (void)(&&L_)
141
142 /* Soft memory barrier */
143 #define __SEH_BARRIER __asm__ __volatile__("#":::"memory")
144
145 /* GCC doesn't know that this equals zero */
146 #define __SEH_VOLATILE_ZERO ({ int zero = 0; __asm__ __volatile__("#" : "+g" (zero)); zero; })
147
148 #define __SEH_VOLATILE_FALSE __builtin_expect(__SEH_VOLATILE_ZERO, 0)
149 #define __SEH_VOLATILE_TRUE __builtin_expect(!__SEH_VOLATILE_ZERO, 1)
150
151 #define ___SEH_STRINGIFY(X_) # X_
152 #define __SEH_STRINGIFY(X_) ___SEH_STRINGIFY(X_)
153
154 #define __SEH_EXCEPT_RET long
155 #define __SEH_EXCEPT_ARGS __attribute__((unused)) _SEH2Frame_t * _SEH2FrameP, __attribute__((unused)) struct _EXCEPTION_POINTERS * _SEHExceptionInformation
156 #define __SEH_EXCEPT_ARGS_ , __SEH_EXCEPT_ARGS
157 #define __SEH_EXCEPT_PFN __SEH_DECLARE_EXCEPT_PFN
158 #define __SEH_DECLARE_EXCEPT_PFN(NAME_) __SEH_EXCEPT_RET (__cdecl * NAME_)(__SEH_EXCEPT_ARGS)
159 #define __SEH_DECLARE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
160 #define __SEH_DEFINE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
161
162 #define __SEH_FINALLY_RET void
163 #define __SEH_FINALLY_ARGS void
164 #define __SEH_FINALLY_ARGS_
165 #define __SEH_FINALLY_PFN __SEH_DECLARE_FINALLY_PFN
166 #define __SEH_DECLARE_FINALLY_PFN(NAME_) __SEH_FINALLY_RET (__cdecl * NAME_)(__SEH_FINALLY_ARGS)
167 #define __SEH_DECLARE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
168 #define __SEH_DEFINE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
169
170 #define __SEH_RETURN_EXCEPT(R_) return (long)(R_)
171 #define __SEH_RETURN_FINALLY() return
172
173 #define __SEH_BEGIN_TRY \
174 { \
175 __label__ _SEHEndTry; \
176 \
177 __SEH_PRETEND_USE_LABEL(_SEHEndTry); \
178 \
179 { \
180 __SEH_BARRIER;
181
182 #define __SEH_END_TRY \
183 __SEH_BARRIER; \
184 } \
185 _SEHEndTry:; \
186 }
187
188 #define __SEH_SET_TRYLEVEL(TRYLEVEL_) \
189 { \
190 __SEH_BARRIER; _SEH2FrameP->SF_TopTryLevel = (TRYLEVEL_); __SEH_BARRIER; \
191 }
192
193 #define __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) (_SEH2EnterFrameAndTrylevel(_SEH2FrameP, (TRYLEVEL_)))
194 #define __SEH_ENTER_TRYLEVEL(TRYLEVEL_) ((__SEH_SET_TRYLEVEL((TRYLEVEL_))), 0)
195
196 #define __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterFrameAndHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
197 #define __SEH_ENTER_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
198
199 #define __SEH_ENTER_SCOPE(TRYLEVEL_) (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) : __SEH_ENTER_TRYLEVEL(TRYLEVEL_))
200 #define __SEH_ENTER_HANDLE_SCOPE(TRYLEVEL_, HANDLE_) (({ __SEH_BARRIER; __asm__ __volatile__("mov %%esp, %0" : "=m" ((TRYLEVEL_)->SHT_Esp)); __SEH_BARRIER; }), (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL((TRYLEVEL_), (HANDLE_)) : __SEH_ENTER_HANDLE_TRYLEVEL((TRYLEVEL_), (HANDLE_))))
201
202 #define __SEH_LEAVE_TRYLEVEL() \
203 if(!_SEHTopTryLevel) \
204 { \
205 __SEH_SET_TRYLEVEL(_SEHPrevTryLevelP); \
206 } \
207
208 #define __SEH_LEAVE_FRAME() \
209 if(_SEHTopTryLevel) \
210 { \
211 _SEH2LeaveFrame(); \
212 __asm__ __volatile__("mov %0, %%esp" : : "g" (_SEHStackPointer)); \
213 }
214
215 #define __SEH_END_SCOPE_CHAIN \
216 static __attribute__((unused)) const int _SEH2ScopeKind = 1; \
217 static __attribute__((unused)) _SEH2Frame_t * const _SEH2FrameP = 0; \
218 static __attribute__((unused)) _SEH2TryLevel_t * const _SEH2TryLevelP = 0;
219
220 #define __SEH_BEGIN_SCOPE \
221 for(;;) \
222 { \
223 const int _SEHTopTryLevel = (_SEH2ScopeKind != 0); \
224 _SEH2Frame_t * const _SEHCurFrameP = _SEH2FrameP; \
225 volatile _SEH2TryLevel_t * const _SEHPrevTryLevelP = _SEH2TryLevelP; \
226 __attribute__((unused)) int _SEHAbnormalTermination; \
227 \
228 (void)_SEHTopTryLevel; \
229 (void)_SEHCurFrameP; \
230 (void)_SEHPrevTryLevelP; \
231 \
232 { \
233 __label__ _SEHBeforeTry; \
234 __label__ _SEHDoTry; \
235 __label__ _SEHAfterTry; \
236 static const int _SEH2ScopeKind = 0; \
237 volatile _SEH2TryLevel_t _SEHTryLevel; \
238 volatile _SEH2HandleTryLevel_t _SEHHandleTryLevel; \
239 void * _SEHStackPointer; \
240 volatile _SEH2TryLevel_t * _SEH2TryLevelP; \
241 _SEH2Frame_t * const _SEH2FrameP = _SEHTopTryLevel ? \
242 ({ __asm__ __volatile__("mov %%esp, %0" : "=g" (_SEHStackPointer)); __builtin_alloca(sizeof(_SEH2Frame_t)); }) : \
243 _SEHCurFrameP; \
244 \
245 (void)_SEH2ScopeKind; \
246 (void)_SEHTryLevel; \
247 (void)_SEHHandleTryLevel; \
248 (void)_SEHStackPointer; \
249 (void)_SEH2FrameP; \
250 (void)_SEH2TryLevelP; \
251 \
252 goto _SEHBeforeTry; \
253 \
254 _SEHDoTry:;
255
256 #define __SEH_END_SCOPE \
257 } \
258 \
259 break; \
260 }
261
262 #define __SEH_SCOPE_LOCALS \
263 __label__ _SEHBeginExcept; \
264 __label__ _SEHEndExcept; \
265 \
266 auto __SEH_DECLARE_FINALLY(_SEHFinally);
267
268 #define _SEH2_TRY \
269 __SEH_BEGIN_SCOPE \
270 { \
271 __SEH_SCOPE_LOCALS; \
272 \
273 __SEH_BEGIN_TRY \
274 {
275
276 #define _SEH2_FINALLY \
277 } \
278 __SEH_END_TRY; \
279 \
280 goto _SEHAfterTry; \
281 _SEHBeforeTry:; \
282 \
283 __SEH_PRETEND_USE_LABEL(_SEHBeginExcept); \
284 __SEH_PRETEND_USE_LABEL(_SEHEndExcept); \
285 \
286 _SEHTryLevel.ST_Filter = 0; \
287 _SEHTryLevel.ST_Body = &_SEHFinally; \
288 _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
289 __SEH_ENTER_SCOPE(&_SEHTryLevel); \
290 _SEH2TryLevelP = &_SEHTryLevel; \
291 \
292 _SEHAbnormalTermination = 1; \
293 \
294 goto _SEHDoTry; \
295 _SEHAfterTry:; \
296 \
297 _SEHAbnormalTermination = 0; \
298 \
299 __SEH_LEAVE_TRYLEVEL(); \
300 \
301 _SEHFinally(); \
302 goto _SEHEndExcept; \
303 \
304 _SEHBeginExcept:; \
305 \
306 __attribute__((noinline)) __SEH_DEFINE_FINALLY(_SEHFinally) \
307 { \
308 __SEH_END_SCOPE_CHAIN; \
309 \
310 (void)_SEH2ScopeKind; \
311 (void)_SEH2FrameP; \
312 (void)_SEH2TryLevelP; \
313 \
314 for(;; ({ __SEH_RETURN_FINALLY(); })) \
315 {
316
317 #define _SEH2_EXCEPT(...) \
318 } \
319 __SEH_END_TRY; \
320 \
321 goto _SEHAfterTry; \
322 \
323 _SEHBeforeTry:; \
324 \
325 { \
326 __attribute__((unused)) struct _EXCEPTION_POINTERS * volatile _SEHExceptionInformation; \
327 \
328 if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) <= 0) \
329 { \
330 if((__VA_ARGS__) < 0) \
331 { \
332 _SEHTryLevel.ST_Filter = (void *)-1; \
333 _SEHTryLevel.ST_Body = 0; \
334 } \
335 else \
336 { \
337 _SEHTryLevel.ST_Filter = (void *)0; \
338 _SEHTryLevel.ST_Body = 0; \
339 } \
340 \
341 _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
342 __SEH_ENTER_SCOPE(&_SEHTryLevel); \
343 _SEH2TryLevelP = &_SEHTryLevel; \
344 } \
345 else \
346 { \
347 if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) > 0) \
348 _SEHHandleTryLevel.SHT_Common.ST_Filter = (void *)1; \
349 else \
350 { \
351 __SEH_DEFINE_EXCEPT(_SEHExcept) \
352 { \
353 __SEH_RETURN_EXCEPT((__VA_ARGS__)); \
354 } \
355 \
356 _SEHHandleTryLevel.SHT_Common.ST_Filter = &_SEHExcept; \
357 } \
358 \
359 _SEHHandleTryLevel.SHT_Common.ST_Next = _SEHPrevTryLevelP; \
360 _SEH2TryLevelP = &_SEHHandleTryLevel.SHT_Common; \
361 \
362 if(__builtin_expect(__SEH_ENTER_HANDLE_SCOPE(&_SEHHandleTryLevel, &&_SEHBeginExcept), 0)) \
363 goto _SEHBeginExcept; \
364 } \
365 } \
366 \
367 goto _SEHDoTry; \
368 \
369 __attribute__((unused)) __SEH_DEFINE_FINALLY(_SEHFinally) { __SEH_RETURN_FINALLY(); } \
370 \
371 _SEHAfterTry:; \
372 __SEH_LEAVE_TRYLEVEL(); \
373 \
374 goto _SEHEndExcept; \
375 \
376 _SEHBeginExcept:; \
377 { \
378 { \
379 __SEH_BARRIER;
380
381 #define _SEH2_END \
382 __SEH_BARRIER; \
383 } \
384 } \
385 \
386 _SEHEndExcept:; \
387 \
388 __SEH_LEAVE_FRAME(); \
389 } \
390 __SEH_END_SCOPE;
391
392 #define _SEH2_GetExceptionInformation() (_SEHExceptionInformation)
393 #define _SEH2_GetExceptionCode() ((_SEH2FrameP)->SF_Code)
394 #define _SEH2_AbnormalTermination() (_SEHAbnormalTermination)
395
396 #define _SEH2_YIELD(STMT_) \
397 for(;;) \
398 { \
399 if(!_SEH2ScopeKind) \
400 _SEH2Return(); \
401 \
402 STMT_; \
403 }
404
405 #define _SEH2_LEAVE goto _SEHEndTry
406
407 __SEH_END_SCOPE_CHAIN;
408
409 #else
410
411 #include <excpt.h>
412
413 #define _SEH2_TRY __try {
414 #define _SEH2_FINALLY } __finally {
415 #define _SEH2_EXCEPT(...) } __except(__VA_ARGS__) {
416 #define _SEH2_END }
417
418 #define _SEH2_GetExceptionInformation() (GetExceptionInformation())
419 #define _SEH2_GetExceptionCode() (GetExceptionCode())
420 #define _SEH2_AbnormalTermination() (AbnormalTermination())
421
422 #define _SEH2_YIELD(STMT_) STMT_
423 #define _SEH2_LEAVE __leave
424
425 #endif
426
427 #else
428
429 #define _SEH2_TRY {
430 #define _SEH2_FINALLY } {
431 #define _SEH2_EXCEPT(...) } if (0) {
432 #define _SEH2_END }
433
434 #define _SEH2_GetExceptionInformation()
435 #define _SEH2_GetExceptionCode() STATUS_SUCCESS
436 #define _SEH2_AbnormalTermination()
437
438 #define _SEH2_YIELD(STMT_) STMT_
439 #define _SEH2_LEAVE
440
441 #endif
442
443 #endif
444 #endif
445
446 /* EOF */