// // Declares internal C++ exception handling data structures. // This file is preprocessed and then the preprocessed results are force-included into every C++ TU. // // Copyright (c) Microsoft Corporation. All rights reserved. // #ifndef _INC_EHDATA_FORCEINCLUDE #define _INC_EHDATA_FORCEINCLUDE #pragma once #ifdef BUILDING_C1XX_FORCEINCLUDE #define PMD _PMD #define PMFN _PMFN #define TypeDescriptor _TypeDescriptor #define CatchableType _CatchableType #define _s_CatchableType _s__CatchableType #define CatchableTypeArray _CatchableTypeArray #define _s_CatchableTypeArray _s__CatchableTypeArray #define ThrowInfo _ThrowInfo #define _s_ThrowInfo _s__ThrowInfo #endif #if defined(_M_CEE_PURE) || defined(BUILDING_C1XX_FORCEINCLUDE) #define _EH_RELATIVE_TYPEINFO 0 #define _EH_RELATIVE_FUNCINFO 0 #define _RTTI_RELATIVE_TYPEINFO 0 #elif defined(_CHPE_X86_ARM64_EH_) #define _EH_RELATIVE_TYPEINFO 0 #define _EH_RELATIVE_FUNCINFO 1 #define _RTTI_RELATIVE_TYPEINFO 0 #elif defined(_M_X64) || defined(_M_ARM64) #define _EH_RELATIVE_TYPEINFO 1 #define _EH_RELATIVE_FUNCINFO 1 #define _RTTI_RELATIVE_TYPEINFO 1 #else #define _EH_RELATIVE_TYPEINFO 0 #define _EH_RELATIVE_FUNCINFO 0 #define _RTTI_RELATIVE_TYPEINFO 0 #endif #pragma pack(push, ehdata, 4) // // PMD - Pointer to Member Data: generalized pointer-to-member descriptor // typedef struct PMD { int mdisp; // Offset of intended data within base int pdisp; // Displacement to virtual base pointer int vdisp; // Index within vbTable to offset of base } PMD; // // PMFN - Pointer to Member Function // #if _EH_RELATIVE_TYPEINFO typedef int PMFN; // Image relative offset of Member Function #else typedef void (__cdecl * PMFN)(void*); #endif typedef void* (__stdcall * PGETWINRT_OOM_EXCEPTION)(); // // TypeDescriptor - per-type record which uniquely identifies the type. // // Each type has a decorated name which uniquely identifies it, and a hash // value which is computed by the compiler. The hash function used is not // important; the only thing which is essential is that it be the same for // all time. // // The special type '...' (ellipsis) is represented by a null name. // #pragma warning(push) #pragma warning(disable:4200) // nonstandard extension used: array of runtime bound #if defined(_M_X64) || defined(_M_ARM64) || defined(BUILDING_C1XX_FORCEINCLUDE) #pragma pack(push, TypeDescriptor, 8) #endif typedef struct TypeDescriptor { #if defined(_WIN64) || defined(_RTTI) || defined(BUILDING_C1XX_FORCEINCLUDE) const void * pVFTable; // Field overloaded by RTTI #else unsigned long hash; // Hash value computed from type's decorated name #endif void * spare; // reserved, possible for RTTI char name[]; // The decorated name of the type; 0 terminated. } TypeDescriptor; #if defined(_M_X64) || defined(_M_ARM64) || defined(BUILDING_C1XX_FORCEINCLUDE) #pragma pack(pop, TypeDescriptor) #endif #pragma warning(pop) ///////////////////////////////////////////////////////////////////////////// // // Description of the thrown object. // // This information is broken down into three levels, to allow for maximum // comdat folding (at the cost of some extra pointers). // // ThrowInfo is the head of the description, and contains information about // the particular variant thrown. // CatchableTypeArray is an array of pointers to type descriptors. It will // be shared between objects thrown by reference but with varying // qualifiers. // CatchableType is the description of an individual type, and how to effect // the conversion from a given type. // //--------------------------------------------------------------------------- // // CatchableType - description of a type that can be caught. // // Note: although isSimpleType can be part of ThrowInfo, it is more // convenient for the run-time to have it here. // typedef const struct _s_CatchableType { unsigned int properties; // Catchable Type properties (Bit field) #if _EH_RELATIVE_TYPEINFO int pType; // Image relative offset of TypeDescriptor #else TypeDescriptor * pType; // Pointer to the type descriptor for this type #endif PMD thisDisplacement; // Pointer to instance of catch type within thrown object. int sizeOrOffset; // Size of simple-type object or offset into // buffer of 'this' pointer for catch object PMFN copyFunction; // Copy constructor or CC-closure } CatchableType; // // CatchableTypeArray - array of pointers to catchable types, with length // #pragma warning (push) #pragma warning (disable:4200) // nonstandard extension used: array of runtime bound typedef const struct _s_CatchableTypeArray { int nCatchableTypes; #if _EH_RELATIVE_TYPEINFO int arrayOfCatchableTypes[]; // Image relative offset of Catchable Types #else CatchableType* arrayOfCatchableTypes[]; #endif } CatchableTypeArray; #pragma warning (pop) // // ThrowInfo - information describing the thrown object, statically built // at the throw site. // // pExceptionObject (the dynamic part of the throw; see below) is always a // reference, whether or not it is logically one. If 'isSimpleType' is true, // it is a reference to the simple type, which is 'size' bytes long. If // 'isReference' and 'isSimpleType' are both false, then it's a UDT or // a pointer to any type (i.e. pExceptionObject points to a pointer). If it's // a pointer, copyFunction is NULL, otherwise it is a pointer to a copy // constructor or copy constructor closure. // // The pForwardCompat function pointer is intended to be filled in by future // versions, so that if say a DLL built with a newer version (say C10) throws, // and a C9 frame attempts a catch, the frame handler attempting the catch (C9) // can let the version that knows all the latest stuff do the work. // typedef const struct _s_ThrowInfo { unsigned int attributes; // Throw Info attributes (Bit field) PMFN pmfnUnwind; // Destructor to call when exception has been handled or aborted #if _EH_RELATIVE_TYPEINFO && !defined(BUILDING_C1XX_FORCEINCLUDE) int pForwardCompat; // Image relative offset of Forward compatibility frame handler int pCatchableTypeArray; // Image relative offset of CatchableTypeArray #else int (__cdecl * pForwardCompat)(...); // Forward compatibility frame handler CatchableTypeArray* pCatchableTypeArray; // Pointer to list of pointers to types #endif } ThrowInfo; // // Here's how to throw: // _ThrowInfo is the name of the type that is 'pre-injected' into the // compiler (see macro above); since this prototype is known to the FE along with the pre-injected // types, it has to match exactly. // extern "C" __declspec(noreturn) void __stdcall _CxxThrowException( void* pExceptionObject, _ThrowInfo* pThrowInfo) noexcept(false); extern "C" int __cdecl __CxxExceptionFilter(void* ppExcept, void* pType, int adjectives, void *pBuildObj); #ifdef prepifdef prepifdef _MANAGED int __clrcall ___CxxExceptionFilter(void* ppExcept, void* pType, int adjectives, void *pBuildObj); prependif // _MANAGED #else #ifdef _MANAGED int __clrcall ___CxxExceptionFilter(void* ppExcept, void* pType, int adjectives, void *pBuildObj); #endif // _MANAGED #endif // Returns true if the object is really a C++ exception // If it is, stores the previous exception in *storage, and saves the current one // This is needed to keep track of the current exception object (used for rethrow & destruction) extern "C" int __cdecl __CxxRegisterExceptionObject(void *exception, void *storage); #ifdef prepifdef prepifdef _MANAGED int __clrcall ___CxxRegisterExceptionObject(void *exception, void *storage); prependif // _MANAGED #else #ifdef _MANAGED int __clrcall ___CxxRegisterExceptionObject(void *exception, void *storage); #endif // _MANAGED #endif // Returns true if exception is a C++ rethrown exception // This is needed, so Unregister can know whether or not to destroy the object extern "C" int __cdecl __CxxDetectRethrow(void *exception); #ifdef prepifdef prepifdef _MANAGED int __clrcall ___CxxDetectRethrow(void *exception); prependif // _MANAGED #else #ifdef _MANAGED int __clrcall ___CxxDetectRethrow(void *exception); #endif // _MANAGED #endif // Returns the byte count of stack space required to store the exception info extern "C" int __cdecl __CxxQueryExceptionSize(void); #ifdef prepifdef prepifdef _MANAGED int __clrcall ___CxxQueryExceptionSize(void); prependif // _MANAGED #else #ifdef _MANAGED int __clrcall ___CxxQueryExceptionSize(void); #endif // _MANAGED #endif // Pops the current exception, restoring the previous one from *storage // This detects whether or not the exception object needs to be destroyed extern "C" void __cdecl __CxxUnregisterExceptionObject(void *storage, int rethrow); #ifdef prepifdef prepifdef _MANAGED void __clrcall ___CxxUnregisterExceptionObject(void *storage, int rethrow); prependif // _MANAGED #else #ifdef _MANAGED void __clrcall ___CxxUnregisterExceptionObject(void *storage, int rethrow); #endif // _MANAGED #endif #pragma pack(pop, ehdata) #ifdef BUILDING_C1XX_FORCEINCLUDE #undef PMD #undef PMFN #undef TypeDescriptor #undef CatchableType #undef _s_CatchableType #undef CatchableTypeArray #undef _s_CatchableTypeArray #undef ThrowInfo #undef _s_ThrowInfo #endif #endif /* _INC_EHDATA_FORCEINCLUDE */