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