| 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 */ |