Leaked source code of windows server 2003
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.

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