[1046] | 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 */
|
---|