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.

1995 lines
71 KiB

  1. /***
  2. *frame.cxx - The frame handler and everything associated with it.
  3. *
  4. * Copyright (c) 1993-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * The frame handler and everything associated with it.
  8. *
  9. * Entry points:
  10. * _CxxFrameHandler - the frame handler.
  11. *
  12. * Open issues:
  13. * Handling re-throw from dynamicly nested scope.
  14. * Fault-tolerance (checking for data structure validity).
  15. *
  16. *Revision History:
  17. * 05-20-93 BS Module created
  18. * 03-03-94 TL Added Mips specific code
  19. * 06-19-94 AD Added Alpha specific code (Al Dosser)
  20. * 10-17-94 BWT Disable code for PPC.
  21. * 11-23-94 JWM Removed obsolete 'hash' check in TypeMatch().
  22. * 11-29-94 JWM AdjustPointer() now adds in pdisp, not vdisp.
  23. * 01-13-95 JWM Added _NLG_Destination struct; dwCode set for catch
  24. * blocks & local destructors.
  25. * 02-09-95 JWM Mac merge.
  26. * 02-10-95 JWM UnhandledExceptionFilter() now called if exception
  27. * raised during stack unwind.
  28. * 03-22-95 PML Add const for read-only compiler-gen'd structs
  29. * 04-14-95 JWM Re-fix EH/SEH exception handling.
  30. * 04-17-95 JWM FrameUnwindFilter() must be #ifdef _WIN32.
  31. * 04-21-95 JWM _NLG_Destination moved to exsup3.asm (_M_X86 only).
  32. * 04-21-95 TGL Added Mips fixes.
  33. * 04-27-95 JWM EH_ABORT_FRAME_UNWIND_PART now #ifdef
  34. * ALLOW_UNWIND_ABORT.
  35. * 05-19-95 DAK Don't initialize the kernel handler
  36. * 06-07-95 JWM Various NLG additions.
  37. * 06-14-95 JWM Unneeded LastError calls removed.
  38. * 06-19-95 JWM NLG no longer uses per-thread data (X86 only).
  39. * 09-26-95 AMP PowerMac avoids re-throws to same catch clause
  40. * 08-06-95 JWM Typo fixed (Orion #6509); Alpha-specific.
  41. * 04-18-97 JWM In __InternalCxxFrameHandler(), 'recursive' changed to
  42. * BOOLEAN.
  43. * 06-01-97 TGL Added P7 specific code
  44. * 08-22-97 TGL More P7 fixes
  45. * 11-14-98 JWM Merge with P7 sources.
  46. * 02-11-99 TGL EH: correct catch in exe calling dll.
  47. * 05-17-99 PML Remove all Macintosh support.
  48. * 07-12-99 RDL Image relative fixes under CC_P7_SOFT25.
  49. * 10-17-99 PML Update EH state before each unwind action, instead of
  50. * once at end (vs7#5419)
  51. * 10-19-99 TGL More P7/Win64 fixes
  52. * 10-22-99 PML Add EHTRACE support
  53. * 12-10-99 GB Add Uncaught exception Support by adding a new function
  54. * __uncaught_exception();
  55. * 02-15-99 PML Can't put __try/__finally around call to
  56. * _UnwindNestedFrames (vs7#79460)
  57. * 03-03-00 GB made __DestructExceptionObject export from dll.
  58. * 03-21-00 KBF Check for C++ exception in __CxxExceptionFilter
  59. * 03-22-00 PML Remove CC_P7_SOFT25, which is now on permanently.
  60. * 03-28-00 GB Check for no buildobj in __CxxExceptionFilter.
  61. * 04-06-00 GB Added more functions for com+ eh support.
  62. * 04-19-00 GB ComPlus EH bug fixes.
  63. * 05-23-00 GB Don't catch BreakPoint generated Exceptions.
  64. * 05-30-00 GB ComPlus EH bug fixes.
  65. * 06-08-00 RDL VS#111429: IA64 workaround for AV while handling throw.
  66. * 06-21-00 GB Fix the difference in order of destruction and
  67. * construction depending on inlining.
  68. * 07-26-00 GB Fixed multiple destruction problem in COM+ eh.
  69. * 08-23-00 GB Fixed problem in BuildCatchObject when called from
  70. * __CxxExceptionFilter.
  71. * 02-23-01 PML Add __CxxCallUnwindDtor COM+ wrapper (vs7#217108)
  72. * 04-09-01 GB Add uncaught_exception support for COM+ C++ App.
  73. * 04-13-01 GB Fixed problems with Seh and catch(...). (vc7#236286)
  74. * 04-26-01 GB Fixed a problem with a rethrow without a throw
  75. * and catch(...)
  76. * 06-05-01 GB AMD64 Eh support Added.
  77. *
  78. ****/
  79. #include <stddef.h>
  80. #include <stdlib.h>
  81. #include <string.h>
  82. #include <malloc.h>
  83. #if defined(_NTSUBSET_)
  84. extern "C" {
  85. #include <nt.h>
  86. #include <ntrtl.h>
  87. #include <nturtl.h>
  88. #include <ntstatus.h> // STATUS_UNHANDLED_EXCEPTION
  89. #include <ntos.h>
  90. #include <ex.h> // ExRaiseException
  91. }
  92. #endif // defined(_NTSUBSET_)
  93. #include <windows.h>
  94. #include <internal.h>
  95. #include <mtdll.h> // CRT internal header file
  96. #include <ehassert.h> // This project's versions of standard assert macros
  97. #include <ehdata.h> // Declarations of all types used for EH
  98. #include <ehstate.h> // Declarations of state management stuff
  99. #include <eh.h> // User-visible routines for eh
  100. #include <ehhooks.h> // Declarations of hook variables and callbacks
  101. #include <trnsctrl.h> // Routines to handle transfer of control (trnsctrl.asm)
  102. #if defined(_M_IA64) /*IFSTRIP=IGN*/
  103. #include <kxia64.h>
  104. #include <ia64inst.h>
  105. #include <cvconst.h>
  106. #endif
  107. #pragma hdrstop // PCH is created from here
  108. ////////////////////////////////////////////////////////////////////////////////
  109. //
  110. // Intel x86-specific definitions
  111. //
  112. #if defined(_M_IX86)
  113. #define __GetRangeOfTrysToCheck(a, b, c, d, e, f, g) \
  114. _GetRangeOfTrysToCheck(b, c, d, e, f)
  115. #define __FrameUnwindToEmptyState(a, b, c) \
  116. __FrameUnwindToState(a, b, c, EH_EMPTY_STATE);
  117. #define __CallSETranslator(a, b, c, d, e, f, g, h) \
  118. _CallSETranslator(a, b, c, d, e, f, g)
  119. #define __GetUnwindState(a, b, c) \
  120. GetCurrentState(a, b, c)
  121. #define __OffsetToAddress(a, b, c) \
  122. OffsetToAddress(a, b)
  123. #define __GetAddress(a, b) \
  124. (a)
  125. #define REAL_FP(a, b) \
  126. (a)
  127. #define __ResetException(a)
  128. ////////////////////////////////////////////////////////////////////////////////
  129. //
  130. // MIPS-specific definitions
  131. //
  132. #elif defined(_M_MRX000)
  133. #define __GetRangeOfTrysToCheck(a, b, c, d, e, f, g) \
  134. _GetRangeOfTrysToCheck(a, b, c, d, e, f)
  135. #define __FrameUnwindToEmptyState(a, b, c) \
  136. __FrameUnwindToState(a, b, c, EH_EMPTY_STATE);
  137. #define __CallSETranslator(a, b, c, d, e, f, g, h) \
  138. _CallSETranslator(a, b, c, d, e, f, g, h)
  139. #define __GetUnwindState(a, b, c) \
  140. GetCurrentState(a, b, c)
  141. #define __OffsetToAddress(a, b, c) \
  142. _OffsetToAddress(a, b, c)
  143. #define __GetAddress(a, b) \
  144. (a)
  145. #define REAL_FP(a, b) \
  146. (a)
  147. #define SetState(a, b, c, d)
  148. #define __ResetException(a)
  149. #define VER41_C2(p) (HT_ADJECTIVES(TBME_CATCH(FUNC_TRYBLOCK(*p, 0), 0)) & 0x20)
  150. #ifdef _MT
  151. #define pExitContext (*((CONTEXT **)&(_getptd()->_pExitContext)))
  152. #else
  153. static CONTEXT *pExitContext = NULL; // context to assist the return to the continuation point
  154. #endif // _MT
  155. ////////////////////////////////////////////////////////////////////////////////
  156. //
  157. // P7 specific definitions
  158. //
  159. #elif defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  160. #define __GetRangeOfTrysToCheck(a, b, c, d, e, f, g) \
  161. _GetRangeOfTrysToCheck(a, b, c, d, e, f, g)
  162. #define __CallSETranslator(a, b, c, d, e, f, g, h) \
  163. _CallSETranslator(a, b, c, d, e, f, g)
  164. #define __GetUnwindState(a, b, c) \
  165. GetCurrentState(a, b, c)
  166. #define __OffsetToAddress(a, b, c) \
  167. OffsetToAddress(a, b)
  168. #define __GetAddress(a, b) \
  169. (void*)(a)
  170. #define REAL_FP(a, b) \
  171. (a)
  172. #define __ResetException(a)
  173. #ifdef _MT
  174. #define pExitContext (*((CONTEXT **)&(_getptd()->_pExitContext)))
  175. #else
  176. static CONTEXT *pExitContext = NULL; // context to assist the return to the continuation point
  177. #endif // _MT
  178. // The throw site
  179. #undef CT_PTD
  180. #define CT_PTD(ct) (CT_PTD_IB(ct, _GetThrowImageBase()))
  181. #undef CT_COPYFUNC
  182. #define CT_COPYFUNC(ct) ((ct).copyFunction? CT_COPYFUNC_IB(ct, _GetThrowImageBase()):NULL)
  183. #undef THROW_FORWARDCOMPAT
  184. #define THROW_FORWARDCOMPAT(ti) ((ti).pForwardCompat? THROW_FORWARDCOMPAT_IB(ti, _GetThrowImageBase()):NULL)
  185. #undef THROW_COUNT
  186. #define THROW_COUNT(ti) THROW_COUNT_IB(ti, _GetThrowImageBase())
  187. #undef THROW_CTLIST
  188. #define THROW_CTLIST(ti) THROW_CTLIST_IB(ti, _GetThrowImageBase())
  189. // The catch site
  190. #undef HT_HANDLER
  191. #define HT_HANDLER(ht) (HT_HANDLER_IB(ht, _GetImageBase()))
  192. #undef UWE_ACTION
  193. #define UWE_ACTION(uwe) ((uwe).action? UWE_ACTION_IB(uwe, _GetImageBase()):NULL)
  194. #undef FUNC_UNWIND
  195. #define FUNC_UNWIND(fi,st) (FUNC_PUNWINDMAP(fi,_GetImageBase())[st])
  196. #undef TBME_CATCH
  197. #define TBME_CATCH(hm,n) (TBME_PLIST(hm,_GetImageBase())[n])
  198. #undef TBME_PCATCH
  199. #define TBME_PCATCH(hm,n) (&(TBME_PLIST(hm,_GetImageBase())[n]))
  200. #undef HT_PTD
  201. #define HT_PTD(ht) ((TypeDescriptor*)((ht).dispType? HT_PTD_IB(ht,_GetImageBase()):NULL))
  202. #undef abnormal_termination
  203. #define abnormal_termination() FALSE
  204. ////////////////////////////////////////////////////////////////////////////////
  205. //
  206. // DEC Alpha-specific definitions
  207. //
  208. #elif defined(_M_ALPHA)
  209. #define __GetRangeOfTrysToCheck(a, b, c, d, e, f, g) \
  210. _GetRangeOfTrysToCheck(b, c, d, e, f)
  211. #define __FrameUnwindToEmptyState(a, b, c) \
  212. __FrameUnwindToState(a, b, c, EH_EMPTY_STATE);
  213. #define __CallSETranslator(a, b, c, d, e, f, g, h) \
  214. _CallSETranslator(a, b, c, d, e, f, g)
  215. #define __GetUnwindState(a, b, c) \
  216. GetCurrentState(a, b, c)
  217. #define __OffsetToAddress(a, b, c) \
  218. OffsetToAddress(a, b)
  219. #define __GetAddress(a, b) \
  220. (a)
  221. #define __ResetException(a)
  222. ////////////////////////////////////////////////////////////////////////////////
  223. //
  224. // PowerPC for Windows/NT-specific definitions
  225. //
  226. #elif defined(_M_PPC)
  227. #define _POWERPC
  228. #define __GetRangeOfTrysToCheck(a, b, c, d, e, f, g) \
  229. _GetRangeOfTrysToCheck(b, c, d, e, f)
  230. #define _MoveContext(a, b) \
  231. RtlMoveMemory(a, b, sizeof(CONTEXT));
  232. #define __CallSETranslator(a, b, c, d, e, f, g, h) \
  233. _CallSETranslator(a, b, c, d, e, f, g)
  234. #define __GetUnwindState(a, b, c) \
  235. GetUnwindState(a, b, c)
  236. #define __OffsetToAddress(a, b, c) \
  237. OffsetToAddress(a, b)
  238. #define __GetAddress(a, b) \
  239. (a)
  240. #define REAL_FP(a, b) \
  241. (a)
  242. #define __ResetException(a)
  243. extern "C" CONTEXT * _GetUnwindContext(VOID);
  244. #ifdef _MT
  245. #define pExitContext (*((CONTEXT **)&(_getptd()->_pExitContext)))
  246. #else
  247. static CONTEXT *pExitContext = NULL; // context to assist the return to the continuation point
  248. #endif // _MT
  249. ////////////////////////////////////////////////////////////////////////////////
  250. //
  251. // Unknown platform
  252. //
  253. #else
  254. #error Unrecognized platform
  255. #endif
  256. extern "C" {
  257. typedef struct {
  258. unsigned long dwSig;
  259. unsigned long uoffDestination;
  260. unsigned long dwCode;
  261. unsigned long uoffFramePointer;
  262. } _NLG_INFO;
  263. extern _NLG_INFO _NLG_Destination;
  264. }
  265. ////////////////////////////////////////////////////////////////////////////////
  266. //
  267. // Forward declaration of local functions:
  268. //
  269. // M00TODO: all these parameters should be declared const
  270. // The local unwinder must be external (see __CxxLongjmpUnwind in trnsctrl.cpp)
  271. extern "C" void __FrameUnwindToState(
  272. EHRegistrationNode *,
  273. DispatcherContext *,
  274. FuncInfo *,
  275. __ehstate_t
  276. );
  277. static void FindHandler(
  278. EHExceptionRecord *,
  279. EHRegistrationNode *,
  280. CONTEXT *,
  281. DispatcherContext *,
  282. FuncInfo *,
  283. BOOLEAN,
  284. int,
  285. EHRegistrationNode*
  286. );
  287. static void CatchIt(
  288. EHExceptionRecord *,
  289. EHRegistrationNode *,
  290. CONTEXT *,
  291. DispatcherContext *,
  292. FuncInfo *,
  293. HandlerType *,
  294. CatchableType *,
  295. TryBlockMapEntry *,
  296. int,
  297. EHRegistrationNode *,
  298. BOOLEAN
  299. );
  300. static void * CallCatchBlock(
  301. EHExceptionRecord *,
  302. EHRegistrationNode *,
  303. CONTEXT *,
  304. FuncInfo *,
  305. void *,
  306. int,
  307. unsigned long
  308. #if defined(_M_IA64) || defined(_M_AMD64)
  309. ,FRAMEINFO *
  310. #endif
  311. );
  312. static void BuildCatchObject(
  313. EHExceptionRecord *,
  314. void *,
  315. HandlerType *,
  316. CatchableType *
  317. );
  318. static __inline int TypeMatch(
  319. HandlerType *,
  320. CatchableType *,
  321. ThrowInfo *
  322. );
  323. static void * AdjustPointer(
  324. void *,
  325. const PMD&
  326. );
  327. static void FindHandlerForForeignException(
  328. EHExceptionRecord *,
  329. EHRegistrationNode *, CONTEXT *,
  330. DispatcherContext *,
  331. FuncInfo *,
  332. __ehstate_t,
  333. int,
  334. EHRegistrationNode *
  335. );
  336. static int FrameUnwindFilter(
  337. EXCEPTION_POINTERS *
  338. );
  339. static int ExFilterRethrow(
  340. EXCEPTION_POINTERS *
  341. );
  342. extern "C" void _CRTIMP __DestructExceptionObject(
  343. EHExceptionRecord *,
  344. BOOLEAN
  345. );
  346. //
  347. // Make sure the terminate wrapper is dragged in:
  348. //
  349. static void *pMyUnhandledExceptionFilter =
  350. #if defined(_NTSUBSET_)
  351. 0;
  352. #else
  353. &__CxxUnhandledExceptionFilter;
  354. #endif
  355. //
  356. // This describes the most recently handled exception, in case of a rethrow:
  357. //
  358. #ifdef _MT
  359. #define _pCurrentException (*((EHExceptionRecord **)&(_getptd()->_curexception)))
  360. #define _pCurrentExContext (*((CONTEXT **)&(_getptd()->_curcontext)))
  361. #define __ProcessingThrow _getptd()->_ProcessingThrow
  362. #else
  363. EHExceptionRecord *_pCurrentException = NULL;
  364. CONTEXT *_pCurrentExContext = NULL;
  365. int __ProcessingThrow = 0;
  366. #endif
  367. ////////////////////////////////////////////////////////////////////////////////
  368. //
  369. // __InternalCxxFrameHandler - the frame handler for all functions with C++ EH
  370. // information.
  371. //
  372. // If exception is handled, this doesn't return; otherwise, it returns
  373. // ExceptionContinueSearch.
  374. //
  375. // Note that this is called three ways:
  376. // From __CxxFrameHandler: primary usage, called to inspect whole function.
  377. // CatchDepth == 0, pMarkerRN == NULL
  378. // From CatchGuardHandler: If an exception occurred within a catch, this is
  379. // called to check for try blocks within that catch only, and does not
  380. // handle unwinds.
  381. // From TranslatorGuardHandler: Called to handle the translation of a
  382. // non-C++ EH exception. Context considered is that of parent.
  383. extern "C" EXCEPTION_DISPOSITION __cdecl __InternalCxxFrameHandler(
  384. EHExceptionRecord *pExcept, // Information for this exception
  385. EHRegistrationNode *pRN, // Dynamic information for this frame
  386. CONTEXT *pContext, // Context info
  387. DispatcherContext *pDC, // Context within subject frame
  388. FuncInfo *pFuncInfo, // Static information for this frame
  389. int CatchDepth, // How deeply nested are we?
  390. EHRegistrationNode *pMarkerRN, // Marker node for when checking inside
  391. // catch block
  392. BOOLEAN recursive // Are we handling a translation?
  393. ) {
  394. EHTRACE_ENTER_FMT2("%s, pRN = 0x%p",
  395. IS_UNWINDING(PER_FLAGS(pExcept)) ? "Unwinding" : "Searching",
  396. pRN);
  397. #if defined(_M_ALPHA)
  398. // On Alpha - these values synthesized from DispatcherContext
  399. pFuncInfo = (FuncInfo *)(pDC ->FunctionEntry->HandlerData);
  400. pRN = (EHRegistrationNode *)VIRTUAL_FP(pDC);
  401. #endif // defined(_M_ALPHA)
  402. DASSERT(FUNC_MAGICNUM(*pFuncInfo) == EH_MAGIC_NUMBER1);
  403. #if defined(_M_ALPHA)
  404. // A special case to support gotos out of nested catch handlers
  405. // and setjmp/longjmp.
  406. //
  407. // See __CxxEHGoto in alpha\trnsctrl.cxx for details.
  408. //
  409. if (IS_TARGET_UNWIND(PER_FLAGS(pExcept))) {
  410. if (PER_CODE(pExcept) == STATUS_UNWIND && PER_NPARAMS(pExcept) == 1) {
  411. __ehstate_t target_state =
  412. (__ehstate_t)((PEXCEPTION_RECORD)(pExcept))->ExceptionInformation[0];
  413. DASSERT(target_state >= EH_EMPTY_STATE
  414. && target_state < FUNC_MAXSTATE(*pFuncInfo));
  415. __FrameUnwindToState(pRN, pDC, pFuncInfo, target_state);
  416. EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
  417. return ExceptionContinueSearch;
  418. } else {
  419. EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
  420. return ExceptionContinueSearch;
  421. }
  422. }
  423. #endif // defined(_M_ALPHA)
  424. if (IS_UNWINDING(PER_FLAGS(pExcept)))
  425. {
  426. // We're at the unwinding stage of things. Don't care about the
  427. // exception itself. (Check this first because it's easier)
  428. #if defined(_POWERPC)
  429. if (FUNC_MAXSTATE(*pFuncInfo) != 0)
  430. #else
  431. if (FUNC_MAXSTATE(*pFuncInfo) != 0 && CatchDepth == 0)
  432. #endif
  433. {
  434. // Only unwind if there's something to unwind
  435. // AND we're being called through the primary RN.
  436. #if defined(_M_MRX000) || defined(_POWERPC) || defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  437. // If we are exiting to the continuation point, we don't want to
  438. // use the unwind map again. Unwinding continues until the
  439. // dispatcher finds the target frame, at which point the dispatcher
  440. // will jump to the continuation point
  441. //
  442. // Don't unwind the target frame if the unwind was initiated by
  443. // UnwindNestedFrames
  444. if (_GetUnwindContext() != NULL
  445. && IS_TARGET_UNWIND(PER_FLAGS(pExcept))) {
  446. #if defined (_POWERPC)
  447. // Virtually unwind the target frame to recover the value of r2.
  448. // We must take care to not unwind a glue sequence that may have
  449. // been used to reach the target frame. This is done by giving
  450. // stack limit values that will regard any stack pointer as bad.
  451. CONTEXT TocContext;
  452. PRUNTIME_FUNCTION FunctionEntry;
  453. BOOLEAN InFunction;
  454. ULONG EstablisherFrame;
  455. _MoveContext(&TocContext, pContext);
  456. FunctionEntry = RtlLookupFunctionEntry(pDC->ControlPc);
  457. RtlVirtualUnwind(pDC->ControlPc, FunctionEntry, &TocContext,
  458. &InFunction, &EstablisherFrame, NULL, 0xffffffff, 0);
  459. pContext->Gpr2 = TocContext.Gpr2;
  460. #endif // defined (_POWERPC)
  461. // Save the target context to be used in 'CatchIt' to jump to
  462. // the continuation point.
  463. DASSERT(pExitContext != NULL);
  464. _MoveContext(pExitContext, pContext);
  465. // This is how we give control back to _UnwindNestedFrames
  466. _MoveContext(pContext, _GetUnwindContext());
  467. EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
  468. return ExceptionContinueSearch;
  469. }
  470. #endif // defined(_M_MRX000) || defined(_POWERPC) || defined(_M_IA64)
  471. #if defined(_M_IA64)
  472. else if (IS_TARGET_UNWIND(PER_FLAGS(pExcept)) && PER_CODE(pExcept) == STATUS_LONGJUMP) {
  473. __ehstate_t target_state = _StateFromIp(pFuncInfo, pDC, pContext->StIIP);
  474. DASSERT(target_state >= EH_EMPTY_STATE
  475. && target_state < FUNC_MAXSTATE(*pFuncInfo));
  476. __FrameUnwindToState(pRN, pDC, pFuncInfo, target_state);
  477. EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
  478. return ExceptionContinueSearch;
  479. }
  480. #elif defined(_M_AMD64)
  481. else if (IS_TARGET_UNWIND(PER_FLAGS(pExcept)) && PER_CODE(pExcept) == STATUS_LONGJUMP) {
  482. __ehstate_t target_state = _StateFromIp(pFuncInfo, pDC, pContext->Rip);
  483. DASSERT(target_state >= EH_EMPTY_STATE
  484. && target_state < FUNC_MAXSTATE(*pFuncInfo));
  485. __FrameUnwindToState(pRN, pDC, pFuncInfo, target_state);
  486. EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
  487. return ExceptionContinueSearch;
  488. }
  489. #endif // defined(_M_IA64)
  490. __FrameUnwindToEmptyState(pRN, pDC, pFuncInfo);
  491. }
  492. EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
  493. return ExceptionContinueSearch; // I don't think this value matters
  494. } else if (FUNC_NTRYBLOCKS(*pFuncInfo) != 0) {
  495. // NT is looking for handlers. We've got handlers.
  496. // Let's check this puppy out. Do we recognize it?
  497. int (__cdecl *pfn)(...);
  498. if (PER_CODE(pExcept) == EH_EXCEPTION_NUMBER
  499. && PER_MAGICNUM(pExcept) > EH_MAGIC_NUMBER1
  500. && (pfn = THROW_FORWARDCOMPAT(*PER_PTHROW(pExcept))) != NULL) {
  501. // Forward compatibility: The thrown object appears to have been
  502. // created by a newer version of our compiler. Let that version's
  503. // frame handler do the work (if one was specified).
  504. #if defined(DEBUG)
  505. if (_ValidateExecute((FARPROC)pfn)) {
  506. #endif
  507. EXCEPTION_DISPOSITION result =
  508. (EXCEPTION_DISPOSITION)pfn(pExcept, pRN, pContext, pDC,
  509. pFuncInfo, CatchDepth,
  510. pMarkerRN, recursive);
  511. EHTRACE_HANDLER_EXIT(result);
  512. return result;
  513. #if defined(DEBUG)
  514. } else {
  515. _inconsistency(); // Does not return; TKB
  516. }
  517. #endif
  518. } else {
  519. // Anything else: we'll handle it here.
  520. FindHandler(pExcept, pRN, pContext, pDC, pFuncInfo, recursive,
  521. CatchDepth, pMarkerRN);
  522. }
  523. // If it returned, we didn't have any matches.
  524. } // NT was looking for a handler
  525. // We had nothing to do with it or it was rethrown. Keep searching.
  526. EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
  527. return ExceptionContinueSearch;
  528. } // InternalCxxFrameHandler
  529. ////////////////////////////////////////////////////////////////////////////////
  530. //
  531. // FindHandler - find a matching handler on this frame, using all means
  532. // available.
  533. //
  534. // Description:
  535. // If the exception thrown was an MSC++ EH, search handlers for match.
  536. // Otherwise, if we haven't already recursed, try to translate.
  537. // If we have recursed (ie we're handling the translator's exception), and
  538. // it isn't a typed exception, call _inconsistency.
  539. //
  540. // Returns:
  541. // Returns iff exception was not handled.
  542. //
  543. // Assumptions:
  544. // Only called if there are handlers in this function.
  545. static void FindHandler(
  546. EHExceptionRecord *pExcept, // Information for this (logical)
  547. // exception
  548. EHRegistrationNode *pRN, // Dynamic information for subject frame
  549. CONTEXT *pContext, // Context info
  550. DispatcherContext *pDC, // Context within subject frame
  551. FuncInfo *pFuncInfo, // Static information for subject frame
  552. BOOLEAN recursive, // TRUE if we're handling the
  553. // translation
  554. int CatchDepth, // Level of nested catch that is being
  555. // checked
  556. EHRegistrationNode *pMarkerRN // Extra marker RN for nested catch
  557. // handling
  558. )
  559. {
  560. EHTRACE_ENTER;
  561. BOOLEAN IsRethrow = FALSE;
  562. // Get the current state (machine-dependent)
  563. #if defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  564. __ehstate_t curState = _StateFromControlPc(pFuncInfo, pDC);
  565. #if defined(_M_AMD64) // Will be used when unwinding.
  566. EHRegistrationNode EstablisherFrame;
  567. _GetEstablisherFrame(pRN, pDC, pFuncInfo, &EstablisherFrame);
  568. if (curState > GetUnwindTryBlock(pRN, pDC, pFuncInfo)) {
  569. SetState(&EstablisherFrame, pDC, pFuncInfo, curState);
  570. }
  571. #endif
  572. #else
  573. __ehstate_t curState = GetCurrentState(pRN, pDC, pFuncInfo);
  574. #endif
  575. DASSERT(curState >= EH_EMPTY_STATE && curState < FUNC_MAXSTATE(*pFuncInfo));
  576. // Check if it's a re-throw. Use the exception we stashed away if it is.
  577. if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == NULL) {
  578. if (_pCurrentException == NULL) {
  579. // Oops! User re-threw a non-existant exception! Let it propogate.
  580. EHTRACE_EXIT;
  581. return;
  582. }
  583. pExcept = _pCurrentException;
  584. pContext = _pCurrentExContext;
  585. IsRethrow = TRUE;
  586. #if defined(_M_IA64) || defined(_M_AMD64)/*IFSTRIP=IGN*/
  587. _SetThrowImageBase((unsigned __int64)pExcept->params.pThrowImageBase);
  588. #endif
  589. DASSERT(_ValidateRead(pExcept));
  590. DASSERT(!PER_IS_MSVC_EH(pExcept) || PER_PTHROW(pExcept) != NULL);
  591. }
  592. if (PER_IS_MSVC_EH(pExcept)) {
  593. // Looks like it's ours. Let's see if we have a match:
  594. //
  595. // First, determine range of try blocks to consider:
  596. // Only try blocks which are at the current catch depth are of interest.
  597. unsigned curTry;
  598. unsigned end;
  599. #if defined(_M_MRX000)
  600. DASSERT(VER41_C2(pFuncInfo));
  601. #endif
  602. TryBlockMapEntry *pEntry = __GetRangeOfTrysToCheck(pRN, pFuncInfo,
  603. CatchDepth, curState, &curTry, &end, pDC);
  604. // Scan the try blocks in the function:
  605. for (; curTry < end; curTry++, pEntry++) {
  606. HandlerType *pCatch;
  607. #if defined(_M_IA64) || defined(_M_AMD64)
  608. __int32 const *ppCatchable;
  609. #elif defined(_WIN64)
  610. CatchableType * UNALIGNED const *ppCatchable;
  611. #else
  612. CatchableType * const *ppCatchable;
  613. #endif
  614. CatchableType *pCatchable;
  615. int catches;
  616. int catchables;
  617. if (TBME_LOW(*pEntry) > curState || curState > TBME_HIGH(*pEntry)) {
  618. continue;
  619. }
  620. // Try block was in scope for current state. Scan catches for this
  621. // try:
  622. pCatch = TBME_PCATCH(*pEntry, 0);
  623. for (catches = TBME_NCATCHES(*pEntry); catches > 0; catches--,
  624. pCatch++) {
  625. // Scan all types that thrown object can be converted to:
  626. ppCatchable = THROW_CTLIST(*PER_PTHROW(pExcept));
  627. for (catchables = THROW_COUNT(*PER_PTHROW(pExcept));
  628. catchables > 0; catchables--, ppCatchable++) {
  629. #if defined(_M_IA64) || defined(_M_AMD64)
  630. pCatchable = (CatchableType *)(_GetThrowImageBase() + *ppCatchable);
  631. #else
  632. pCatchable = *ppCatchable;
  633. #endif
  634. if (!TypeMatch(pCatch, pCatchable, PER_PTHROW(pExcept))) {
  635. continue;
  636. }
  637. // OK. We finally found a match. Activate the catch. If
  638. // control gets back here, the catch did a re-throw, so
  639. // keep searching.
  640. #if defined(_M_MRX000)
  641. PVOID pRealFrame = _OffsetToAddress(0, pRN, FUNC_FRAMENEST(*pFuncInfo));
  642. UNWINDHELP(pRealFrame, FUNC_DISPUNWINDHELP(*pFuncInfo),0) = curTry;
  643. #elif defined(_M_IA64) || defined(_M_AMD64)/*IFSTRIP=IGN*/
  644. SetUnwindTryBlock(pRN, pDC, pFuncInfo, /*curTry*/ curState);
  645. #endif // defined(_M_MRX000)
  646. CatchIt(pExcept, pRN, pContext, pDC, pFuncInfo, pCatch,
  647. pCatchable, pEntry, CatchDepth, pMarkerRN, IsRethrow);
  648. #if defined(_M_IA64) /*IFSTRIP=IGN*/
  649. goto EndOfTryScan;
  650. #else
  651. goto NextTryBlock;
  652. #endif
  653. } // Scan posible conversions
  654. } // Scan catch clauses
  655. #if !defined(_M_IA64) /*IFSTRIP=IGN*/
  656. NextTryBlock: ;
  657. #endif
  658. #if defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  659. // if( GetUnwindTryBlock(pRN, pDC, pFuncInfo) >= 0 )
  660. // curTry = GetUnwindTryBlock(pRN, pDC, pFuncInfo);
  661. #endif
  662. } // Scan try blocks
  663. #if defined(_M_IA64) /*IFSTRIP=IGN*/
  664. EndOfTryScan:
  665. #endif
  666. if (recursive) {
  667. // A translation was provided, but this frame didn't catch it.
  668. // Destruct the translated object before returning; if destruction
  669. // raises an exception, issue _inconsistency.
  670. __DestructExceptionObject(pExcept, TRUE);
  671. }
  672. } // It was a C++ EH exception
  673. else {
  674. // Not ours. But maybe someone told us how to make it ours.
  675. if (!recursive) {
  676. FindHandlerForForeignException(pExcept, pRN, pContext, pDC,
  677. pFuncInfo, curState, CatchDepth, pMarkerRN);
  678. } else {
  679. // We're recursive, and the exception wasn't a C++ EH!
  680. // Translator threw something uninteligable. We're outa here!
  681. // M00REVIEW: Two choices here actually: we could let the new
  682. // exception take over.
  683. terminate();
  684. }
  685. } // It wasn't our exception
  686. EHTRACE_EXIT;
  687. }
  688. ////////////////////////////////////////////////////////////////////////////////
  689. //
  690. // FindHandlerForForeignException - We've got an exception which wasn't ours.
  691. // Try to translate it into C++ EH, and also check for match with ellipsis.
  692. //
  693. // Description:
  694. // If an SE-to-EH translator has been installed, call it. The translator
  695. // must throw the appropriate typed exception or return. If the translator
  696. // throws, we invoke FindHandler again as the exception filter.
  697. //
  698. // Returns:
  699. // Returns if exception was not fully handled.
  700. // No return value.
  701. //
  702. // Assumptions:
  703. // Only called if there are handlers in this function.
  704. static void FindHandlerForForeignException(
  705. EHExceptionRecord *pExcept, // Information for this (logical)
  706. // exception
  707. EHRegistrationNode *pRN, // Dynamic information for subject frame
  708. CONTEXT *pContext, // Context info
  709. DispatcherContext *pDC, // Context within subject frame
  710. FuncInfo *pFuncInfo, // Static information for subject frame
  711. __ehstate_t curState, // Current state
  712. int CatchDepth, // Level of nested catch that is being
  713. // checked
  714. EHRegistrationNode *pMarkerRN // Extra marker RN for nested catch
  715. // handling
  716. )
  717. {
  718. EHTRACE_ENTER;
  719. unsigned curTry;
  720. unsigned end;
  721. TryBlockMapEntry *pEntry;
  722. // We don't want to touch BreakPoint generated Exception.
  723. if (PER_CODE(pExcept) == STATUS_BREAKPOINT) {
  724. EHTRACE_EXIT;
  725. return;
  726. }
  727. if (__pSETranslator != NULL) {
  728. // Call the translator. If the translator knows what to
  729. // make of it, it will throw an appropriate C++ exception.
  730. // We intercept it and use it (recursively) for this
  731. // frame. Don't recurse more than once.
  732. #if defined(_M_MRX000)
  733. ULONG TDTransOffset = 0;
  734. #ifdef _MT
  735. struct _tiddata DummyStruct;
  736. TDTransOffset = (char*)&DummyStruct._translator - (char*)&DummyStruct;
  737. #endif
  738. #endif // defined(_M_MRX000)
  739. if (__CallSETranslator(pExcept, pRN, pContext, pDC, pFuncInfo,
  740. CatchDepth, pMarkerRN, TDTransOffset)) {
  741. EHTRACE_EXIT;
  742. return;
  743. }
  744. }
  745. // Didn't have a translator, or the translator returned normally (i.e.
  746. // didn't translate it). Still need to check for match with ellipsis:
  747. pEntry = __GetRangeOfTrysToCheck(pRN, pFuncInfo, CatchDepth, curState,
  748. &curTry, &end, pDC);
  749. // Scan the try blocks in the function:
  750. for (; curTry < end; curTry++, pEntry++) {
  751. // If the try-block was in scope *and* the last catch in that try is an
  752. // ellipsis (no other can be)
  753. if (curState < TBME_LOW(*pEntry) || curState > TBME_HIGH(*pEntry)
  754. || !HT_IS_TYPE_ELLIPSIS(TBME_CATCH(*pEntry, TBME_NCATCHES(*pEntry) - 1))) {
  755. continue;
  756. }
  757. // Found an ellipsis. Handle exception.
  758. #if defined(_M_MRX000)
  759. DASSERT(VER41_C2(pFuncInfo));
  760. PVOID pRealFrame = _OffsetToAddress(0, pRN, FUNC_FRAMENEST(*pFuncInfo));
  761. UNWINDHELP(pRealFrame, FUNC_DISPUNWINDHELP(*pFuncInfo), 0) = curTry;
  762. #elif defined(_M_IA64) || defined(_M_AMD64)/*IFSTRIP=IGN*/
  763. SetUnwindTryBlock(pRN, pDC, pFuncInfo, /*curTry*/ curState);
  764. #endif // defined(_M_MRX000)
  765. CatchIt(pExcept, pRN, pContext, pDC, pFuncInfo,
  766. TBME_PCATCH(*pEntry, TBME_NCATCHES(*pEntry) - 1), NULL, pEntry,
  767. CatchDepth, pMarkerRN, TRUE);
  768. // If it returns, handler re-threw. Keep searching.
  769. } // Search for try
  770. EHTRACE_EXIT;
  771. // If we got here, that means we didn't have anything to do with the
  772. // exception. Continue search.
  773. }
  774. ////////////////////////////////////////////////////////////////////////////////
  775. //
  776. // TypeMatch - Check if the catch type matches the given throw conversion.
  777. //
  778. // Returns:
  779. // TRUE if the catch can catch using this throw conversion, FALSE otherwise.
  780. static __inline int TypeMatch(
  781. HandlerType *pCatch, // Type of the 'catch' clause
  782. CatchableType *pCatchable, // Type conversion under consideration
  783. ThrowInfo *pThrow // General information about the thrown
  784. // type.
  785. ) {
  786. // First, check for match with ellipsis:
  787. if (HT_IS_TYPE_ELLIPSIS(*pCatch)) {
  788. return TRUE;
  789. }
  790. // Not ellipsis; the basic types match if it's the same record *or* the
  791. // names are identical.
  792. if (HT_PTD(*pCatch) != CT_PTD(*pCatchable)
  793. && strcmp(HT_NAME(*pCatch), CT_NAME(*pCatchable)) != 0) {
  794. return FALSE;
  795. }
  796. // Basic types match. The actual conversion is valid if:
  797. // caught by ref if ref required *and*
  798. // the qualifiers are compatible *and*
  799. // the alignments match *and*
  800. // the volatility matches
  801. return (!CT_BYREFONLY(*pCatchable) || HT_ISREFERENCE(*pCatch))
  802. && (!THROW_ISCONST(*pThrow) || HT_ISCONST(*pCatch))
  803. #if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC) || defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  804. && (!THROW_ISUNALIGNED(*pThrow) || HT_ISUNALIGNED(*pCatch))
  805. #endif
  806. && (!THROW_ISVOLATILE(*pThrow) || HT_ISVOLATILE(*pCatch));
  807. }
  808. ////////////////////////////////////////////////////////////////////////////////
  809. //
  810. // FrameUnwindFilter - Allows possibility of continuing through SEH during
  811. // unwind.
  812. //
  813. static int FrameUnwindFilter(
  814. EXCEPTION_POINTERS *pExPtrs
  815. ) {
  816. EHTRACE_ENTER;
  817. EHExceptionRecord *pExcept = (EHExceptionRecord *)pExPtrs->ExceptionRecord;
  818. switch (PER_CODE(pExcept)) {
  819. case EH_EXCEPTION_NUMBER:
  820. __ProcessingThrow = 0;
  821. terminate();
  822. #ifdef ALLOW_UNWIND_ABORT
  823. case EH_ABORT_FRAME_UNWIND_PART:
  824. EHTRACE_EXIT;
  825. return EXCEPTION_EXECUTE_HANDLER;
  826. #endif
  827. default:
  828. EHTRACE_EXIT;
  829. return EXCEPTION_CONTINUE_SEARCH;
  830. }
  831. }
  832. ////////////////////////////////////////////////////////////////////////////////
  833. //
  834. // __FrameUnwindToState - Unwind this frame until specified state is reached.
  835. //
  836. // Returns:
  837. // No return value.
  838. //
  839. // Side Effects:
  840. // All objects on frame which go out of scope as a result of the unwind are
  841. // destructed.
  842. // Registration node is updated to reflect new state.
  843. //
  844. // Usage:
  845. // This function is called both to do full-frame unwind during the unwind
  846. // phase (targetState = -1), and to do partial unwinding when the current
  847. // frame has an appropriate catch.
  848. extern "C" void __FrameUnwindToState (
  849. EHRegistrationNode *pRN, // Registration node for subject
  850. // function
  851. DispatcherContext *pDC, // Context within subject frame
  852. FuncInfo *pFuncInfo, // Static information for subject
  853. // function
  854. __ehstate_t targetState // State to unwind to
  855. ) {
  856. EHTRACE_ENTER;
  857. __ehstate_t curState = __GetUnwindState(pRN, pDC, pFuncInfo);
  858. __ProcessingThrow++;
  859. __try {
  860. #if defined(_M_MRX000)
  861. // The MIPS unwind-map may have a shortcut by using EH_EMPTY_STATE
  862. while (curState != EH_EMPTY_STATE && curState != targetState)
  863. #elif defined(_M_IA64) || defined(_M_AMD64)
  864. while (curState != EH_EMPTY_STATE && curState > targetState)
  865. #else
  866. while (curState != targetState)
  867. #endif
  868. {
  869. DASSERT((curState > EH_EMPTY_STATE)
  870. && (curState < FUNC_MAXSTATE(*pFuncInfo)));
  871. // Get state after next unwind action
  872. __ehstate_t nxtState = UWE_TOSTATE(FUNC_UNWIND(*pFuncInfo, curState));
  873. __try {
  874. // Call the unwind action (if one exists):
  875. #if defined(_M_MRX000)
  876. // If this is nested function (catch block), the real frame where
  877. // all locals are stored is the outermost function's frame.
  878. PVOID pRealFrame =
  879. _OffsetToAddress(0, pRN, FUNC_FRAMENEST(*pFuncInfo));
  880. if (UWE_ACTION(FUNC_UNWIND(*pFuncInfo, curState)) != NULL
  881. && !UNWINDHELP(pRealFrame, FUNC_DISPUNWINDHELP(*pFuncInfo),
  882. curState)) {
  883. UNWINDHELP(pRealFrame, FUNC_DISPUNWINDHELP(*pFuncInfo),
  884. curState) = TRUE;
  885. #else // !defined(_M_MRX000)
  886. if (UWE_ACTION(FUNC_UNWIND(*pFuncInfo, curState)) != NULL) {
  887. #endif
  888. // Before calling unwind action, adjust state as if it were
  889. // already completed:
  890. SetState(pRN, pDC, pFuncInfo, nxtState);
  891. EHTRACE_FMT2("Unwind from state %d to state %d", curState, nxtState);
  892. _CallSettingFrame(__GetAddress(UWE_ACTION(FUNC_UNWIND(*pFuncInfo, curState)), pDC),
  893. REAL_FP(pRN, pFuncInfo), 0x103);
  894. }
  895. } __except(EHTRACE_EXCEPT(FrameUnwindFilter(exception_info()))) {
  896. }
  897. curState = nxtState;
  898. }
  899. } __finally {
  900. if (__ProcessingThrow > 0) {
  901. __ProcessingThrow--;
  902. }
  903. }
  904. // Now that we're done, set the frame to reflect the final state.
  905. #if defined(_M_MRX000)
  906. DASSERT(curState == EH_EMPTY_STATE || curState == targetState);
  907. #elif defined(_M_IA64) || defined(_M_AMD64)
  908. DASSERT(curState == EH_EMPTY_STATE || curState <= targetState);
  909. #else
  910. DASSERT(curState == targetState);
  911. #endif
  912. EHTRACE_FMT2("Move from state %d to state %d", __GetUnwindState(pRN, pDC, pFuncInfo), curState);
  913. SetState(pRN, pDC, pFuncInfo, curState);
  914. EHTRACE_EXIT;
  915. }
  916. ////////////////////////////////////////////////////////////////////////////////
  917. //
  918. // CatchIt - A handler has been found for the thrown type. Do the work to
  919. // transfer control.
  920. //
  921. // Description:
  922. // Builds the catch object
  923. // Unwinds the stack to the point of the try
  924. // Calls the address of the handler (funclet) with the frame set up for that
  925. // function but without resetting the stack.
  926. // Handler funclet returns address to continue execution, or NULL if the
  927. // handler re-threw ("throw;" lexically in handler)
  928. // If the handler throws an EH exception whose exception info is NULL, then
  929. // it's a re-throw from a dynamicly enclosed scope.
  930. //
  931. // M00REVIEW: It is still an open question whether the catch object is built
  932. // before or after the local unwind.
  933. //
  934. // Returns:
  935. // No return value. Returns iff handler re-throws.
  936. static void CatchIt(
  937. EHExceptionRecord *pExcept, // The exception thrown
  938. EHRegistrationNode *pRN, // Dynamic info of function with catch
  939. CONTEXT *pContext, // Context info
  940. DispatcherContext *pDC, // Context within subject frame
  941. FuncInfo *pFuncInfo, // Static info of function with catch
  942. HandlerType *pCatch, // The catch clause selected
  943. CatchableType *pConv, // The rules for making the conversion
  944. TryBlockMapEntry *pEntry, // Description of the try block
  945. int CatchDepth, // How many catches are we nested in?
  946. EHRegistrationNode *pMarkerRN, // Special node if nested in catch
  947. BOOLEAN IsRethrow // Is this a rethrow ?
  948. ) {
  949. EHTRACE_ENTER_FMT1("Catching object @ 0x%p", PER_PEXCEPTOBJ(pExcept));
  950. void *continuationAddress;
  951. EHRegistrationNode *pEstablisher = pRN;
  952. #if defined(_M_MRX000) || defined(_POWERPC) || defined(_M_IA64) || defined(_M_AMD64)/*IFSTRIP=IGN*/
  953. FRAMEINFO FrameInfo;
  954. FRAMEINFO *pFrameInfo;
  955. CONTEXT ExitContext;
  956. #endif // defined(_M_MRX000) || defined(_POWERPC) || defined(_M_IA64) || defined(_M_AMD64)
  957. #if defined(_POWERPC)
  958. int dummy;
  959. pEstablisher = _GetEstablisherFrame(pDC, &dummy);
  960. #elif defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  961. PVOID pExceptionObjectDestroyed = NULL;
  962. EHRegistrationNode EstablisherFramePointers;
  963. pEstablisher = _GetEstablisherFrame(pRN, pDC, pFuncInfo, &EstablisherFramePointers);
  964. #endif // defined(_POWERPC)
  965. // Copy the thrown object into a buffer in the handler's stack frame,
  966. // unless the catch was by elipsis (no conversion) OR the catch was by
  967. // type without an actual 'catch object'.
  968. if (pConv != NULL) {
  969. BuildCatchObject(pExcept, pEstablisher, pCatch, pConv);
  970. }
  971. // Unwind stack objects to the entry of the try that caught this exception.
  972. #if defined(_M_MRX000) || defined(_POWERPC) || defined(_M_IA64) || defined(_M_AMD64)/*IFSTRIP=IGN*/
  973. pExitContext = &ExitContext;
  974. _UnwindNestedFrames(pRN,
  975. pExcept,
  976. pContext
  977. #ifdef _M_AMD64
  978. , pDC
  979. #endif
  980. );
  981. #if defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  982. if( _pCurrentException != NULL && _ExecutionInCatch(pDC, pFuncInfo) && ! IsRethrow) {
  983. __DestructExceptionObject(_pCurrentException, TRUE);
  984. pExceptionObjectDestroyed = PER_PEXCEPTOBJ(_pCurrentException);
  985. }
  986. #endif
  987. #elif defined(_M_ALPHA)
  988. // Alpha specific - this calls a special version of RtlUnwind which
  989. // walks the stack performing unwind actions but which does NOT
  990. // restore the context to the target frame's routine. Instead it
  991. // just returns.
  992. _UnwindNestedFrames(pRN, pExcept);
  993. #else
  994. if (pMarkerRN == NULL) {
  995. _UnwindNestedFrames(pRN, pExcept);
  996. } else {
  997. _UnwindNestedFrames(pMarkerRN, pExcept);
  998. }
  999. #endif
  1000. #if defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  1001. // Create FrameInfo before we attempt to unwind with __FrameUnwindToState()
  1002. // pExitContext must be setup in advance just in case a DTOR throws a new exception. VS7:#202440
  1003. pFrameInfo = _CreateFrameInfo(&FrameInfo, pDC, pExitContext, -2, pExceptionObjectDestroyed, pExcept);
  1004. #endif
  1005. __FrameUnwindToState(pEstablisher, pDC, pFuncInfo, TBME_LOW(*pEntry));
  1006. // Call the catch. Separated out because it introduces a new registration
  1007. // node.
  1008. #if defined(_M_MRX000)
  1009. pFrameInfo = _CreateFrameInfo(&FrameInfo, pDC, pRN, pExitContext);
  1010. #elif defined(_M_IA64) /*IFSTRIP=IGN*/
  1011. UNWINDSTATE(pEstablisher->MemoryStackFp, FUNC_DISPUNWINDHELP(*pFuncInfo)) = GetCurrentState(pEstablisher,pDC,pFuncInfo);
  1012. if(IsRethrow) {
  1013. pFrameInfo->isRethrow = TRUE;
  1014. }
  1015. else if( pExcept != NULL && pExceptionObjectDestroyed == NULL ) {
  1016. pFrameInfo->pExceptionObjectToBeDestroyed = PER_PEXCEPTOBJ(pExcept);
  1017. }
  1018. #elif defined(_M_AMD64)
  1019. if(IsRethrow) {
  1020. pFrameInfo->isRethrow = TRUE;
  1021. }
  1022. else if( pExcept != NULL && pExceptionObjectDestroyed == NULL ) {
  1023. pFrameInfo->pExceptionObjectToBeDestroyed = PER_PEXCEPTOBJ(pExcept);
  1024. }
  1025. #elif defined(_POWERPC)
  1026. pFrameInfo = _CreateFrameInfo(&FrameInfo, pDC, pEstablisher, pExitContext,
  1027. (FUNC_UNWIND(*pFuncInfo, TBME_LOW(*pEntry))).toState);
  1028. #elif defined(_M_ALPHA)
  1029. SetState(pRN, pDC, pFuncInfo,
  1030. (FUNC_UNWIND(*pFuncInfo, TBME_LOW(*pEntry))).toState);
  1031. #else
  1032. EHTRACE_FMT2("Move from state %d to state %d", __GetUnwindState(pRN, pDC, pFuncInfo), TBME_HIGH(*pEntry) + 1);
  1033. SetState(pRN, pDC, pFuncInfo, TBME_HIGH(*pEntry) + 1);
  1034. #endif
  1035. continuationAddress = CallCatchBlock(pExcept, pEstablisher, pContext,
  1036. pFuncInfo, __GetAddress(HT_HANDLER(*pCatch), pDC), CatchDepth, 0x100
  1037. #if defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  1038. , pFrameInfo
  1039. #endif
  1040. );
  1041. // Transfer control to the continuation address. If no continuation then
  1042. // it's a re-throw, so return.
  1043. if (continuationAddress != NULL) {
  1044. #if defined(_M_MRX000) || defined(_POWERPC) || defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  1045. // Exit gracefully to the continuation adddress.
  1046. //
  1047. // We are done, but we have to blow away the stack below the frame where
  1048. // the try-block resides. In addition, we have to resore a bunch of
  1049. // other registers besides SP as well. Leave that task up to
  1050. // _JumpToContinuation.
  1051. //
  1052. // The code that is commented out below worked well until we hit the
  1053. // scenario of:
  1054. //
  1055. // void foo()
  1056. // {
  1057. // try {
  1058. // bar();
  1059. // }
  1060. // catch(int) {
  1061. // }
  1062. // }
  1063. //
  1064. // void bar()
  1065. // {
  1066. // __try {
  1067. // throw 1;
  1068. // }
  1069. // __finally {
  1070. // }
  1071. // }
  1072. //
  1073. // In the above example, RtlUnwind would call the __finally's handler
  1074. // twice. Once for the original unwind through the call to
  1075. // _UnwindNestedFrames, then here where all we want is to get to the
  1076. // continuation point.
  1077. //
  1078. // ExitContext was saved during the original unwind when we detected the
  1079. // target of the unwind in __InternalCxxFrameHandler.
  1080. #if defined(_M_MRX000)
  1081. DASSERT(VER41_C2(pFuncInfo));
  1082. PVOID pRealFrame = _OffsetToAddress(0, pRN, FUNC_FRAMENEST(*pFuncInfo));
  1083. UNWINDHELP(pRealFrame, FUNC_DISPUNWINDHELP(*pFuncInfo), 0) = -1;
  1084. #elif defined(_M_AMD64)
  1085. UNWINDHELP(*pEstablisher, FUNC_DISPUNWINDHELP(*pFuncInfo)) = -2;
  1086. FRAMEINFO * pContFrameInfo = _FindFrameInfo(continuationAddress, pFrameInfo);
  1087. if( pContFrameInfo != NULL && !pContFrameInfo->isRethrow
  1088. && pContFrameInfo->pExceptionObjectToBeDestroyed
  1089. && !_IsExceptionObjectDestroyed(pContFrameInfo->pExceptionObjectToBeDestroyed,pFrameInfo)
  1090. ) {
  1091. __DestructExceptionObject(pContFrameInfo->pExcept, TRUE);
  1092. _MarkExceptionObjectDestroyed(pContFrameInfo->pExcept);
  1093. }
  1094. #elif defined(_M_IA64) /*IFSTRIP=IGN*/
  1095. UNWINDHELP(pEstablisher->MemoryStackFp, FUNC_DISPUNWINDHELP(*pFuncInfo)) = -2;
  1096. FRAMEINFO * pContFrameInfo = _FindFrameInfo(continuationAddress, pFrameInfo);
  1097. if( pContFrameInfo != NULL && !pContFrameInfo->isRethrow
  1098. && pContFrameInfo->pExceptionObjectToBeDestroyed
  1099. && !_IsExceptionObjectDestroyed(pContFrameInfo->pExceptionObjectToBeDestroyed,pFrameInfo)
  1100. ) {
  1101. __DestructExceptionObject(pContFrameInfo->pExcept, TRUE);
  1102. }
  1103. else if( pFrameInfo != NULL && pFrameInfo != pContFrameInfo
  1104. && !_IsExceptionObjectDestroyed(PER_PEXCEPTOBJ(pExcept),pFrameInfo)
  1105. ) {
  1106. __DestructExceptionObject(pExcept, TRUE);
  1107. }
  1108. #endif // defined(_M_MRX000)
  1109. __ResetException(pExcept);
  1110. pExitContext = NULL;
  1111. #if defined(_WIN64)
  1112. _JumpToContinuation((unsigned __int64)continuationAddress,
  1113. #else
  1114. _JumpToContinuation((ULONG)continuationAddress,
  1115. #endif
  1116. _FindAndUnlinkFrame(continuationAddress, pFrameInfo)
  1117. #if defined(_M_IA64) || defined(_M_AMD64)
  1118. ,pExcept
  1119. #endif
  1120. );
  1121. #else // !(defined(_M_MRX000) || defined(_POWERPC)) || defined(_M_IA64) || defined(_M_AMD64)
  1122. _JumpToContinuation(continuationAddress, pRN);
  1123. #endif
  1124. // No return.
  1125. #if defined(_POWERPC)
  1126. } else {
  1127. _FindAndUnlinkFrame(NULL, pFrameInfo);
  1128. #elif defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  1129. } else {
  1130. _UnlinkFrame(pFrameInfo);
  1131. #endif
  1132. }
  1133. EHTRACE_EXIT;
  1134. }
  1135. ////////////////////////////////////////////////////////////////////////////////
  1136. //
  1137. // CallCatchBlock - continuation of CatchIt.
  1138. //
  1139. // This is seperated from CatchIt because it needs to introduce an SEH/EH frame
  1140. // in case the catch block throws. This frame cannot be added until unwind of
  1141. // nested frames has been completed (otherwise this frame would be the first
  1142. // to go).
  1143. static void *CallCatchBlock(
  1144. EHExceptionRecord *pExcept, // The exception thrown
  1145. EHRegistrationNode *pRN, // Dynamic info of function with catch
  1146. CONTEXT *pContext, // Context info
  1147. FuncInfo *pFuncInfo, // Static info of function with catch
  1148. void *handlerAddress, // Code address of handler
  1149. int CatchDepth, // How deeply nested in catch blocks
  1150. // are we?
  1151. unsigned long NLGCode // NLG destination code
  1152. #if defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  1153. ,
  1154. FRAMEINFO *pFrameInfo
  1155. #endif
  1156. ) {
  1157. EHTRACE_ENTER;
  1158. // Address where execution resumes after exception handling completed.
  1159. // Initialized to non-NULL (value doesn't matter) to distinguish from
  1160. // re-throw in __finally.
  1161. void *continuationAddress = handlerAddress;
  1162. BOOL ExceptionObjectDestroyed = FALSE;
  1163. #if defined(_M_IX86)
  1164. // The stack pointer at entry to the try must be saved, in case there is
  1165. // another try inside this catch. We'll restore it on our way out.
  1166. void *saveESP = PRN_STACK(pRN);
  1167. // Push this catch block's frame info on a linked list
  1168. FRAMEINFO FrameInfo;
  1169. FRAMEINFO *pFrameInfo = _CreateFrameInfo(&FrameInfo, PER_PEXCEPTOBJ(pExcept));
  1170. #endif
  1171. // Save the current exception in case of a rethrow. Save the previous value
  1172. // on the stack, to be restored when the catch exits.
  1173. EHExceptionRecord *pSaveException = _pCurrentException;
  1174. CONTEXT *pSaveExContext = _pCurrentExContext;
  1175. _pCurrentException = pExcept;
  1176. _pCurrentExContext = pContext;
  1177. __try {
  1178. __try {
  1179. // Execute the handler as a funclet, whose return value is the
  1180. // address to resume execution.
  1181. #if defined(_M_IX86)
  1182. continuationAddress = _CallCatchBlock2(pRN, pFuncInfo,
  1183. handlerAddress, CatchDepth, NLGCode);
  1184. #else
  1185. continuationAddress = _CallSettingFrame(handlerAddress,
  1186. REAL_FP(pRN, pFuncInfo), NLGCode);
  1187. #endif
  1188. } __except(EHTRACE_EXCEPT(ExFilterRethrow(exception_info()))) {
  1189. #if defined(_M_IX86)
  1190. // Here we are exiting the catch block on rethrow out of this
  1191. // catch block. To keep the order of destruction and construction
  1192. // same when the the rethrow was from function or was inline, here
  1193. // we unwind to the parent state for this catch.
  1194. UnwindMapEntry *pUnwindMap = pFuncInfo->pUnwindMap;
  1195. int cState = GetCurrentState(pRN, handlerAddress, pFuncInfo);
  1196. TryBlockMapEntry *pTryBlockMap = pFuncInfo->pTryBlockMap;
  1197. unsigned int i;
  1198. for (i = 0; i < pFuncInfo->nTryBlocks; i++) {
  1199. if (cState > pTryBlockMap[i].tryHigh &&
  1200. cState <= pTryBlockMap[i].catchHigh) {
  1201. cState = pTryBlockMap[i].tryHigh +1;
  1202. cState = pUnwindMap[cState].toState;
  1203. break;
  1204. }
  1205. }
  1206. __FrameUnwindToState(pRN, NULL, pFuncInfo, cState);
  1207. #endif
  1208. // If the handler threw a typed exception without exception info or
  1209. // exception object, then it's a re-throw, so return. Otherwise
  1210. // it's a new exception, which takes precedence over this one.
  1211. continuationAddress = NULL;
  1212. }
  1213. } __finally {
  1214. EHTRACE_SAVE_LEVEL;
  1215. EHTRACE_FMT1("Executing __finally, %snormal termination", _abnormal_termination() ? "ab" : "");
  1216. #if defined(_M_IX86)
  1217. // Restore the saved stack pointer, so the stack can be reset when
  1218. // we're done.
  1219. PRN_STACK(pRN) = saveESP;
  1220. // Pop this catch block's frame info
  1221. _FindAndUnlinkFrame(pFrameInfo);
  1222. #endif
  1223. // Restore the 'current exception' for a possibly enclosing catch
  1224. _pCurrentException = pSaveException;
  1225. _pCurrentExContext = pSaveExContext;
  1226. // Destroy the original exception object if we're not exiting on a
  1227. // re-throw and the object isn't also in use by a more deeply nested
  1228. // catch. Note that the catch handles destruction of its parameter.
  1229. if (PER_IS_MSVC_EH(pExcept) && !ExceptionObjectDestroyed
  1230. && continuationAddress != NULL
  1231. #if defined(_M_IA64) || defined(_M_AMD64)
  1232. && !_IsExceptionObjectDestroyed(PER_PEXCEPTOBJ(pExcept),pFrameInfo)
  1233. && !pFrameInfo->isRethrow
  1234. #elif defined(_M_IX86)
  1235. && IsExceptionObjectToBeDestroyed(PER_PEXCEPTOBJ(pExcept))
  1236. #endif
  1237. ) {
  1238. #if defined(_M_IA64) || defined(_M_AMD64)
  1239. pFrameInfo->dtorThrowFlag = TRUE;
  1240. #endif
  1241. __DestructExceptionObject(pExcept, abnormal_termination());
  1242. #if defined(_M_MRX000)
  1243. ExceptionObjectDestroyed = TRUE;
  1244. #endif
  1245. }
  1246. EHTRACE_RESTORE_LEVEL(!!_abnormal_termination());
  1247. }
  1248. EHTRACE_EXIT;
  1249. #if defined(_M_IA64) || defined(_M_AMD64)
  1250. pFrameInfo->dtorThrowFlag = FALSE;
  1251. #endif
  1252. return continuationAddress;
  1253. }
  1254. ////////////////////////////////////////////////////////////////////////////////
  1255. //
  1256. // ExFilterRethrow - Exception filter for re-throw exceptions.
  1257. //
  1258. // Returns:
  1259. // EXCEPTION_EXECUTE_HANDLER - exception was a re-throw
  1260. // EXCEPTION_CONTINUE_SEARCH - anything else
  1261. //
  1262. // Side-effects: NONE.
  1263. static int ExFilterRethrow(
  1264. EXCEPTION_POINTERS *pExPtrs
  1265. ) {
  1266. // Get the exception record thrown (don't care about other info)
  1267. EHExceptionRecord *pExcept = (EHExceptionRecord *)pExPtrs->ExceptionRecord;
  1268. // Check if it's ours and it's has no exception information.
  1269. if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == NULL) {
  1270. return EXCEPTION_EXECUTE_HANDLER;
  1271. } else {
  1272. return EXCEPTION_CONTINUE_SEARCH;
  1273. }
  1274. }
  1275. ////////////////////////////////////////////////////////////////////////////////
  1276. //
  1277. // BuildCatchObject - Copy or construct the catch object from the object thrown.
  1278. //
  1279. // Returns:
  1280. // nothing.
  1281. //
  1282. // Side-effects:
  1283. // A buffer in the subject function's frame is initialized.
  1284. //
  1285. // Open issues:
  1286. // What happens if the constructor throws? (or faults?)
  1287. static void BuildCatchObject(
  1288. EHExceptionRecord *pExcept, // Original exception thrown
  1289. void *pRN, // This is a pointer to the object
  1290. // that we want to build while doing
  1291. // COM+ eh. If we are in our own eh,
  1292. // then this is a Registration node of
  1293. // catching function
  1294. HandlerType *pCatch, // The catch clause that got it
  1295. CatchableType *pConv // The conversion to use
  1296. ) {
  1297. EHTRACE_ENTER;
  1298. // If the catch is by ellipsis, then there is no object to construct.
  1299. // If the catch is by type(No Catch Object), then leave too!
  1300. if (HT_IS_TYPE_ELLIPSIS(*pCatch) ||
  1301. (!HT_DISPCATCH(*pCatch) && !HT_ISCOMPLUSEH(*pCatch))) {
  1302. EHTRACE_EXIT;
  1303. return;
  1304. }
  1305. void **pCatchBuffer;
  1306. if ( HT_ISCOMPLUSEH(*pCatch))
  1307. {
  1308. pCatchBuffer = (void **)pRN;
  1309. }
  1310. else
  1311. {
  1312. #if defined(_M_IA64) /*IFSTRIP=IGN*/
  1313. pCatchBuffer = (void **)__OffsetToAddress(
  1314. HT_DISPCATCH(*pCatch),
  1315. ((EHRegistrationNode *)pRN)->MemoryStackFp,
  1316. HT_FRAMENEST(*pCatch)
  1317. );
  1318. #elif defined(_M_AMD64)
  1319. pCatchBuffer = (void **)__OffsetToAddress(
  1320. HT_DISPCATCH(*pCatch),
  1321. *((EHRegistrationNode *)pRN),
  1322. HT_FRAMENEST(*pCatch)
  1323. );
  1324. #else
  1325. pCatchBuffer = (void **)__OffsetToAddress(
  1326. HT_DISPCATCH(*pCatch),
  1327. (EHRegistrationNode *)pRN,
  1328. HT_FRAMENEST(*pCatch)
  1329. );
  1330. #endif
  1331. }
  1332. __try {
  1333. if (HT_ISREFERENCE(*pCatch)) {
  1334. // The catch is of form 'reference to T'. At the throw point we
  1335. // treat both 'T' and 'reference to T' the same, i.e.
  1336. // pExceptionObject is a (machine) pointer to T. Adjust as
  1337. // required.
  1338. if (_ValidateRead(PER_PEXCEPTOBJ(pExcept))
  1339. && _ValidateWrite(pCatchBuffer)) {
  1340. *pCatchBuffer = PER_PEXCEPTOBJ(pExcept);
  1341. *pCatchBuffer = AdjustPointer(*pCatchBuffer,
  1342. CT_THISDISP(*pConv));
  1343. } else {
  1344. _inconsistency(); // Does not return; TKB
  1345. }
  1346. } else if (CT_ISSIMPLETYPE(*pConv)) {
  1347. // Object thrown is of simple type (this including pointers) copy
  1348. // specified number of bytes. Adjust the pointer as required. If
  1349. // the thing is not a pointer, then this should be safe since all
  1350. // the entries in the THISDISP are 0.
  1351. if (_ValidateRead(PER_PEXCEPTOBJ(pExcept))
  1352. && _ValidateWrite(pCatchBuffer)) {
  1353. memmove(pCatchBuffer, PER_PEXCEPTOBJ(pExcept), CT_SIZE(*pConv));
  1354. if (CT_SIZE(*pConv) == sizeof(void*) && *pCatchBuffer != NULL) {
  1355. *pCatchBuffer = AdjustPointer(*pCatchBuffer,
  1356. CT_THISDISP(*pConv));
  1357. }
  1358. } else {
  1359. _inconsistency(); // Does not return; TKB
  1360. }
  1361. } else {
  1362. // Object thrown is UDT.
  1363. if (CT_COPYFUNC(*pConv) == NULL) {
  1364. // The UDT had a simple ctor. Adjust in the thrown object,
  1365. // then copy n bytes.
  1366. if (_ValidateRead(PER_PEXCEPTOBJ(pExcept))
  1367. && _ValidateWrite(pCatchBuffer)) {
  1368. memmove(pCatchBuffer, AdjustPointer(PER_PEXCEPTOBJ(pExcept),
  1369. CT_THISDISP(*pConv)), CT_SIZE(*pConv));
  1370. } else {
  1371. _inconsistency(); // Does not return; TKB
  1372. }
  1373. } else {
  1374. // It's a UDT: make a copy using copy ctor
  1375. #pragma warning(disable:4191)
  1376. if (_ValidateRead(PER_PEXCEPTOBJ(pExcept))
  1377. && _ValidateWrite(pCatchBuffer)
  1378. && _ValidateExecute((FARPROC)CT_COPYFUNC(*pConv))) {
  1379. #pragma warning(default:4191)
  1380. if (CT_HASVB(*pConv)) {
  1381. _CallMemberFunction2((char *)pCatchBuffer,
  1382. CT_COPYFUNC(*pConv),
  1383. AdjustPointer(PER_PEXCEPTOBJ(pExcept),
  1384. CT_THISDISP(*pConv)), 1);
  1385. } else {
  1386. _CallMemberFunction1((char *)pCatchBuffer,
  1387. CT_COPYFUNC(*pConv),
  1388. AdjustPointer(PER_PEXCEPTOBJ(pExcept),
  1389. CT_THISDISP(*pConv)));
  1390. }
  1391. } else {
  1392. _inconsistency(); // Does not return; TKB
  1393. }
  1394. }
  1395. }
  1396. } __except(EHTRACE_EXCEPT(EXCEPTION_EXECUTE_HANDLER)) {
  1397. // Something went wrong when building the catch object.
  1398. terminate();
  1399. }
  1400. EHTRACE_EXIT;
  1401. }
  1402. ////////////////////////////////////////////////////////////////////////////////
  1403. //
  1404. // __DestructExceptionObject - Call the destructor (if any) of the original
  1405. // exception object.
  1406. //
  1407. // Returns: None.
  1408. //
  1409. // Side-effects:
  1410. // Original exception object is destructed.
  1411. //
  1412. // Notes:
  1413. // If destruction throws any exception, and we are destructing the exception
  1414. // object as a result of a new exception, we give up. If the destruction
  1415. // throws otherwise, we let it be.
  1416. extern "C" void _CRTIMP __DestructExceptionObject(
  1417. EHExceptionRecord *pExcept, // The original exception record
  1418. BOOLEAN fThrowNotAllowed // TRUE if destructor not allowed to
  1419. // throw
  1420. ) {
  1421. EHTRACE_ENTER_FMT1("Destroying object @ 0x%p", PER_PEXCEPTOBJ(pExcept));
  1422. if (pExcept != NULL && THROW_UNWINDFUNC(*PER_PTHROW(pExcept)) != NULL) {
  1423. __try {
  1424. // M00REVIEW: A destructor has additional hidden arguments, doesn't
  1425. // it?
  1426. #if defined(_M_IA64) || defined(_M_AMD64) /*IFSTRIP=IGN*/
  1427. _MarkExceptionObjectDestroyed(pExcept);
  1428. _CallMemberFunction0(PER_PEXCEPTOBJ(pExcept),
  1429. THROW_UNWINDFUNC_IB(*PER_PTHROW(pExcept),(unsigned __int64)PER_PTHROWIB(pExcept)));
  1430. #else
  1431. _CallMemberFunction0(PER_PEXCEPTOBJ(pExcept),
  1432. THROW_UNWINDFUNC(*PER_PTHROW(pExcept)));
  1433. #endif
  1434. __ResetException(pExcept);
  1435. } __except(EHTRACE_EXCEPT(fThrowNotAllowed
  1436. ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)) {
  1437. // Can't have new exceptions when we're unwinding due to another
  1438. // exception.
  1439. terminate();
  1440. }
  1441. }
  1442. EHTRACE_EXIT;
  1443. }
  1444. ////////////////////////////////////////////////////////////////////////////////
  1445. //
  1446. // AdjustPointer - Adjust the pointer to the exception object to a pointer to a
  1447. // base instance.
  1448. //
  1449. // Output:
  1450. // The address point of the base.
  1451. //
  1452. // Side-effects:
  1453. // NONE.
  1454. static void *AdjustPointer(
  1455. void *pThis, // Address point of exception object
  1456. const PMD& pmd // Generalized pointer-to-member
  1457. // descriptor
  1458. ) {
  1459. char *pRet = (char *)pThis + pmd.mdisp;
  1460. if (pmd.pdisp >= 0) {
  1461. pRet += *(__int32 *)((char *)*(ptrdiff_t *)((char *)pThis + pmd.pdisp)
  1462. #if defined(_WIN64)
  1463. + (unsigned _int64)pmd.vdisp);
  1464. #else
  1465. + pmd.vdisp);
  1466. #endif
  1467. pRet += pmd.pdisp;
  1468. }
  1469. return pRet;
  1470. }
  1471. ///////////////////////////////////////////////////////////////////////////////
  1472. //
  1473. // __uncaught_exception() - Returns true after completing of a throw-expression
  1474. // untils completing initialization of the
  1475. // exception-declaration in the matching handler.
  1476. //
  1477. bool __uncaught_exception()
  1478. {
  1479. return (__ProcessingThrow != 0);
  1480. }
  1481. #if !defined(_M_IA64) && !defined(_M_AMD64) // Enable&fix for IA64 when COM+ C++ EH support available there
  1482. ////////////////////////////////////////////////////////////////////////////////
  1483. // Model of C++ eh in COM+
  1484. //
  1485. // void func()
  1486. // {
  1487. // try {
  1488. // TryBody();
  1489. // } catch (cpp_object o)
  1490. // {
  1491. // CatchOBody();
  1492. // } catch (...)
  1493. // {
  1494. // CatchAllBody();
  1495. // }
  1496. // }
  1497. //
  1498. // Turns into this:
  1499. //
  1500. //
  1501. // void func()
  1502. // {
  1503. // int rethrow;
  1504. // // One per try block
  1505. // int isCxxException;
  1506. // // One per catch(...)
  1507. // __try {
  1508. // TryBody();
  1509. // }
  1510. // __except(__CxxExceptionFilter(exception,
  1511. // typeinfo(cpp_object),
  1512. // flags,
  1513. // &o))
  1514. // // This is how it's done already
  1515. // {
  1516. // // Begin catch(object) prefix
  1517. // char *storage = _alloca(__CxxQueryExceptionSize());
  1518. // rethrow = false;
  1519. // __CxxRegisterExceptionObject(exception,
  1520. // storage);
  1521. // __try {
  1522. // __try {
  1523. // // End catch(object) prefix
  1524. // CatchOBody();
  1525. // // Begin catch(object) suffix
  1526. // } __except(rethrow = __CxxDetectRethrow(exception),
  1527. // EXCEPTION_CONTINUE_SEARCH)
  1528. // {}
  1529. // }
  1530. // __finally
  1531. // {
  1532. // __CxxUnregisterExceptionObject(storage,
  1533. // rethrow);
  1534. // }
  1535. // // End catch(object) suffix
  1536. // }
  1537. // __except(1)
  1538. // {
  1539. // // Begin catch(...) prefix
  1540. // char *storage = _alloca(__CxxQueryExceptionSize());
  1541. // rethrow = false;
  1542. // isCxxException = __CxxRegisterExceptionObject(exception,
  1543. // storage);
  1544. // __try
  1545. // {
  1546. // __try
  1547. // {
  1548. // // End catch(...) prefix
  1549. // CatchAllBody();
  1550. // // Begin catch(...) suffix
  1551. // } __except(rethrow = __CxxDetectRethrow(exception),
  1552. // EXCEPTION_CONTINUE_SEARCH)
  1553. // {}
  1554. // } __finally
  1555. // {
  1556. // if (isCxxException)
  1557. // __CxxUnregisterExceptionObject(storage, rethrow);
  1558. // }
  1559. // // End catch(...) suffix
  1560. // }
  1561. // }
  1562. //
  1563. ////////////////////////////////////////////////////////////////////////////////
  1564. ////////////////////////////////////////////////////////////////////////////////
  1565. //
  1566. // __CxxExceptionFilter() - Returns EXCEPTION_EXECUTE_HANDLER when the pType
  1567. // matches with the objects we can catch. Returns
  1568. // EXCEPTION_CONTINUE_SEARCH when pType is not one of
  1569. // the catchable type for the thrown object. This
  1570. // function is made for use with COM+ EH, where they
  1571. // attempt to do C++ EH as well.
  1572. //
  1573. extern "C" int __cdecl __CxxExceptionFilter(
  1574. void *ppExcept, // Information for this (logical)
  1575. // exception
  1576. void *pType, // Info about the datatype.
  1577. int adjectives, // Extra Info about the datatype.
  1578. void *pBuildObj // Pointer to datatype.
  1579. )
  1580. {
  1581. struct _s_HandlerType pCatch;
  1582. #if defined(_M_IA64) || defined(_M_AMD64)
  1583. __int32 const *ppCatchable;
  1584. #elif defined(_WIN64)
  1585. CatchableType * UNALIGNED const *ppCatchable;
  1586. #else
  1587. CatchableType * const *ppCatchable;
  1588. #endif
  1589. CatchableType *pCatchable;
  1590. int catchables;
  1591. EHExceptionRecord *pExcept;
  1592. if (!ppExcept)
  1593. return EXCEPTION_CONTINUE_SEARCH;
  1594. pExcept = *(EHExceptionRecord **)ppExcept;
  1595. // If catch all, always return EXCEPTION_EXECUTE_HANDLER
  1596. if ( TD_IS_TYPE_ELLIPSIS((TypeDescriptor *)pType))
  1597. {
  1598. if (PER_IS_MSVC_EH(pExcept))
  1599. {
  1600. if ( PER_PTHROW(pExcept) == NULL)
  1601. {
  1602. if ( _pCurrentException != NULL)
  1603. *(EHExceptionRecord **)ppExcept = _pCurrentException;
  1604. else
  1605. return EXCEPTION_CONTINUE_SEARCH;
  1606. }
  1607. }
  1608. __ProcessingThrow++;
  1609. return EXCEPTION_EXECUTE_HANDLER;
  1610. }
  1611. if (PER_IS_MSVC_EH(pExcept))
  1612. {
  1613. if ( PER_PTHROW(pExcept) == NULL) {
  1614. if (_pCurrentException == NULL)
  1615. return EXCEPTION_CONTINUE_SEARCH;
  1616. pExcept = _pCurrentException;
  1617. }
  1618. pCatch.pType = (TypeDescriptor *)pType;
  1619. pCatch.adjectives = adjectives;
  1620. SET_HT_ISCOMPLUSEH(pCatch);
  1621. // Scan all types that thrown object can be converted to:
  1622. ppCatchable = THROW_CTLIST(*PER_PTHROW(pExcept));
  1623. for (catchables = THROW_COUNT(*PER_PTHROW(pExcept));
  1624. catchables > 0; catchables--, ppCatchable++) {
  1625. #if defined(_M_IA64) || defined(_M_AMD64)
  1626. pCatchable = (CatchableType *)(_GetThrowImageBase() + *ppCatchable);
  1627. #else
  1628. pCatchable = *ppCatchable;
  1629. #endif
  1630. if (TypeMatch(&pCatch, pCatchable, PER_PTHROW(pExcept))) {
  1631. // SucessFull. Now build the object.
  1632. __ProcessingThrow++;
  1633. if (pBuildObj != NULL)
  1634. BuildCatchObject(pExcept, pBuildObj, &pCatch, pCatchable);
  1635. // We set the current exception.
  1636. if ( PER_PTHROW(*(EHExceptionRecord **)ppExcept) == NULL)
  1637. *(EHExceptionRecord **)ppExcept = _pCurrentException;
  1638. return EXCEPTION_EXECUTE_HANDLER;
  1639. }
  1640. } // Scan posible conversions
  1641. }
  1642. return EXCEPTION_CONTINUE_SEARCH;
  1643. }
  1644. ////////////////////////////////////////////////////////////////////////////////
  1645. //
  1646. // __CxxRgisterExceptionObject() - Registers Exception Object and saves it to
  1647. // This is same as first part of
  1648. // CallCatchBlock.
  1649. //
  1650. extern "C" int __cdecl __CxxRegisterExceptionObject(
  1651. void *ppExcept,
  1652. void *pStorage
  1653. )
  1654. {
  1655. // This function is only called for C++ EH.
  1656. EHExceptionRecord *pExcept;
  1657. FRAMEINFO *pFrameInfo = (FRAMEINFO *)pStorage;
  1658. EHExceptionRecord **ppSaveException;
  1659. CONTEXT **ppSaveExContext;
  1660. ppSaveException = (EHExceptionRecord **)(&pFrameInfo[1]);
  1661. ppSaveExContext = (CONTEXT **)(&ppSaveException[1]);
  1662. pExcept = *(EHExceptionRecord **)ppExcept;
  1663. pFrameInfo = _CreateFrameInfo(pFrameInfo, PER_PEXCEPTOBJ(pExcept));
  1664. *ppSaveException = _pCurrentException;
  1665. *ppSaveExContext = _pCurrentExContext;
  1666. _pCurrentException = pExcept;
  1667. __ProcessingThrow--;
  1668. if ( __ProcessingThrow < 0)
  1669. __ProcessingThrow = 0;
  1670. return 1;
  1671. }
  1672. ////////////////////////////////////////////////////////////////////////////////
  1673. //
  1674. // __CxxDetectRethrow() - Looks at the Exception and returns true if rethrow,
  1675. // false if not a rethrow. This is then used for
  1676. // destructing the exception object in
  1677. // __CxxUnregisterExceptionObject().
  1678. //
  1679. extern "C" int __cdecl __CxxDetectRethrow(
  1680. void *ppExcept
  1681. )
  1682. {
  1683. EHExceptionRecord *pExcept;
  1684. if (!ppExcept)
  1685. return 0;
  1686. pExcept = *(EHExceptionRecord **)ppExcept;
  1687. if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == NULL) {
  1688. *(EHExceptionRecord **)ppExcept = _pCurrentException;
  1689. return 1;
  1690. } else if (*(EHExceptionRecord **)ppExcept == _pCurrentException)
  1691. return 1;
  1692. return 0;
  1693. }
  1694. ////////////////////////////////////////////////////////////////////////////////
  1695. //
  1696. // __CxxUnregisterExceptionObject - Destructs Exception Objects if rethrow ==
  1697. // true. Also set __pCurrentException and
  1698. // __pCurrentExContext() to current value.
  1699. //
  1700. extern "C" void __cdecl __CxxUnregisterExceptionObject(
  1701. void *pStorage,
  1702. int rethrow
  1703. )
  1704. {
  1705. FRAMEINFO *pFrameInfo = (FRAMEINFO *)pStorage;
  1706. EHExceptionRecord **ppSaveException;
  1707. CONTEXT **ppSaveExContext;
  1708. ppSaveException = (EHExceptionRecord **)(&pFrameInfo[1]);
  1709. ppSaveExContext = (CONTEXT **)(&ppSaveException[1]);
  1710. _FindAndUnlinkFrame(pFrameInfo);
  1711. if ( !rethrow && PER_IS_MSVC_EH(_pCurrentException) && IsExceptionObjectToBeDestroyed(PER_PEXCEPTOBJ(_pCurrentException))) {
  1712. __DestructExceptionObject(_pCurrentException, TRUE);
  1713. }
  1714. _pCurrentException = *ppSaveException;
  1715. _pCurrentExContext = *ppSaveExContext;
  1716. }
  1717. ////////////////////////////////////////////////////////////////////////////////
  1718. //
  1719. // __CxxQueryExceptionSize - returns the value of Storage needed to save
  1720. // FrameInfo + two pointers.
  1721. //
  1722. extern "C" int __cdecl __CxxQueryExceptionSize(
  1723. void
  1724. )
  1725. {
  1726. return sizeof(FRAMEINFO) + sizeof(void *) + sizeof(void *);
  1727. }
  1728. ////////////////////////////////////////////////////////////////////////////////
  1729. //
  1730. // __CxxCallUnwindDtor - Calls a destructor during unwind. For COM+, the dtor
  1731. // call needs to be wrapped inside a __try/__except to
  1732. // get correct terminate() behavior when an exception
  1733. // occurs during the dtor call.
  1734. //
  1735. extern "C" void __cdecl __CxxCallUnwindDtor(
  1736. void (__thiscall * pDtor)(void*),
  1737. void *pThis
  1738. )
  1739. {
  1740. __try
  1741. {
  1742. (*pDtor)(pThis);
  1743. }
  1744. __except(FrameUnwindFilter(exception_info()))
  1745. {
  1746. }
  1747. }
  1748. #endif // ndef _M_IA64