Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

874 lines
29 KiB

  1. /***
  2. *ehdata.h -
  3. *
  4. * Copyright (c) 1993-1995, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Declare misc. types, macros, etc. for implementation
  8. * of C++ Exception Handling for the run-time and the compiler.
  9. * Hardware independent, assumes Windows NT.
  10. *
  11. * Portions of this header file can be disabled by defining the following
  12. * macros:
  13. * _EHDATA_NOHEADERS - suppresses inclusion of standard header files
  14. * If this is specified, then appropriate typedefs or macros must
  15. * be provided by some other means.
  16. * _EHDATA_NOTHROW - suppresses definitions used only to describe a throw
  17. * _EHDATA_NOFUNCINFO - suppresses definitions for the frame descriptor
  18. * _EHDATA_NONT - suppresses definitions of our version of NT's stuff
  19. *
  20. * Other conditional compilation macros:
  21. * CC_EXPLICITFRAME - if true, representation of registration node includes
  22. * the value of the frame-pointer for that frame, making the location
  23. * of the registration node on the frame flexible. This is intended
  24. * primarily for early testing.
  25. *
  26. * [Internal]
  27. *
  28. *Revision History:
  29. * 05-20-93 BS Module Created.
  30. * 03-01-94 CFW Remove CONTEXT def for x86 for TiborL.
  31. * 03-03-94 TL Mips (_M_MRX000 >= 4000) changes
  32. * 09-02-94 SKS This header file added.
  33. * 09-12-94 GJF Merged in changes from/for DEC (Al Doser, dated 6/20,
  34. * and Bill Baxter, dated 6/28).
  35. * 11-06-94 GJF Changed pack pragma to 8 byte alignment.
  36. * 02-14-95 CFW Clean up Mac merge.
  37. * 03-22-95 PML Add const for read-only structs
  38. * 03-29-95 CFW Add error message to internal headers.
  39. * 04-14-95 JWM Added EH_ABORT_FRAME_UNWIND_PART for EH/SEH exception handling.
  40. * 04-20-95 TGL Added iFrameNestLevel field to MIPS FuncInfo
  41. * 04-27-95 JWM EH_ABORT_FRAME_UNWIND_PART now #ifdef ALLOW_UNWIND_ABORT.
  42. * 06-08-95 JWM Merged CRT version of ehdata.h into langapi source.
  43. *
  44. ****/
  45. #ifndef _INC_EHDATA
  46. #define _INC_EHDATA
  47. #if _M_IX86 >= 300 /*IFSTRIP=IGN*/
  48. # ifndef CC_EXPLICITFRAME
  49. # define CC_EXPLICITFRAME 0 // If non-zero, we're using a hack version of the
  50. // registration node.
  51. # endif
  52. #endif
  53. #ifndef _EHDATA_NOHEADERS
  54. #include <stddef.h>
  55. #include <excpt.h>
  56. #if defined(_WIN32)
  57. #include <windows.h>
  58. #else
  59. #include <nowin.h>
  60. #endif
  61. #endif /* _EHDATA_NOHEADERS */
  62. #pragma pack(push, ehdata, 4)
  63. #define EH_EXCEPTION_NUMBER ('msc' | 0xE0000000) // The NT Exception # that we use
  64. #define EH_MAGIC_NUMBER1 0x19930520 // The magic # identifying this version
  65. // As magic numbers increase, we have to keep track of
  66. // the versions that we are backwards compatible with.
  67. #define EH_EXCEPTION_PARAMETERS 3 // Number of parameters in exception record
  68. #ifdef ALLOW_UNWIND_ABORT
  69. #define EH_ABORT_FRAME_UNWIND_PART EH_EXCEPTION_NUMBER+1
  70. #endif
  71. //
  72. // PMD - Pointer to Member Data: generalized pointer-to-member descriptor
  73. //
  74. typedef struct PMD
  75. {
  76. ptrdiff_t mdisp; // Offset of intended data within base
  77. ptrdiff_t pdisp; // Displacement to virtual base pointer
  78. ptrdiff_t vdisp; // Index within vbTable to offset of base
  79. } PMD;
  80. //
  81. // PMFN - Pointer to Member Function
  82. // M00REVIEW: we may need something more than this, but this will do for now.
  83. //
  84. typedef void (*PMFN)(void);
  85. //
  86. // TypeDescriptor - per-type record which uniquely identifies the type.
  87. //
  88. // Each type has a decorated name which uniquely identifies it, and a hash
  89. // value which is computed by the compiler. The hash function used is not
  90. // important; the only thing which is essential is that it be the same for
  91. // all time.
  92. //
  93. // The special type '...' (ellipsis) is represented by a null name.
  94. //
  95. #pragma warning(disable:4200) // get rid of obnoxious nonstandard extension warning
  96. typedef struct TypeDescriptor
  97. {
  98. #if _RTTI
  99. const void * pVFTable; // Field overloaded by RTTI
  100. #else
  101. DWORD hash; // Hash value computed from type's decorated name
  102. #endif
  103. void * spare; // reserved, possible for RTTI
  104. char name[]; // The decorated name of the type; 0 terminated.
  105. } TypeDescriptor;
  106. #pragma warning(default:4200)
  107. #define TD_HASH(td) ((td).hash)
  108. #define TD_NAME(td) ((td).name)
  109. #define TD_IS_TYPE_ELLIPSIS(td) ((td == NULL) || (TD_NAME(*td)[0] == '\0'))
  110. #ifndef _EHDATA_NOTHROW
  111. /////////////////////////////////////////////////////////////////////////////
  112. //
  113. // Description of the thrown object. (M00REVIEW: not final)
  114. //
  115. // This information is broken down into three levels, to allow for maximum
  116. // comdat folding (at the cost of some extra pointers).
  117. //
  118. // ThrowInfo is the head of the description, and contains information about
  119. // the particular variant thrown.
  120. // CatchableTypeArray is an array of pointers to type descriptors. It will
  121. // be shared between objects thrown by reference but with varying
  122. // qualifiers.
  123. // CatchableType is the description of an individual type, and how to effect
  124. // the conversion from a given type.
  125. //
  126. //---------------------------------------------------------------------------
  127. //
  128. // CatchableType - description of a type that can be caught.
  129. //
  130. // Note: although isSimpleType can be part of ThrowInfo, it is more
  131. // convenient for the run-time to have it here.
  132. //
  133. typedef const struct _s_CatchableType {
  134. unsigned int properties; // Catchable Type properties (Bit field)
  135. TypeDescriptor *pType; // Pointer to the type descriptor for this type
  136. PMD thisDisplacement; // Pointer to instance of catch type within
  137. // thrown object.
  138. int sizeOrOffset; // Size of simple-type object or offset into
  139. // buffer of 'this' pointer for catch object
  140. PMFN copyFunction; // Copy constructor or CC-closure
  141. } CatchableType;
  142. #define CT_IsSimpleType 0x00000001 // type is a simple type
  143. #define CT_ByReferenceOnly 0x00000002 // type must be caught by reference
  144. #define CT_HasVirtualBase 0x00000004 // type is a class with virtual bases
  145. #define CT_PROPERTIES(ct) ((ct).properties)
  146. #define CT_PTD(ct) ((ct).pType)
  147. #define CT_THISDISP(ct) ((ct).thisDisplacement)
  148. #define CT_SIZE(ct) ((ct).sizeOrOffset)
  149. #define CT_COPYFUNC(ct) ((ct).copyFunction)
  150. #define CT_OFFSET(ct) ((ct).sizeOrOffset)
  151. #define CT_HASH(ct) (TD_HASH(*CT_PTD(ct)))
  152. #define CT_NAME(ct) (TD_NAME(*CT_PTD(ct)))
  153. #define SET_CT_ISSIMPLETYPE(ct) (CT_PROPERTIES(ct) |= CT_IsSimpleType)
  154. #define SET_CT_BYREFONLY(ct) (CT_PROPERTIES(ct) |= CT_ByReferenceOnly)
  155. #define SET_CT_HASVB(ct) (CT_PROPERTIES(ct) |= CT_HasVirtualBase)
  156. #define CT_ISSIMPLETYPE(ct) (CT_PROPERTIES(ct) & CT_IsSimpleType) // Is it a simple type?
  157. #define CT_BYREFONLY(ct) (CT_PROPERTIES(ct) & CT_ByReferenceOnly) // Must it be caught by reference?
  158. #define CT_HASVB(ct) (CT_PROPERTIES(ct) & CT_HasVirtualBase) // Is this type a class with virtual bases?
  159. //
  160. // CatchableTypeArray - array of pointers to catchable types, with length
  161. //
  162. #pragma warning(disable:4200) // get rid of obnoxious nonstandard extension warning
  163. typedef const struct _s_CatchableTypeArray {
  164. int nCatchableTypes;
  165. CatchableType *arrayOfCatchableTypes[];
  166. } CatchableTypeArray;
  167. #pragma warning(default:4200)
  168. //
  169. // ThrowInfo - information describing the thrown object, staticly built
  170. // at the throw site.
  171. //
  172. // pExceptionObject (the dynamic part of the throw; see below) is always a
  173. // reference, whether or not it is logically one. If 'isSimpleType' is true,
  174. // it is a reference to the simple type, which is 'size' bytes long. If
  175. // 'isReference' and 'isSimpleType' are both false, then it's a UDT or
  176. // a pointer to any type (ie pExceptionObject points to a pointer). If it's
  177. // a pointer, copyFunction is NULL, otherwise it is a pointer to a copy
  178. // constructor or copy constructor closure.
  179. //
  180. // The pForwardCompat function pointer is intended to be filled in by future
  181. // versions, so that if say a DLL built with a newer version (say C10) throws,
  182. // and a C9 frame attempts a catch, the frame handler attempting the catch (C9)
  183. // can let the version that knows all the latest stuff do the work.
  184. //
  185. typedef const struct _s_ThrowInfo {
  186. unsigned int attributes; // Throw Info attributes (Bit field)
  187. PMFN pmfnUnwind; // Destructor to call when exception
  188. // has been handled or aborted.
  189. int (__cdecl*pForwardCompat)(...); // Forward compatibility frame handler
  190. CatchableTypeArray *pCatchableTypeArray; // Pointer to list of pointers to types.
  191. } ThrowInfo;
  192. #define TI_IsConst 0x00000001 // thrown object has const qualifier
  193. #define TI_IsVolatile 0x00000002 // thrown object has volatile qualifier
  194. #define TI_IsUnaligned 0x00000004 // thrown object has unaligned qualifier
  195. #define THROW_ATTRS(t) ((t).attributes)
  196. #define THROW_UNWINDFUNC(t) ((t).pmfnUnwind)
  197. #define THROW_FORWARDCOMPAT(t) ((t).pForwardCompat)
  198. #define THROW_COUNT(t) ((t).pCatchableTypeArray->nCatchableTypes)
  199. #define THROW_CTLIST(t) ((t).pCatchableTypeArray->arrayOfCatchableTypes)
  200. #define THROW_PCTLIST(t) (&THROW_CTLIST(t))
  201. #define THROW_CT(t, n) (*THROW_CTLIST(t)[n])
  202. #define THROW_PCT(t, n) (THROW_CTLIST(t)[n])
  203. #define SET_TI_ISCONST(t) (THROW_ATTRS(t) |= TI_IsConst) // Is the object thrown 'const' qualified
  204. #define SET_TI_ISVOLATILE(t) (THROW_ATTRS(t) |= TI_IsVolatile) // Is the object thrown 'volatile' qualified
  205. #define SET_TI_ISUNALIGNED(t) (THROW_ATTRS(t) |= TI_IsUnaligned) // Is the object thrown 'unaligned' qualified
  206. #define THROW_ISCONST(t) (THROW_ATTRS(t) & TI_IsConst)
  207. #define THROW_ISVOLATILE(t) (THROW_ATTRS(t) & TI_IsVolatile)
  208. #define THROW_ISUNALIGNED(t) (THROW_ATTRS(t) & TI_IsUnaligned)
  209. //
  210. // Here's how to throw:
  211. // M00HACK: _ThrowInfo is the name of the type that is 'pre-injected' into the
  212. // compiler; since this prototype is known to the FE along with the pre-injected
  213. // types, it has to match exactly.
  214. //
  215. #if _MSC_VER >= 900 /*IFSTRIP=IGN*/
  216. extern "C" void __stdcall _CxxThrowException(void* pExceptionObject, _ThrowInfo* pThrowInfo);
  217. #else
  218. // If we're not self-building, we need to use the name that we defined above.
  219. extern "C" void __stdcall _CxxThrowException(void* pExceptionObject, ThrowInfo* pThrowInfo);
  220. #endif
  221. #endif /* _EHDATA_NOTHROW */
  222. #ifndef _EHDATA_NOFUNCINFO
  223. /////////////////////////////////////////////////////////////////////////////
  224. //
  225. // Describing 'try/catch' blocks:
  226. //
  227. //---------------------------------------------------------------------------
  228. //
  229. // Current state of a function.
  230. // -1 is the 'blank' state, ie there is nothing to unwind, no try blocks active.
  231. //
  232. typedef int __ehstate_t; // The type of a state index
  233. #define EH_EMPTY_STATE -1
  234. //
  235. // HandlerType - description of a single 'catch'
  236. //
  237. typedef const struct _s_HandlerType {
  238. unsigned int adjectives; // Handler Type adjectives (bitfield)
  239. TypeDescriptor *pType; // Pointer to the corresponding type descriptor
  240. ptrdiff_t dispCatchObj; // Displacement of catch object from base
  241. // of current stack frame.
  242. #if _M_MRX000 >= 4000 /*IFSTRIP=IGN*/
  243. ULONG frameNestLevel; // The static nesting level of parent function
  244. #endif
  245. void * addressOfHandler; // Address of 'catch' code
  246. } HandlerType;
  247. #define HT_IsConst 0x00000001 // type referenced is 'const' qualified
  248. #define HT_IsVolatile 0x00000002 // type referenced is 'volatile' qualified
  249. #define HT_IsUnaligned 0x00000004 // type referenced is 'unaligned' qualified
  250. #define HT_IsReference 0x00000008 // catch type is by reference
  251. #define HT_IsResumable 0x00000010 // the catch may choose to resume (Reserved)
  252. #define HT_ADJECTIVES(ht) ((ht).adjectives)
  253. #define HT_PTD(ht) ((ht).pType)
  254. #define HT_DISPCATCH(ht) ((ht).dispCatchObj)
  255. #if _M_MRX000 >= 4000 /*IFSTRIP=IGN*/
  256. #define HT_FRAMENEST(ht) ((ht).frameNestLevel)
  257. #endif
  258. #define HT_HANDLER(ht) ((ht).addressOfHandler)
  259. #define HT_NAME(ht) (TD_NAME(*HT_PTD(ht)))
  260. #define HT_HASH(ht) (TD_HASH(*HT_PTD(ht)))
  261. #define HT_IS_TYPE_ELLIPSIS(ht) TD_IS_TYPE_ELLIPSIS(HT_PTD(ht))
  262. #define SET_HT_ISCONST(ht) (HT_ADJECTIVES(ht) |= HT_IsConst)
  263. #define SET_HT_ISVOLATILE(ht) (HT_ADJECTIVES(ht) |= HT_IsVolatile)
  264. #define SET_HT_ISUNALIGNED(ht) (HT_ADJECTIVES(ht) |= HT_IsUnaligned)
  265. #define SET_HT_ISREFERENCE(ht) (HT_ADJECTIVES(ht) |= HT_IsReference)
  266. #define SET_HT_ISRESUMABLE(ht) (HT_ADJECTIVES(ht) |= HT_IsResumable)
  267. #define HT_ISCONST(ht) (HT_ADJECTIVES(ht) & HT_IsConst) // Is the type referenced 'const' qualified
  268. #define HT_ISVOLATILE(ht) (HT_ADJECTIVES(ht) & HT_IsVolatile) // Is the type referenced 'volatile' qualified
  269. #define HT_ISUNALIGNED(ht) (HT_ADJECTIVES(ht) & HT_IsUnaligned) // Is the type referenced 'unaligned' qualified
  270. #define HT_ISREFERENCE(ht) (HT_ADJECTIVES(ht) & HT_IsReference) // Is the catch type by reference
  271. #define HT_ISRESUMABLE(ht) (HT_ADJECTIVES(ht) & HT_IsResumable) // Might the catch choose to resume (Reserved)
  272. //
  273. // HandlerMapEntry - associates a handler list (sequence of catches) with a
  274. // range of eh-states.
  275. //
  276. typedef const struct _s_TryBlockMapEntry {
  277. __ehstate_t tryLow; // Lowest state index of try
  278. __ehstate_t tryHigh; // Highest state index of try
  279. #if !defined(_M_ALPHA) && !defined(_M_IA64)
  280. __ehstate_t catchHigh; // Highest state index of any associated catch
  281. #endif
  282. int nCatches; // Number of entries in array
  283. HandlerType *pHandlerArray; // List of handlers for this try
  284. } TryBlockMapEntry;
  285. #define TBME_LOW(hm) ((hm).tryLow)
  286. #define TBME_HIGH(hm) ((hm).tryHigh)
  287. #if !defined(_M_IA64)
  288. #define TBME_CATCHHIGH(hm) ((hm).catchHigh)
  289. #endif // !defined(_M_IA64)
  290. #define TBME_NCATCHES(hm) ((hm).nCatches)
  291. #define TBME_PLIST(hm) ((hm).pHandlerArray)
  292. #define TBME_CATCH(hm, n) (TBME_PLIST(hm)[n])
  293. #define TBME_PCATCH(hm, n) (&(TBME_PLIST(hm)[n]))
  294. /////////////////////////////////////////////////////////////////////////////
  295. //
  296. // Description of the function:
  297. //
  298. //---------------------------------------------------------------------------
  299. //
  300. // UnwindMapEntry - Description of each state transition for unwinding
  301. // the stack (ie destructing objects).
  302. //
  303. // The unwind map is an array, indexed by current state. Each entry specifies
  304. // the state to go to during unwind, and the action required to get there.
  305. // Note that states are represented by a signed integer, and that the 'blank'
  306. // state is -1 so that the array remains 0-based (because by definition there
  307. // is never any unwind action to be performed from state -1). It is also
  308. // assumed that state indices will be dense, ie that there will be no gaps of
  309. // unused state indices in a function.
  310. //
  311. typedef const struct _s_UnwindMapEntry {
  312. __ehstate_t toState; // State this action takes us to
  313. void (*action)(void); // Funclet to call to effect state change
  314. } UnwindMapEntry;
  315. #define UWE_TOSTATE(uwe) ((uwe).toState)
  316. #define UWE_ACTION(uwe) ((uwe).action)
  317. #if _M_MRX000 >= 4000 || defined(_M_MPPC) || defined(_M_PPC) /*IFSTRIP=IGN*/
  318. typedef struct IptoStateMapEntry {
  319. ULONG Ip;
  320. __ehstate_t State;
  321. } IptoStateMapEntry;
  322. #endif
  323. //
  324. // FuncInfo - all the information that describes a function with exception
  325. // handling information.
  326. //
  327. typedef const struct _s_FuncInfo
  328. {
  329. unsigned int magicNumber; // Identifies version of compiler
  330. __ehstate_t maxState; // Highest state number plus one (thus
  331. // number of entries in unwind map)
  332. UnwindMapEntry *pUnwindMap; // Where the unwind map is
  333. unsigned int nTryBlocks; // Number of 'try' blocks in this function
  334. TryBlockMapEntry *pTryBlockMap; // Where the handler map is
  335. #if defined(_M_ALPHA)
  336. signed int EHContextDelta; // Frame offset of EHContext record
  337. #endif
  338. unsigned int nIPMapEntries; // # entries in the IP-to-state map. NYI (reserved)
  339. #if _M_MRX000 >= 4000 /*IFSTRIP=IGN*/
  340. IptoStateMapEntry *pIPtoStateMap; // An IP to state map..
  341. ptrdiff_t dispUnwindHelp; // Displacement of unwind helpers from base
  342. int iTryBlockIndex; // Used by catch functions only
  343. int iFrameNestLevel; // The static nesting level of parent function
  344. #elif defined(_M_MPPC) || defined(_M_PPC)
  345. IptoStateMapEntry *pIPtoStateMap; // An IP to state map..
  346. #else
  347. void *pIPtoStateMap; // An IP to state map. NYI (reserved).
  348. #endif
  349. } FuncInfo;
  350. #define FUNC_MAGICNUM(fi) ((fi).magicNumber)
  351. #define FUNC_MAXSTATE(fi) ((fi).maxState)
  352. #define FUNC_NTRYBLOCKS(fi) ((fi).nTryBlocks)
  353. #define FUNC_NIPMAPENT(fi) ((fi).nIPMapEntries)
  354. #define FUNC_PUNWINDMAP(fi) ((fi).pUnwindMap)
  355. #define FUNC_PHANDLERMAP(fi) ((fi).pTryBlockMap)
  356. #if defined(_M_ALPHA)
  357. #define FUNC_EHCONTEXTDELTA(fi) ((fi).EHContextDelta)
  358. #endif
  359. #define FUNC_IPMAP(fi) ((fi).pIPtoStateMap)
  360. #define FUNC_UNWIND(fi, st) ((fi).pUnwindMap[st])
  361. #define FUNC_PUNWIND(fi, st) (&FUNC_UNWIND(fi, st))
  362. #define FUNC_TRYBLOCK(fi,n) ((fi).pTryBlockMap[n])
  363. #define FUNC_PTRYBLOCK(fi,n) (&FUNC_TRYBLOCK(fi, n))
  364. #if _M_MRX000 >= 4000 /*IFSTRIP=IGN*/
  365. #define FUNC_IPTOSTATE(fi,n) ((fi).pIPtoStateMap[n])
  366. #define FUNC_PIPTOSTATE(fi,n) (&FUNC_IPTOSTATE(fi,n))
  367. #define FUNC_DISPUNWINDHELP(fi) ((fi).dispUnwindHelp)
  368. #define FUNC_TRYBLOCKINDEX(fi) ((fi).iTryBlockIndex)
  369. #define FUNC_FRAMENEST(fi) ((fi).iFrameNestLevel)
  370. #elif defined(_M_MPPC) || defined(_M_PPC)
  371. #define FUNC_IPTOSTATE(fi,n) ((fi).pIPtoStateMap[n])
  372. #define FUNC_PIPTOSTATE(fi,n) (&FUNC_IPTOSTATE(fi,n))
  373. #elif defined(_M_IA64)
  374. #define FUNC_UNWIND(fi, st) ((fi).pUnwindMap[st])
  375. #define FUNC_PUNWIND(fi, st) (&FUNC_UNWIND(fi, st))
  376. #define FUNC_TRYBLOCK(fi,n) ((fi).pTryBlockMap[n])
  377. #define FUNC_PTRYBLOCK(fi,n) (&FUNC_TRYBLOCK(fi, n))
  378. #else
  379. #define FUNC_IPTOSTATE(fi,n) __ERROR_NYI__
  380. #endif
  381. #endif /* _EHDATA_NOFUNCINFO */
  382. #ifndef _EHDATA_NONT
  383. /////////////////////////////////////////////////////////////////////////////
  384. //
  385. // Data types that are variants of data used by NT (and Chicago) to manage
  386. // exception handling.
  387. //
  388. //---------------------------------------------------------------------------
  389. /////////////////////////////////////////////////////////////////////////////
  390. //
  391. // A stack registration node (i386 only)
  392. //
  393. #if _M_IX86 >= 300 /*IFSTRIP=IGN*/
  394. struct EHRegistrationNode {
  395. /* void * stackPtr */ // Stack ptr at entry to try (below address point)
  396. EHRegistrationNode *pNext; // Next node in the chain
  397. void * frameHandler; // The handler function for this frame
  398. __ehstate_t state; // The current state of this function
  399. #if CC_EXPLICITFRAME
  400. void * frame; // Value of ebp for this frame
  401. #endif
  402. };
  403. #if !CC_EXPLICITFRAME
  404. // Cannonical offset
  405. # define FRAME_OFFSET sizeof(EHRegistrationNode)
  406. #endif
  407. #define PRN_NEXT(prn) ((prn)->pNext)
  408. #define PRN_HANDLER(prn) ((prn)->frameHandler)
  409. #define PRN_STATE(prn) ((prn)->state)
  410. #define PRN_STACK(prn) (((void**)(prn))[-1])
  411. #if CC_EXPLICITFRAME
  412. # define PRN_FRAME(prn) ((prn)->frame)
  413. #else
  414. # define PRN_FRAME(prn) ((void*)(((char*)prn) + FRAME_OFFSET))
  415. #endif
  416. typedef void DispatcherContext; // Meaningless on Intel
  417. #elif _M_MRX000 >= 4000 /*IFSTRIP=IGN*/
  418. //
  419. // On MIPS we don't have a registration node, just a pointer to the stack frame base
  420. //
  421. typedef ULONG EHRegistrationNode;
  422. #define PRN_NEXT(prn) __ERROR__
  423. #define PRN_HANDLER(prn) __ERROR__
  424. #define PRN_STATE(prn) __ERROR__
  425. #define PRN_STACK(prn) __ERROR__
  426. #define PRN_FRAME(prn) __ERROR__
  427. #define FRAME_OFFSET 0
  428. #if !defined(_NTSUBSET_)
  429. typedef struct _RUNTIME_FUNCTION {
  430. ULONG BeginAddress;
  431. ULONG EndAddress;
  432. EXCEPTION_DISPOSITION (*ExceptionHandler)();
  433. PVOID HandlerData;
  434. ULONG PrologEndAddress;
  435. } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
  436. #endif
  437. typedef struct _xDISPATCHER_CONTEXT {
  438. ULONG ControlPc;
  439. PRUNTIME_FUNCTION FunctionEntry;
  440. ULONG EstablisherFrame;
  441. PCONTEXT ContextRecord;
  442. } DispatcherContext; // changed the case of the name to conform to EH conventions
  443. #elif defined(_M_ALPHA)
  444. //
  445. // On Alpha we don't have a registration node,
  446. // just a pointer to the stack frame base
  447. //
  448. typedef ULONG EHRegistrationNode;
  449. #define PRN_NEXT(prn) __ERROR__
  450. #define PRN_HANDLER(prn) __ERROR__
  451. #define PRN_STATE(prn) __ERROR__
  452. #define PRN_STACK(prn) __ERROR__
  453. #define PRN_FRAME(prn) __ERROR__
  454. #define FRAME_OFFSET 0
  455. #if !defined(_NTSUBSET_)
  456. typedef struct _RUNTIME_FUNCTION {
  457. ULONG BeginAddress;
  458. ULONG EndAddress;
  459. EXCEPTION_DISPOSITION (*ExceptionHandler)();
  460. PVOID HandlerData; // ptr to FuncInfo record
  461. ULONG PrologEndAddress;
  462. } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
  463. #endif
  464. typedef struct _xDISPATCHER_CONTEXT {
  465. ULONG ControlPc;
  466. PRUNTIME_FUNCTION FunctionEntry;
  467. ULONG EstablisherFrame; // Virtual Frame Pointer
  468. PCONTEXT ContextRecord;
  469. } DispatcherContext; // changed the case of the name to conform to EH conventions
  470. //
  471. // _EHCONTEXT is a struct built in the frame by the compiler.
  472. // On entry to a function, compiler generated code stores the
  473. // address of the base of the fixed frame area (the so-called
  474. // Real Frame Pointer) into the Rfp. On every state transition,
  475. // compiler generated code stores the current state index into
  476. // the State field.
  477. //
  478. // The FuncInfo record for the function contains the offset of
  479. // the _EHCONTEXT record from the Virtual Frame Pointer - a
  480. // pointer to the highest address of the frame so this offset
  481. // is negative (frames grow down in the address space).
  482. //
  483. typedef struct _EHCONTEXT {
  484. ULONG State;
  485. PVOID Rfp;
  486. } EHContext;
  487. #define VIRTUAL_FP(pDC) (pDC->EstablisherFrame)
  488. #define REAL_FP(VirtualFP, pFuncInfo) \
  489. (((EHContext *)((char *)VirtualFP \
  490. + pFuncInfo->EHContextDelta)) -> Rfp)
  491. #define EH_STATE(VirtualFP, pFuncInfo) \
  492. (((EHContext *)((char *)VirtualFP \
  493. + pFuncInfo->EHContextDelta)) -> State)
  494. #elif defined(_M_M68K)
  495. struct EHRegistrationNode {
  496. /* void * _sp; // The stack pointer for the entry of try/catch */
  497. void * frameHandler; // The handler function for this frame
  498. __ehstate_t state; // The current state of this function
  499. };
  500. #define PRN_HANDLER(prn) ((prn)->frameHandler)
  501. #define PRN_STATE(prn) ((prn)->state)
  502. typedef void DispatcherContext; // Meaningless on Mac
  503. #elif defined(_M_PPC) || defined(_M_MPPC)
  504. //
  505. // On PowerPC we don't have a registration node, just a pointer to the stack
  506. // frame base
  507. //
  508. typedef ULONG EHRegistrationNode;
  509. #define PRN_NEXT(prn) __ERROR__
  510. #define PRN_HANDLER(prn) __ERROR__
  511. #define PRN_STATE(prn) __ERROR__
  512. #define PRN_STACK(prn) __ERROR__
  513. #define PRN_FRAME(prn) __ERROR__
  514. #define FRAME_OFFSET 0
  515. #if !defined(_NTSUBSET_)
  516. typedef struct _RUNTIME_FUNCTION {
  517. ULONG BeginAddress;
  518. ULONG EndAddress;
  519. EXCEPTION_DISPOSITION (*ExceptionHandler)(...);
  520. PVOID HandlerData;
  521. ULONG PrologEndAddress;
  522. } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
  523. #endif
  524. typedef struct _xDISPATCHER_CONTEXT {
  525. ULONG ControlPc;
  526. PRUNTIME_FUNCTION FunctionEntry;
  527. ULONG EstablisherFrame;
  528. PCONTEXT ContextRecord;
  529. } DispatcherContext;
  530. // changed the case of the name to conform to EH conventions
  531. #if defined(_M_MPPC)
  532. typedef struct _ftinfo {
  533. ULONG dwMagicNumber; // magic number
  534. void *pFrameInfo; // pointer to runtime frame info
  535. PRUNTIME_FUNCTION rgFuncTable; // function table
  536. ULONG cFuncTable; // number of function entry
  537. ULONG dwEntryCF; // address of starting of the code fragment
  538. ULONG dwSizeCF; // size of the code fragment
  539. } FTINFO, *PFTINFO;
  540. #define offsFTINFO 64
  541. #endif
  542. #elif defined(_M_IA64)
  543. #if !defined(_NTSUBSET_)
  544. struct _CONTEXT;
  545. struct _EXCEPTION_RECORD;
  546. typedef __int64 ULONGLONG;
  547. typedef
  548. EXCEPTION_DISPOSITION
  549. (*PEXCEPTION_ROUTINE) (
  550. IN struct _EXCEPTION_RECORD *ExceptionRecord,
  551. IN PVOID EstablisherFrame,
  552. IN OUT struct _CONTEXT *ContextRecord,
  553. IN OUT PVOID DispatcherContext
  554. );
  555. typedef struct _UNWIND_INFO {
  556. USHORT Version; // Version Number
  557. USHORT Flags; // Flags
  558. ULONG DataLength; // Length of Descriptor Data
  559. PVOID Descriptors; // Unwind Descriptors
  560. } UNWIND_INFO, *PUNWIND_INFO;
  561. typedef union _FRAME_POINTERS {
  562. struct {
  563. ULONG MemoryStackFp;
  564. ULONG BackingStoreFp;
  565. };
  566. ULONGLONG FramePointers; // used to force 8-byte alignment
  567. } FRAME_POINTERS, *PFRAME_POINTERS;
  568. typedef struct _RUNTIME_FUNCTION {
  569. ULONG BeginAddress;
  570. ULONG EndAddress;
  571. PEXCEPTION_ROUTINE ExceptionHandler;
  572. PVOID HandlerData;
  573. PUNWIND_INFO UnwindData;
  574. } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
  575. #endif
  576. //
  577. // On IA64 we don't have a registration node, just a pointer to the stack
  578. // frame base and backing store base.
  579. //
  580. typedef FRAME_POINTERS EHRegistrationNode;
  581. #define PRN_NEXT(prn) __ERROR__
  582. #define PRN_HANDLER(prn) __ERROR__
  583. #define PRN_STATE(prn) __ERROR__
  584. #define PRN_STACK(prn) __ERROR__
  585. #define PRN_FRAME(prn) __ERROR__
  586. typedef struct _xDISPATCHER_CONTEXT {
  587. FRAME_POINTERS EstablisherFrame;
  588. ULONG ControlPc;
  589. struct _RUNTIME_FUNCTION *FunctionEntry;
  590. PCONTEXT ContextRecord;
  591. } DispatcherContext, *pDispatcherContext;
  592. typedef struct _EHContext {
  593. PVOID Psp;
  594. LONG State;
  595. } EHContext;
  596. #define EH_STATE_OFFSET -12
  597. #define EH_STATE(pRN) \
  598. (*(int*)(pRN->MemoryStackFp + EH_STATE_OFFSET))
  599. #else
  600. #error "Machine not supported"
  601. #endif
  602. /////////////////////////////////////////////////////////////////////////////
  603. //
  604. // The NT Exception record that we use to pass information from the throw to
  605. // the possible catches.
  606. //
  607. // The constants in the comments are the values we expect.
  608. // This is based on the definition of EXCEPTION_RECORD in winnt.h.
  609. //
  610. typedef struct EHExceptionRecord {
  611. DWORD ExceptionCode; // The code of this exception. (= EH_EXCEPTION_NUMBER)
  612. DWORD ExceptionFlags; // Flags determined by NT
  613. struct _EXCEPTION_RECORD *ExceptionRecord; // An extra exception record (not used)
  614. void * ExceptionAddress; // Address at which exception occurred
  615. DWORD NumberParameters; // Number of extended parameters. (= EH_EXCEPTION_PARAMETERS)
  616. struct EHParameters {
  617. DWORD magicNumber; // = EH_MAGIC_NUMBER1
  618. void * pExceptionObject; // Pointer to the actual object thrown
  619. ThrowInfo *pThrowInfo; // Description of thrown object
  620. } params;
  621. } EHExceptionRecord;
  622. #define PER_CODE(per) ((per)->ExceptionCode)
  623. #define PER_FLAGS(per) ((per)->ExceptionFlags)
  624. #define PER_NEXT(per) ((per)->ExceptionRecord)
  625. #define PER_ADDRESS(per) ((per)->ExceptionAddress)
  626. #define PER_NPARAMS(per) ((per)->NumberParameters)
  627. #define PER_MAGICNUM(per) ((per)->params.magicNumber)
  628. #define PER_PEXCEPTOBJ(per) ((per)->params.pExceptionObject)
  629. #define PER_PTHROW(per) ((per)->params.pThrowInfo)
  630. #define PER_THROW(per) (*PER_PTHROW(per))
  631. #define PER_ISSIMPLETYPE(t) (PER_THROW(t).isSimpleType)
  632. #define PER_ISREFERENCE(t) (PER_THROW(t).isReference)
  633. #define PER_ISCONST(t) (PER_THROW(t).isConst)
  634. #define PER_ISVOLATILE(t) (PER_THROW(t).isVolatile)
  635. #define PER_ISUNALIGNED(t) (PER_THROW(t).isUnaligned)
  636. #define PER_UNWINDFUNC(t) (PER_THROW(t).pmfnUnwind)
  637. #define PER_PCTLIST(t) (PER_THROW(t).pCatchable)
  638. #define PER_CTLIST(t) (*PER_PCTLIST(t))
  639. #define PER_IS_MSVC_EH(per) ((PER_CODE(per) == EH_EXCEPTION_NUMBER) && \
  640. (PER_NPARAMS(per) == EH_EXCEPTION_PARAMETERS) && \
  641. (PER_MAGICNUM(per) == EH_MAGIC_NUMBER1))
  642. /////////////////////////////////////////////////////////////////////////////
  643. //
  644. // NT kernel routines and definitions required to implement exception handling:
  645. //
  646. // (from ntxcapi.h, which is not a public header file)
  647. //
  648. //---------------------------------------------------------------------------
  649. #ifndef _NTXCAPI_
  650. // begin_ntddk
  651. //
  652. // Exception flag definitions.
  653. //
  654. // begin_winnt
  655. #define EXCEPTION_NONCONTINUABLE 0x1 // Noncontinuable exception
  656. // end_winnt
  657. // end_ntddk
  658. #define EXCEPTION_UNWINDING 0x2 // Unwind is in progress
  659. #define EXCEPTION_EXIT_UNWIND 0x4 // Exit unwind is in progress
  660. #define EXCEPTION_STACK_INVALID 0x8 // Stack out of limits or unaligned
  661. #define EXCEPTION_NESTED_CALL 0x10 // Nested exception handler call
  662. #define EXCEPTION_TARGET_UNWIND 0x20 // Target unwind in progress
  663. #define EXCEPTION_COLLIDED_UNWIND 0x40 // Collided exception handler call
  664. #define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | \
  665. EXCEPTION_TARGET_UNWIND | EXCEPTION_COLLIDED_UNWIND)
  666. #define IS_UNWINDING(Flag) ((Flag & EXCEPTION_UNWIND) != 0)
  667. #define IS_DISPATCHING(Flag) ((Flag & EXCEPTION_UNWIND) == 0)
  668. #define IS_TARGET_UNWIND(Flag) (Flag & EXCEPTION_TARGET_UNWIND)
  669. #define IS_EXIT_UNWIND(Flag) (Flag & EXCEPTION_EXIT_UNWIND)
  670. #if !defined(_M_M68K)
  671. #ifdef __cplusplus
  672. extern "C" {
  673. #endif
  674. void WINAPI
  675. RtlUnwind (
  676. IN void * TargetFrame OPTIONAL,
  677. IN void * TargetIp OPTIONAL,
  678. IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
  679. IN void * ReturnValue
  680. );
  681. #if defined(_M_ALPHA)
  682. #define STATUS_UNWIND 0xc0000027
  683. void WINAPI
  684. RtlUnwindRfp (
  685. IN void * TargetRealFrame OPTIONAL,
  686. IN void * TargetIp OPTIONAL,
  687. IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
  688. IN void * ReturnValue
  689. );
  690. #endif
  691. #if defined(_M_PPC)
  692. ULONG WINAPI
  693. RtlVirtualUnwind (
  694. IN ULONG ControlPc,
  695. IN PRUNTIME_FUNCTION FunctionEntry,
  696. IN OUT PCONTEXT ContextRecord,
  697. OUT PBOOLEAN InFunction,
  698. OUT PULONG EstablisherFrame,
  699. IN OUT PVOID ContextPointers OPTIONAL,
  700. IN ULONG LowStackLimit,
  701. IN ULONG HighStackLimit
  702. );
  703. PRUNTIME_FUNCTION
  704. RtlLookupFunctionEntry (
  705. IN ULONG ControlPc
  706. );
  707. #endif
  708. #if defined(_M_MPPC)
  709. ULONG WINAPI
  710. RtlVirtualUnwind (
  711. IN ULONG ControlPc,
  712. IN PRUNTIME_FUNCTION FunctionEntry,
  713. IN OUT PCONTEXT ContextRecord,
  714. OUT PBOOLEAN InFunction,
  715. OUT PULONG EstablisherFrame,
  716. IN OUT PVOID ContextPointers OPTIONAL,
  717. IN ULONG LowStackLimit,
  718. IN ULONG HighStackLimit
  719. );
  720. PRUNTIME_FUNCTION
  721. RtlLookupFunctionEntry (
  722. IN PRUNTIME_FUNCTION RuntimeFunction,
  723. IN ULONG ControlPc,
  724. IN ULONG Rtoc
  725. );
  726. VOID
  727. RtlRaiseException (
  728. IN PEXCEPTION_RECORD ExceptionRecord
  729. );
  730. #endif
  731. #ifdef __cplusplus
  732. }
  733. #endif
  734. #endif
  735. #endif /* _NTXCAPI_ */
  736. #endif /* _EHDATA_NONT */
  737. #pragma pack(pop, ehdata)
  738. #endif /* _INC_EHDATA */