ReactOS  0.4.15-dev-3207-ga415bd4
pseh2.h
Go to the documentation of this file.
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 
23 #ifndef KJK_PSEH2_H_
24 #define KJK_PSEH2_H_
25 
26 #if defined(_USE_NATIVE_SEH) || (defined(_MSC_VER) && !(defined(__clang__) && defined(_M_AMD64)))
27 
28 #include <excpt.h>
29 #define _SEH2_TRY __try
30 #define _SEH2_FINALLY __finally
31 #define _SEH2_EXCEPT(...) __except(__VA_ARGS__)
32 #define _SEH2_END
33 #define _SEH2_GetExceptionInformation() (GetExceptionInformation())
34 #define _SEH2_GetExceptionCode() (GetExceptionCode())
35 #define _SEH2_AbnormalTermination() (AbnormalTermination())
36 #define _SEH2_YIELD(STMT_) STMT_
37 #define _SEH2_LEAVE __leave
38 #define _SEH2_VOLATILE
39 
40 #elif defined(__GNUC__) && !defined(__clang__) && defined(_M_AMD64)
41 
42 #include "pseh2_64.h"
43 
44 #elif defined(_USE_DUMMY_PSEH) || defined (__arm__) || defined(_M_AMD64)
45 
46 #ifdef __cplusplus
47 extern"C"
48 {
49 #endif
50 extern int _SEH2_Volatile0;
52 #ifdef __cplusplus
53 } // extern "C"
54 #endif
55 
56 #define _SEH2_TRY \
57 _Pragma("GCC diagnostic push") \
58 _Pragma("GCC diagnostic ignored \"-Wunused-label\"")\
59 { \
60  __label__ __seh2_scope_end__;
61 
62 #define _SEH2_FINALLY \
63  __seh2_scope_end__:; \
64  } \
65  if (1) \
66  { \
67  __label__ __seh2_scope_end__;
68 
69 #define _SEH2_EXCEPT(...) \
70  __seh2_scope_end__:; \
71  } \
72  if (_SEH2_Volatile0 || (0 && (__VA_ARGS__))) \
73  { \
74  __label__ __seh2_scope_end__;
75 
76 #define _SEH2_END \
77  __seh2_scope_end__:; \
78  } \
79 _Pragma("GCC diagnostic pop")
80 
81 #define _SEH2_GetExceptionInformation() ((struct _EXCEPTION_POINTERS*)0)
82 #define _SEH2_GetExceptionCode() _SEH2_VolatileExceptionCode
83 #define _SEH2_AbnormalTermination() (0)
84 #define _SEH2_YIELD(STMT_) STMT_
85 #define _SEH2_LEAVE goto __seh2_scope_end__;
86 #define _SEH2_VOLATILE volatile
87 
88 #elif defined(_USE_PSEH3)
89 
90 #include "pseh3.h"
91 
92 /* Compatibility macros */
93 #define _SEH2_TRY _SEH3_TRY
94 #define _SEH2_EXCEPT _SEH3_EXCEPT
95 #define _SEH2_FINALLY _SEH3_FINALLY
96 #define _SEH2_END _SEH3_END
97 #define _SEH2_GetExceptionInformation() ((struct _EXCEPTION_POINTERS*)_exception_info())
98 #define _SEH2_GetExceptionCode _exception_code
99 #define _SEH2_AbnormalTermination _abnormal_termination
100 #define _SEH2_LEAVE _SEH3_LEAVE
101 #define _SEH2_YIELD(x) x
102 #define _SEH2_VOLATILE volatile
103 
104 #elif defined(__GNUC__)
105 
106 struct _EXCEPTION_RECORD;
107 struct _EXCEPTION_POINTERS;
108 struct _CONTEXT;
109 
110 typedef int (__cdecl * _SEH2FrameHandler_t)
111 (
112  struct _EXCEPTION_RECORD *,
113  void *,
114  struct _CONTEXT *,
115  void *
116 );
117 
118 typedef struct __SEH2Registration
119 {
120  struct __SEH2Registration * SER_Prev;
121  _SEH2FrameHandler_t SER_Handler;
122 }
123 _SEH2Registration_t;
124 
125 typedef struct __SEH2Frame
126 {
127  _SEH2Registration_t SF_Registration;
128  volatile struct __SEH2TryLevel * volatile SF_TopTryLevel;
129  volatile unsigned long SF_Code;
130 }
131 _SEH2Frame_t;
132 
133 typedef struct __SEH2TryLevel
134 {
135  volatile struct __SEH2TryLevel * ST_Next;
136  void * ST_Filter;
137  void * ST_Body;
138 }
139 _SEH2TryLevel_t;
140 
141 typedef struct __SEH2HandleTryLevel
142 {
143  _SEH2TryLevel_t SHT_Common;
144  void * volatile SHT_Esp;
145  void * volatile SHT_Ebp;
146  void * volatile SHT_Ebx;
147  void * volatile SHT_Esi;
148  void * volatile SHT_Edi;
149 }
150 _SEH2HandleTryLevel_t;
151 
152 #ifdef __cplusplus
153 extern "C" {
154 #endif
155 
156 extern int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);
157 extern __attribute__((returns_twice)) int __cdecl _SEH2EnterFrameAndHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
158 extern __attribute__((returns_twice)) int __cdecl _SEH2EnterHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
159 extern void __cdecl _SEH2LeaveFrame(void);
160 extern void __cdecl _SEH2Return(void);
161 
162 #ifdef __cplusplus
163 }
164 #endif
165 
166 /* Prevent gcc from inlining functions that use SEH. */
167 #if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 7))
168 static inline __attribute__((always_inline)) __attribute__((returns_twice)) void _SEH_DontInline() {}
169 #define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() _SEH_DontInline();
170 #else
171 #define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS()
172 #endif
173 
174 /* A no-op side effect that scares GCC */
175 #define __SEH_SIDE_EFFECT __asm__ __volatile__("#")
176 
177 /* A no-op without any real side effects, but silences warnings */
178 #define __SEH_PRETEND_SIDE_EFFECT (void)0
179 
180 /* Forces GCC to consider the specified label reachable */
181 #define __SEH_USE_LABEL(L_) if(__SEH_VOLATILE_FALSE) goto L_;
182 
183 /* Makes GCC pretend the specified label is reachable, to silence warnings */
184 #define __SEH_PRETEND_USE_LABEL(L_) (void)(&&L_)
185 
186 /* Soft memory barrier */
187 #define __SEH_BARRIER __asm__ __volatile__("#":::"memory")
188 
189 /* GCC doesn't know that this equals zero */
190 #define __SEH_VOLATILE_ZERO ({ int zero = 0; __asm__ __volatile__("#" : "+g" (zero)); zero; })
191 
192 #define __SEH_VOLATILE_FALSE __builtin_expect(__SEH_VOLATILE_ZERO, 0)
193 #define __SEH_VOLATILE_TRUE __builtin_expect(!__SEH_VOLATILE_ZERO, 1)
194 
195 #define ___SEH_STRINGIFY(X_) # X_
196 #define __SEH_STRINGIFY(X_) ___SEH_STRINGIFY(X_)
197 
198 #define __SEH_EXCEPT_RET long
199 #define __SEH_EXCEPT_ARGS __attribute__((unused)) _SEH2Frame_t * _SEH2FrameP, __attribute__((unused)) struct _EXCEPTION_POINTERS * _SEHExceptionInformation
200 #define __SEH_EXCEPT_ARGS_ , __SEH_EXCEPT_ARGS
201 #define __SEH_EXCEPT_PFN __SEH_DECLARE_EXCEPT_PFN
202 #define __SEH_DECLARE_EXCEPT_PFN(NAME_) __SEH_EXCEPT_RET (__cdecl * NAME_)(__SEH_EXCEPT_ARGS)
203 #define __SEH_DECLARE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
204 #define __SEH_DEFINE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
205 
206 #define __SEH_FINALLY_RET void
207 #define __SEH_FINALLY_ARGS void
208 #define __SEH_FINALLY_ARGS_
209 #define __SEH_FINALLY_PFN __SEH_DECLARE_FINALLY_PFN
210 #define __SEH_DECLARE_FINALLY_PFN(NAME_) __SEH_FINALLY_RET (__cdecl * NAME_)(__SEH_FINALLY_ARGS)
211 #define __SEH_DECLARE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
212 #define __SEH_DEFINE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
213 
214 #define __SEH_RETURN_EXCEPT(R_) return (long)(R_)
215 #define __SEH_RETURN_FINALLY() return
216 
217 #define __SEH_BEGIN_TRY \
218  { \
219  __label__ _SEHEndTry; \
220  \
221  __SEH_PRETEND_USE_LABEL(_SEHEndTry); \
222  \
223  { \
224  __SEH_BARRIER;
225 
226 #define __SEH_END_TRY \
227  __SEH_BARRIER; \
228  } \
229  _SEHEndTry:; \
230  }
231 
232 #define __SEH_SET_TRYLEVEL(TRYLEVEL_) \
233  { \
234  __SEH_BARRIER; _SEH2FrameP->SF_TopTryLevel = (TRYLEVEL_); __SEH_BARRIER; \
235  }
236 
237 #define __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) (_SEH2EnterFrameAndTrylevel(_SEH2FrameP, (TRYLEVEL_)))
238 #define __SEH_ENTER_TRYLEVEL(TRYLEVEL_) ((__SEH_SET_TRYLEVEL((TRYLEVEL_))), 0)
239 
240 #define __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterFrameAndHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
241 #define __SEH_ENTER_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
242 
243 #define __SEH_ENTER_SCOPE(TRYLEVEL_) (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) : __SEH_ENTER_TRYLEVEL(TRYLEVEL_))
244 #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_))))
245 
246 #define __SEH_LEAVE_TRYLEVEL() \
247  if(!_SEHTopTryLevel) \
248  { \
249  __SEH_SET_TRYLEVEL(_SEHPrevTryLevelP); \
250  } \
251 
252 #define __SEH_LEAVE_FRAME() \
253  if(_SEHTopTryLevel) \
254  { \
255  _SEH2LeaveFrame(); \
256  }
257 
258 #define __SEH_END_SCOPE_CHAIN \
259  static __attribute__((unused)) const int _SEH2ScopeKind = 1; \
260  static __attribute__((unused)) _SEH2Frame_t * const _SEH2FrameP = 0; \
261  static __attribute__((unused)) _SEH2TryLevel_t * const _SEH2TryLevelP = 0;
262 
263 #define __SEH_BEGIN_SCOPE \
264  for(;;) \
265  { \
266  const int _SEHTopTryLevel = (_SEH2ScopeKind != 0); \
267  _SEH2Frame_t * const _SEHCurFrameP = _SEH2FrameP; \
268  volatile _SEH2TryLevel_t * const _SEHPrevTryLevelP = _SEH2TryLevelP; \
269  __attribute__((unused)) int _SEHAbnormalTermination; \
270  \
271  (void)_SEHTopTryLevel; \
272  (void)_SEHCurFrameP; \
273  (void)_SEHPrevTryLevelP; \
274  \
275  { \
276  __label__ _SEHBeforeTry; \
277  __label__ _SEHDoTry; \
278  __label__ _SEHAfterTry; \
279  static const int _SEH2ScopeKind = 0; \
280  volatile _SEH2TryLevel_t _SEHTryLevel; \
281  volatile _SEH2HandleTryLevel_t _SEHHandleTryLevel; \
282  _SEH2Frame_t _SEH2Frame[_SEHTopTryLevel ? 1 : 0]; \
283  volatile _SEH2TryLevel_t * _SEH2TryLevelP; \
284  _SEH2Frame_t * const _SEH2FrameP = _SEHTopTryLevel ? \
285  _SEH2Frame : _SEHCurFrameP; \
286  \
287  (void)_SEH2ScopeKind; \
288  (void)_SEHTryLevel; \
289  (void)_SEHHandleTryLevel; \
290  (void)_SEH2FrameP; \
291  (void)_SEH2TryLevelP; \
292  \
293  goto _SEHBeforeTry; \
294  \
295  _SEHDoTry:;
296 
297 #define __SEH_END_SCOPE \
298  } \
299  \
300  break; \
301  }
302 
303 #define __SEH_SCOPE_LOCALS \
304  __label__ _SEHBeginExcept; \
305  __label__ _SEHEndExcept; \
306  \
307  auto __SEH_DECLARE_FINALLY(_SEHFinally);
308 
309 #define _SEH2_TRY \
310  __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() \
311  __SEH_BEGIN_SCOPE \
312  { \
313  __SEH_SCOPE_LOCALS; \
314  \
315  __SEH_BEGIN_TRY \
316  {
317 
318 #define _SEH2_FINALLY \
319  } \
320  __SEH_END_TRY; \
321  \
322  goto _SEHAfterTry; \
323  _SEHBeforeTry:; \
324  \
325  __SEH_PRETEND_USE_LABEL(_SEHBeginExcept); \
326  __SEH_PRETEND_USE_LABEL(_SEHEndExcept); \
327  \
328  _SEHTryLevel.ST_Filter = 0; \
329  _SEHTryLevel.ST_Body = &_SEHFinally; \
330  _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
331  __SEH_ENTER_SCOPE(&_SEHTryLevel); \
332  _SEH2TryLevelP = &_SEHTryLevel; \
333  \
334  _SEHAbnormalTermination = 1; \
335  \
336  goto _SEHDoTry; \
337  _SEHAfterTry:; \
338  \
339  _SEHAbnormalTermination = 0; \
340  \
341  __SEH_LEAVE_TRYLEVEL(); \
342  \
343  _SEHFinally(); \
344  goto _SEHEndExcept; \
345  \
346  _SEHBeginExcept:; \
347  \
348  __attribute__((noinline)) __SEH_DEFINE_FINALLY(_SEHFinally) \
349  { \
350  __SEH_END_SCOPE_CHAIN; \
351  \
352  (void)_SEH2ScopeKind; \
353  (void)_SEH2FrameP; \
354  (void)_SEH2TryLevelP; \
355  \
356  for(;; ({ __SEH_RETURN_FINALLY(); })) \
357  {
358 
359 #define _SEH2_EXCEPT(...) \
360  } \
361  __SEH_END_TRY; \
362  \
363  goto _SEHAfterTry; \
364  \
365  _SEHBeforeTry:; \
366  \
367  { \
368  __attribute__((unused)) struct _EXCEPTION_POINTERS * volatile _SEHExceptionInformation; \
369  \
370  if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) <= 0) \
371  { \
372  if((__VA_ARGS__) < 0) \
373  { \
374  _SEHTryLevel.ST_Filter = (void *)-1; \
375  _SEHTryLevel.ST_Body = 0; \
376  } \
377  else \
378  { \
379  _SEHTryLevel.ST_Filter = (void *)0; \
380  _SEHTryLevel.ST_Body = 0; \
381  } \
382  \
383  _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
384  __SEH_ENTER_SCOPE(&_SEHTryLevel); \
385  _SEH2TryLevelP = &_SEHTryLevel; \
386  } \
387  else \
388  { \
389  if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) > 0) \
390  _SEHHandleTryLevel.SHT_Common.ST_Filter = (void *)1; \
391  else \
392  { \
393  __SEH_DEFINE_EXCEPT(_SEHExcept) \
394  { \
395  __SEH_RETURN_EXCEPT((__VA_ARGS__)); \
396  } \
397  \
398  _SEHHandleTryLevel.SHT_Common.ST_Filter = &_SEHExcept; \
399  } \
400  \
401  _SEHHandleTryLevel.SHT_Common.ST_Next = _SEHPrevTryLevelP; \
402  _SEH2TryLevelP = &_SEHHandleTryLevel.SHT_Common; \
403  \
404  if(__builtin_expect(__SEH_ENTER_HANDLE_SCOPE(&_SEHHandleTryLevel, &&_SEHBeginExcept), 0)) \
405  goto _SEHBeginExcept; \
406  } \
407  } \
408  \
409  goto _SEHDoTry; \
410  \
411  __attribute__((unused)) __SEH_DEFINE_FINALLY(_SEHFinally) { __SEH_RETURN_FINALLY(); } \
412  \
413  _SEHAfterTry:; \
414  __SEH_LEAVE_TRYLEVEL(); \
415  \
416  goto _SEHEndExcept; \
417  \
418  _SEHBeginExcept:; \
419  { \
420  { \
421  __SEH_BARRIER;
422 
423 #define _SEH2_END \
424  __SEH_BARRIER; \
425  } \
426  } \
427  \
428  _SEHEndExcept:; \
429  \
430  __SEH_LEAVE_FRAME(); \
431  } \
432  __SEH_END_SCOPE;
433 
434 #define _SEH2_GetExceptionInformation() (_SEHExceptionInformation)
435 #define _SEH2_GetExceptionCode() ((_SEH2FrameP)->SF_Code)
436 #define _SEH2_AbnormalTermination() (_SEHAbnormalTermination)
437 
438 #define _SEH2_YIELD(STMT_) \
439  for(;;) \
440  { \
441  if(!_SEH2ScopeKind) \
442  _SEH2Return(); \
443  \
444  STMT_; \
445  }
446 
447 #define _SEH2_LEAVE goto _SEHEndTry
448 
449 __SEH_END_SCOPE_CHAIN;
450 
451 #define _SEH2_VOLATILE volatile
452 
453 #else
454 #error no PSEH support
455 #endif
456 
457 #endif /* !KJK_PSEH2_H_ */
458 
459 /* EOF */
#define __cdecl
Definition: accygwin.h:79
void __cdecl _SEH2Return(void)
int _SEH2_VolatileExceptionCode
Definition: dummy.c:4
#define __attribute__(x)
Definition: wpp_private.h:207
void __cdecl _SEH2LeaveFrame(void)
int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t *frame, volatile _SEH2TryLevel_t *trylevel)
int _SEH2_Volatile0
Definition: dummy.c:3
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31