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