1 | /*
|
---|
2 | * excpt.h
|
---|
3 | *
|
---|
4 | * Experimental support for operating system level structured handling
|
---|
5 | * of exceptions.
|
---|
6 | *
|
---|
7 | * $Id: excpt.h,v 14fc79433294 2016/06/28 13:50:38 keithmarshall $
|
---|
8 | *
|
---|
9 | * Written by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
|
---|
10 | * Revised by Keith Marshall <keithmarshall@users.sourceforge.net>
|
---|
11 | * Copyright (C) 1997, 1999, 2001-2002, 2004, 2007, 2012, 2016,
|
---|
12 | * MinGW.org Project.
|
---|
13 | *
|
---|
14 | *
|
---|
15 | * Permission is hereby granted, free of charge, to any person obtaining a
|
---|
16 | * copy of this software and associated documentation files (the "Software"),
|
---|
17 | * to deal in the Software without restriction, including without limitation
|
---|
18 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
---|
19 | * and/or sell copies of the Software, and to permit persons to whom the
|
---|
20 | * Software is furnished to do so, subject to the following conditions:
|
---|
21 | *
|
---|
22 | * The above copyright notice, this permission notice, and the following
|
---|
23 | * disclaimer shall be included in all copies or substantial portions of
|
---|
24 | * the Software.
|
---|
25 | *
|
---|
26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
---|
27 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
---|
28 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
---|
29 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
---|
30 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
---|
31 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
|
---|
32 | * DEALINGS IN THE SOFTWARE.
|
---|
33 | *
|
---|
34 | */
|
---|
35 | #ifndef _EXCPT_H
|
---|
36 | #pragma GCC system_header
|
---|
37 | #define _EXCPT_H
|
---|
38 |
|
---|
39 | /* FIXME: this utility macro, to allocate stack space for any aggregate
|
---|
40 | * data type, with an explicit type cast of a pointer to that data type,
|
---|
41 | * deserves a place in a more universally accessible header file. The
|
---|
42 | * type cast is not strictly necessary for C, (but is permitted); it is
|
---|
43 | * essential for C++.
|
---|
44 | */
|
---|
45 | #define __typecast_alloca(type) (type *)(__builtin_alloca( sizeof(type) ))
|
---|
46 |
|
---|
47 | /* All MinGW CRT headers are required to include <_mingw.h>
|
---|
48 | */
|
---|
49 | #include <_mingw.h>
|
---|
50 |
|
---|
51 | /* Exception handler functions require definitions of _CONTEXT, and
|
---|
52 | * _EXCEPTION_RECORD structures, which are provided in <windef.h>
|
---|
53 | */
|
---|
54 | #include <windef.h>
|
---|
55 |
|
---|
56 | #ifndef _EXCPT_W32API_H
|
---|
57 | /* FIXME: These constants, structs, and typedefs should be defined
|
---|
58 | * in the Win32 API headers; (we need to establish where -- perhaps
|
---|
59 | * this header itself should be redesignated as a W32API header).
|
---|
60 | */
|
---|
61 | #define EH_NONCONTINUABLE 0x01
|
---|
62 | #define EH_UNWINDING 0x02
|
---|
63 | #define EH_EXIT_UNWIND 0x04
|
---|
64 | #define EH_STACK_INVALID 0x08
|
---|
65 | #define EH_NESTED_CALL 0x10
|
---|
66 |
|
---|
67 | #ifndef RC_INVOKED
|
---|
68 |
|
---|
69 | typedef enum
|
---|
70 | { ExceptionContinueExecution,
|
---|
71 | ExceptionContinueSearch,
|
---|
72 | ExceptionNestedException,
|
---|
73 | ExceptionCollidedUnwind
|
---|
74 | } EXCEPTION_DISPOSITION;
|
---|
75 |
|
---|
76 | #endif /* ! RC_INVOKED */
|
---|
77 | #endif /* !_EXCPT_W2API_H */
|
---|
78 |
|
---|
79 | #ifndef RC_INVOKED
|
---|
80 |
|
---|
81 | _BEGIN_C_DECLS
|
---|
82 |
|
---|
83 | /* The type of function that is expected as an exception handler,
|
---|
84 | * to be installed by the __try1(__handler) primitive.
|
---|
85 | */
|
---|
86 | typedef EXCEPTION_DISPOSITION (*PEXCEPTION_HANDLER)
|
---|
87 | (struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
|
---|
88 |
|
---|
89 | typedef struct _EXCEPTION_REGISTRATION
|
---|
90 | { /* Maps the structure of the exception handler registration
|
---|
91 | * block, as installed by the __try1(__handler) primitive.
|
---|
92 | */
|
---|
93 | struct _EXCEPTION_REGISTRATION *prev;
|
---|
94 | PEXCEPTION_HANDLER handler;
|
---|
95 | } EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION;
|
---|
96 |
|
---|
97 | /* Aliases which may be preferred, when referring to the
|
---|
98 | * EXCEPTION_REGISTRATION structure.
|
---|
99 | */
|
---|
100 | typedef EXCEPTION_REGISTRATION EXCEPTION_REGISTRATION_RECORD;
|
---|
101 | typedef PEXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION_RECORD;
|
---|
102 |
|
---|
103 | /* Deployment of exception handlers is facilitated by the pair
|
---|
104 | * of macros, __try1(_handler) and __except1.
|
---|
105 | *
|
---|
106 | * CAUTION: __try1(__handler) and __except1 must be deployed as
|
---|
107 | * a complementary pair, within the scope of the stack frame of
|
---|
108 | * a single function, with __try1(__handler) preceding the use
|
---|
109 | * of __except1. Failure to invoke __except1 before release of
|
---|
110 | * any stack frame, in which __try1(__handler) has been invoked,
|
---|
111 | * will invalidate the EXCEPTION_REGISTRATION_RECORD, which has
|
---|
112 | * been installed by __try1(_handler), at the head of the active
|
---|
113 | * exception handler chain; this will cause undefined behaviour,
|
---|
114 | * which is sure to go badly.
|
---|
115 | *
|
---|
116 | * To accommodate implementation differences between _WIN32 and
|
---|
117 | * _WIN64 hosts, the actual implementations of __try1(__handler)
|
---|
118 | * and __except1 are expressed in terms of a pair of lower level
|
---|
119 | * internal macros, namely:
|
---|
120 | *
|
---|
121 | * Macro: __try1_setup(__handler,__wsize,__ts)
|
---|
122 | *
|
---|
123 | * Helper for implementation of macro __try1(__handler); allocate
|
---|
124 | * a block of memory, within the stack frame of the calling function,
|
---|
125 | * which is then initialized as an EXCEPTION_REGISTRATION_RECORD, and
|
---|
126 | * linked to the head of the installed exception handler chain.
|
---|
127 | *
|
---|
128 | * Inputs:
|
---|
129 | * __handler pointer to an EXCEPTION_HANDLER function.
|
---|
130 | * __wsize the Intel host word size pointer description.
|
---|
131 | * __ts thread information segment register name.
|
---|
132 | */
|
---|
133 | #define __try1_setup(__handler,__wsize,__ts) \
|
---|
134 | { EXCEPTION_REGISTRATION *__hook; \
|
---|
135 | __hook = __typecast_alloca( EXCEPTION_REGISTRATION ); \
|
---|
136 | __hook->handler = __handler; \
|
---|
137 | __asm__ __volatile__ \
|
---|
138 | ( "mov{%z0}\t{%%|%0, "__wsize" }"__ts":{|[}0x0{, %0|]}\n\t" \
|
---|
139 | "mov{%z1}\t{%1, %%|"__wsize" }"__ts":{|[}0x0{|], %1}" \
|
---|
140 | :"=r"(__hook->prev):"r"(__hook):"memory" \
|
---|
141 | ); \
|
---|
142 | }
|
---|
143 |
|
---|
144 | /* Macro: __except1_teardown(__wsize,__ts)
|
---|
145 | *
|
---|
146 | * Helper which provides the implementation for the __except1
|
---|
147 | * complement to __try1(__handler) macro; it unlinks the first
|
---|
148 | * EXCEPTION_REGISTRATION_RECORD from the head of the exception
|
---|
149 | * handler chain. Arguments are as described for those of the
|
---|
150 | * same name, in the __try1_setup macro argument list.
|
---|
151 | */
|
---|
152 | #define __except1_teardown(__wsize,__ts) \
|
---|
153 | { register EXCEPTION_REGISTRATION *__hook; \
|
---|
154 | __asm__ __volatile__ \
|
---|
155 | ( "mov{%z0}\t{%%|%0, "__wsize" }"__ts":{|[}0x0{, %0|]}\n\t" \
|
---|
156 | "mov{%z0}\t{(}%0{)}, {|"__wsize" [}%0{|]}\n\t" \
|
---|
157 | "mov{%z0}\t{%0, %%|"__wsize" }"__ts":{|[}0x0{|], %0}" \
|
---|
158 | :"+r"(__hook)::"memory" \
|
---|
159 | ); \
|
---|
160 | }
|
---|
161 |
|
---|
162 | /* Specialization of the above primitives, creating __try1(__handler),
|
---|
163 | * and its complementary __except1 implementation, with the appropriate
|
---|
164 | * assignments of word size and TIB segment register, for each of...
|
---|
165 | */
|
---|
166 | #ifdef _WIN64
|
---|
167 | /* ...64-bit windows, for which the word size for representation of
|
---|
168 | * pointers, in Intel-syntax code, is "QWORD PTR", and the gs segment
|
---|
169 | * is used for access to the thread information block...
|
---|
170 | */
|
---|
171 | # define __try1(__handler) __try1_setup(__handler,"QWORD PTR","gs")
|
---|
172 | # define __except1 __except1_teardown("QWORD PTR","gs")
|
---|
173 |
|
---|
174 | #else /* _WIN32 */
|
---|
175 | /* ...while in 32-bit windows, the corresponding pointer word size
|
---|
176 | * is "DWORD PTR", and the the thread information block is located
|
---|
177 | * in the fs segment.
|
---|
178 | */
|
---|
179 | # define __try1(__handler) __try1_setup(__handler,"DWORD PTR","fs")
|
---|
180 | # define __except1 __except1_teardown("DWORD PTR","fs")
|
---|
181 | #endif
|
---|
182 |
|
---|
183 | _END_C_DECLS
|
---|
184 |
|
---|
185 | #endif /* ! RC_INVOKED */
|
---|
186 | #endif /* !_EXCPT_H: $RCSfile: excpt.h,v $: end of file */
|
---|