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