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.

641 lines
23 KiB

  1. /***
  2. *trnsctrl.cpp -
  3. *
  4. * Copyright (c) 1990-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *Revision History:
  9. * 06-01-97 Created by TiborL.
  10. * 07-12-99 RDL Image relative fixes under CC_P7_SOFT25.
  11. * 10-07-99 SAH utc_p7#1126: fix ipsr.ri reset.
  12. * 10-19-99 TGL Miscellaneous unwind fixes.
  13. * 03-15-00 PML Remove CC_P7_SOFT25, which is now on permanently.
  14. * 03-30-00 SAH New version of GetLanguageSpecificData from ntia64.h.
  15. * 06-08-00 RDL VS#111429: IA64 workaround for AV while handling throw.
  16. *
  17. ****/
  18. #if defined(_NTSUBSET_)
  19. extern "C" {
  20. #include <nt.h>
  21. #include <ntrtl.h>
  22. #include <nturtl.h>
  23. #include <ntstatus.h> // STATUS_UNHANDLED_EXCEPTION
  24. #include <ntos.h>
  25. #include <ex.h> // ExRaiseException
  26. }
  27. #endif
  28. extern "C" {
  29. #include <windows.h>
  30. };
  31. #include <mtdll.h>
  32. #include <ehassert.h>
  33. #include <ehdata.h>
  34. #include <trnsctrl.h>
  35. #include <ehstate.h>
  36. #include <eh.h>
  37. #include <ehhooks.h>
  38. #include <kxia64.h>
  39. #include <ia64inst.h>
  40. #include <cvconst.h>
  41. #pragma hdrstop
  42. #ifdef _MT
  43. #define pFrameInfoChain (*((FRAMEINFO **) &(_getptd()->_pFrameInfoChain)))
  44. #define pUnwindContext (*((CONTEXT **) &(_getptd()->_pUnwindContext)))
  45. #define _ImageBase (_getptd()->_ImageBase)
  46. #define _TargetGp (_getptd()->_TargetGp)
  47. #define _ThrowImageBase (_getptd()->_ThrowImageBase)
  48. #define _pCurrentException (*((EHExceptionRecord **)&(_getptd()->_curexception)))
  49. #else
  50. static FRAMEINFO *pFrameInfoChain = NULL; // used to remember nested frames
  51. static CONTEXT *pUnwindContext = NULL; // context to assist the return to 'UnwindNestedFrames'
  52. static unsigned __int64 _ImageBase = 0;
  53. static unsigned __int64 _ThrowImageBase = 0;
  54. static unsigned __int64 _TargetGp = 0;
  55. extern EHExceptionRecord *_pCurrentException; // defined in frame.cpp
  56. #endif
  57. // Should be used out of ntia64.h, but can't figure out how to allow that with
  58. // existing dependencies.
  59. // If GetLanguageSpecificData changes cause a redefinition error rather than
  60. // using wrong version.
  61. // Version 2 = soft2.3 conventions
  62. // Version 3 = soft2.6 conventions
  63. #define GetLanguageSpecificData(f, base) \
  64. ((((PUNWIND_INFO)(base + f->UnwindInfoAddress))->Version <= 2) ? \
  65. (((PVOID)(base + f->UnwindInfoAddress + sizeof(UNWIND_INFO) + \
  66. ((PUNWIND_INFO)(base+f->UnwindInfoAddress))->DataLength*sizeof(ULONGLONG) + sizeof(ULONGLONG)))) : \
  67. (((PVOID)(base + f->UnwindInfoAddress + sizeof(UNWIND_INFO) + \
  68. ((PUNWIND_INFO)(base+f->UnwindInfoAddress))->DataLength*sizeof(ULONGLONG) + sizeof(ULONG)))))
  69. extern "C" VOID RtlRestoreContext (PCONTEXT ContextRecord,PEXCEPTION_RECORD ExceptionRecord OPTIONAL);
  70. extern "C" void RtlCaptureContext(CONTEXT*);
  71. extern "C" void _GetNextInstrOffset(PVOID*);
  72. extern "C" void __FrameUnwindToState(EHRegistrationNode *, DispatcherContext *, FuncInfo *, __ehstate_t);
  73. //
  74. // Returns the establisher frame pointers. For catch handlers it is the parent's frame pointer.
  75. //
  76. EHRegistrationNode *_GetEstablisherFrame(
  77. EHRegistrationNode *pRN,
  78. DispatcherContext *pDC,
  79. FuncInfo *pFuncInfo,
  80. EHRegistrationNode *pEstablisher
  81. ) {
  82. TryBlockMapEntry *pEntry;
  83. unsigned num_of_try_blocks = FUNC_NTRYBLOCKS(*pFuncInfo);
  84. unsigned index;
  85. __ehstate_t curState;
  86. curState = _StateFromControlPc(pFuncInfo, pDC);
  87. pEstablisher->MemoryStackFp = pRN->MemoryStackFp;
  88. pEstablisher->BackingStoreFp = pRN->BackingStoreFp;
  89. for (index = 0; index < num_of_try_blocks; index++) {
  90. pEntry = FUNC_PTRYBLOCK(*pFuncInfo, index, pDC->ImageBase);
  91. if (curState > TBME_HIGH(*pEntry) && curState <= TBME_CATCHHIGH(*pEntry)) {
  92. pEstablisher->MemoryStackFp = *(__int64 *)OffsetToAddress(-8,pRN->MemoryStackFp);
  93. pEstablisher->BackingStoreFp = *(__int64 *)OffsetToAddress(-16,pRN->BackingStoreFp);
  94. break;
  95. }
  96. }
  97. return pEstablisher;
  98. }
  99. #if 0 // v-vadimp new version with NLG support for the debugger is in handlers.s
  100. //
  101. // Temporary version until the asm version is written that supports NLG
  102. //
  103. extern "C" void* _CallSettingFrame(
  104. void* handler,
  105. EHRegistrationNode *pEstablisher,
  106. ULONG NLG_CODE)
  107. {
  108. void* retValue = __Cxx_ExecuteHandler(
  109. pEstablisher->MemoryStackFp,
  110. pEstablisher->BackingStoreFp,
  111. (__int64)handler,
  112. _TargetGp
  113. );
  114. return retValue? (void*)(_ImageBase + (__int32)retValue) : NULL;
  115. }
  116. #endif
  117. extern "C" CONTEXT* _GetUnwindContext()
  118. {
  119. return pUnwindContext;
  120. }
  121. extern "C" unsigned __int64 _GetImageBase()
  122. {
  123. return _ImageBase;
  124. }
  125. extern "C" VOID _SetImageBase(unsigned __int64 ImageBaseToRestore)
  126. {
  127. _ImageBase = ImageBaseToRestore;
  128. }
  129. extern "C" unsigned __int64 _GetThrowImageBase()
  130. {
  131. return _ThrowImageBase;
  132. }
  133. extern "C" VOID _SetThrowImageBase(unsigned __int64 NewThrowImageBase)
  134. {
  135. _ThrowImageBase = NewThrowImageBase;
  136. }
  137. extern "C" unsigned __int64 _GetTargetGP(unsigned __int64 TargetAddress)
  138. {
  139. unsigned __int64 ImageBase;
  140. unsigned __int64 TargetGp;
  141. PRUNTIME_FUNCTION pContFunctionEntry = RtlLookupFunctionEntry(TargetAddress, &ImageBase, &TargetGp);
  142. // return _TargetGp;
  143. return TargetGp;
  144. }
  145. extern "C" VOID _MoveContext(CONTEXT* pTarget, CONTEXT* pSource)
  146. {
  147. RtlMoveMemory(pTarget, pSource, sizeof(CONTEXT));
  148. }
  149. // This function returns the try block for the given state if the state is in a
  150. // catch; otherwise, NULL is returned.
  151. static __inline TryBlockMapEntry *_CatchTryBlock(
  152. FuncInfo *pFuncInfo,
  153. __ehstate_t curState
  154. ) {
  155. TryBlockMapEntry *pEntry;
  156. unsigned num_of_try_blocks = FUNC_NTRYBLOCKS(*pFuncInfo);
  157. unsigned index;
  158. for (index = 0; index < num_of_try_blocks; index++) {
  159. pEntry = FUNC_PTRYBLOCK(*pFuncInfo, index, _ImageBase);
  160. if (curState > TBME_HIGH(*pEntry) && curState <= TBME_CATCHHIGH(*pEntry)) {
  161. return pEntry;
  162. }
  163. }
  164. return NULL;
  165. }
  166. //
  167. // This routine returns TRUE if we are executing from within a catch. Otherwise, FALSE is returned.
  168. //
  169. BOOL _ExecutionInCatch(
  170. DispatcherContext *pDC,
  171. FuncInfo *pFuncInfo
  172. ) {
  173. __ehstate_t curState = _StateFromControlPc(pFuncInfo, pDC);
  174. return _CatchTryBlock(pFuncInfo, curState)? TRUE : FALSE;
  175. }
  176. // This function unwinds to the empty state.
  177. VOID __FrameUnwindToEmptyState(
  178. EHRegistrationNode *pRN,
  179. DispatcherContext *pDC,
  180. FuncInfo *pFuncInfo
  181. ) {
  182. __ehstate_t stateFromControlPC;
  183. TryBlockMapEntry *pEntry;
  184. EHRegistrationNode EstablisherFramePointers, *pEstablisher;
  185. pEstablisher = _GetEstablisherFrame(pRN, pDC, pFuncInfo, &EstablisherFramePointers);
  186. stateFromControlPC = _StateFromControlPc(pFuncInfo, pDC);
  187. pEntry = _CatchTryBlock(pFuncInfo, stateFromControlPC);
  188. // Reuse pFrameInfoChain->State to propagate the previous catch block's final state.
  189. // This is used in case there is a nested catch inside this catch
  190. // who already dtored object's in our frame. This can happen if in our catch
  191. // there is a nested catch that throws and the catch executed is an outer catch.
  192. //
  193. //try{
  194. // try{
  195. // throw(1);
  196. // }catch(int){
  197. // B b4;
  198. // try{
  199. // throw 2;
  200. // }catch(int){
  201. // //this throw would dtor b4 by calling the outermost catch,
  202. // //and also during unwinding the first catch would try to dtor as well.
  203. // throw 3;
  204. // }
  205. // }
  206. //}catch(int){
  207. // throw 4;
  208. //}
  209. //
  210. if( pEntry && pFrameInfoChain != NULL ) {
  211. __ehstate_t curState = GetCurrentState(pEstablisher, pDC, pFuncInfo);
  212. if( pFrameInfoChain->State != -2 && pFrameInfoChain->State < curState )
  213. SetState(pEstablisher, pDC, pFuncInfo, pFrameInfoChain->State);
  214. pFrameInfoChain->State = curState;
  215. }
  216. else if( pFrameInfoChain != NULL ) {
  217. __ehstate_t curState = GetCurrentState(pEstablisher, pDC, pFuncInfo);
  218. if( pEntry == NULL && stateFromControlPC < curState ) {
  219. SetState(pEstablisher, pDC, pFuncInfo, stateFromControlPC - 1);
  220. }
  221. pFrameInfoChain->State = -2;
  222. }
  223. __FrameUnwindToState(pEstablisher, pDC,
  224. pFuncInfo, pEntry == NULL ? EH_EMPTY_STATE : TBME_HIGH(*pEntry) /*+ 1*/);
  225. }
  226. BOOL _IsExceptionObjectDestroyed(PVOID pExceptionObject,FRAMEINFO *pFrameInfo)
  227. {
  228. for (; pFrameInfo != NULL; pFrameInfo = pFrameInfo->pNext ) {
  229. if( pFrameInfo->pExceptionObjectDestroyed == pExceptionObject ) {
  230. return TRUE;
  231. }
  232. }
  233. return FALSE;
  234. }
  235. void _MarkExceptionObjectDestroyed(EHExceptionRecord *pExcept)
  236. {
  237. for (FRAMEINFO *pFrameInfo = pFrameInfoChain; pFrameInfo != NULL; pFrameInfo = pFrameInfo->pNext ) {
  238. if( pFrameInfo->pExcept == pExcept ) {
  239. pFrameInfo->pExceptionObjectDestroyed = PER_PEXCEPTOBJ(pExcept);
  240. }
  241. }
  242. }
  243. void _UnlinkFrame(FRAMEINFO *pFrameInfo)
  244. {
  245. FRAMEINFO *pPrevFrameInfo = pFrameInfoChain;
  246. if( pFrameInfoChain == pFrameInfo ) {
  247. pFrameInfoChain = pFrameInfoChain->pNext;
  248. return;
  249. }
  250. for (FRAMEINFO *pCurFrameInfo = pFrameInfoChain; pCurFrameInfo != NULL; pCurFrameInfo = pCurFrameInfo->pNext ) {
  251. if( pCurFrameInfo == pFrameInfo ) {
  252. pPrevFrameInfo->pNext = pCurFrameInfo->pNext;
  253. return;
  254. }
  255. pPrevFrameInfo = pCurFrameInfo;
  256. }
  257. }
  258. // Find the frame info structure corresponding to the given address. Return
  259. // NULL if the frame info structure does not exist.
  260. FRAMEINFO *_FindFrameInfo(
  261. PVOID pContinuation,
  262. FRAMEINFO *pFrameInfo
  263. ) {
  264. unsigned __int64 ImageBase;
  265. unsigned __int64 TargetGp;
  266. PRUNTIME_FUNCTION pContFunctionEntry = RtlLookupFunctionEntry((unsigned __int64)pContinuation, &ImageBase, &TargetGp);
  267. PRUNTIME_FUNCTION pFrameFunctionEntry = pFrameInfo->pFunctionEntry;
  268. DASSERT(pFrameInfo != NULL);
  269. for (; pFrameInfo != NULL; pFrameInfo = pFrameInfo->pNext ) {
  270. if (pContFunctionEntry == pFrameInfo->pFunctionEntry &&
  271. (pContinuation > OffsetToAddress(pFrameInfo->pFunctionEntry->BeginAddress,ImageBase)) &&
  272. (pContinuation <= OffsetToAddress(pFrameInfo->pFunctionEntry->EndAddress,ImageBase))
  273. ){
  274. return pFrameInfo;
  275. }
  276. }
  277. return NULL;
  278. }
  279. BOOL __IsFramePdataMatch(
  280. PVOID pContinuation,
  281. RUNTIME_FUNCTION* pFrameRfe)
  282. {
  283. BOOL fRetVal = FALSE;
  284. unsigned __int64 ImageBase, TargetGp;
  285. PRUNTIME_FUNCTION pContRfe = RtlLookupFunctionEntry((unsigned __int64) pContinuation, &ImageBase, &TargetGp);
  286. FuncInfo* pContFuncInfo = (FuncInfo*)(ImageBase + *(PULONG)GetLanguageSpecificData(pContRfe, ImageBase));
  287. FuncInfo* pFrameFuncInfo = (FuncInfo*)(ImageBase + *(PULONG)GetLanguageSpecificData(pFrameRfe, ImageBase));
  288. //
  289. // first see if there is a regular match, i.e. if the RFE registered with the frame
  290. // matches the RFE for the continuation address
  291. //
  292. fRetVal = (pContRfe == pFrameRfe) &&
  293. (pContinuation > OffsetToAddress(pFrameRfe->BeginAddress,ImageBase)) &&
  294. (pContinuation <= OffsetToAddress(pFrameRfe->EndAddress,ImageBase));
  295. if (!fRetVal && (pContFuncInfo->bbtFlags == BBT_UNIQUE_FUNCINFO)) {
  296. fRetVal = (pContFuncInfo == pFrameFuncInfo);
  297. }
  298. return fRetVal;
  299. }
  300. //
  301. // Given the address of a continuation point, return the corresponding context.
  302. // Each frame info was saved just before a catch handler was called.
  303. // The most recently encountered frame is at the head of the chain.
  304. // The routine starts out with the frame given as the second argument, and scans the
  305. // linked list for the frame that corresponds to the continuation point.
  306. //
  307. CONTEXT* _FindAndUnlinkFrame(PVOID pContinuation, FRAMEINFO *pFrameInfo)
  308. {
  309. DASSERT(pFrameInfo != NULL);
  310. for( ; pFrameInfo != NULL; pFrameInfo = pFrameInfo->pNext ) {
  311. if(__IsFramePdataMatch(pContinuation, pFrameInfo->pFunctionEntry)) {
  312. //
  313. // We found the frame.
  314. // All frames preceeding and including this one are gone. so unlink them.
  315. //
  316. CONTEXT* pExitContext = pFrameInfo->pExitContext;
  317. pFrameInfoChain = pFrameInfo->pNext;
  318. //
  319. // If there are no more exceptions are pending get rid of unneeded frame info records.
  320. //
  321. if( _pCurrentException == NULL ) {
  322. while( pFrameInfoChain != NULL && pFrameInfoChain->pExceptionObjectDestroyed ) {
  323. pFrameInfoChain = pFrameInfoChain->pNext;
  324. }
  325. }
  326. return pExitContext;
  327. }
  328. }
  329. DASSERT(pFrameInfo != NULL);
  330. return NULL;
  331. }
  332. //
  333. // Save the frame information for this scope. Put it at the head of the linked-list.
  334. //
  335. FRAMEINFO* _CreateFrameInfo(
  336. FRAMEINFO *pFrameInfo,
  337. DispatcherContext *pDC,
  338. CONTEXT *pExitContext,
  339. __ehstate_t State,
  340. PVOID pExceptionObjectDestroyed,
  341. EHExceptionRecord *pExcept
  342. ) {
  343. pFrameInfo->pFunctionEntry = pDC->FunctionEntry;
  344. pFrameInfo->pExitContext = pExitContext;
  345. pFrameInfo->pExceptionObjectDestroyed = pExceptionObjectDestroyed;
  346. pFrameInfo->pExceptionObjectToBeDestroyed = NULL;
  347. pFrameInfo->pExcept = pExcept;
  348. pFrameInfo->State = State;
  349. pFrameInfo->dtorThrowFlag = FALSE;
  350. pFrameInfo->isRethrow = FALSE;
  351. if( pFrameInfoChain != NULL && pFrameInfoChain->dtorThrowFlag ) {
  352. pFrameInfoChain->dtorThrowFlag = FALSE;
  353. pFrameInfoChain = pFrameInfoChain->pNext;
  354. }
  355. pFrameInfo->pNext = (pFrameInfo < pFrameInfoChain)? pFrameInfoChain : NULL;
  356. pFrameInfoChain = pFrameInfo;
  357. return pFrameInfo;
  358. }
  359. //
  360. // THIS ROUTINE IS USED ONLY TO JUMP TO THE CONTINUATION POINT
  361. //
  362. // Sets SP and jumps to specified code address.
  363. // Does not return.
  364. //
  365. void _JumpToContinuation(
  366. unsigned __int64 TargetAddress, // The target address to call
  367. CONTEXT *pContext, // Context of target function
  368. EHExceptionRecord *pExcept
  369. ) {
  370. unsigned __int64 ImageBase;
  371. unsigned __int64 TargetGp;
  372. PRUNTIME_FUNCTION pFunctionEntry = RtlLookupFunctionEntry(TargetAddress, &ImageBase, &TargetGp);
  373. pContext->StIIP = TargetAddress;
  374. pContext->IntGp = TargetGp;
  375. pContext->StIPSR &= ~IPSR_RI_MASK;
  376. RtlRestoreContext(pContext,(PEXCEPTION_RECORD)pExcept);
  377. }
  378. //
  379. // Prototype for the internal handler
  380. //
  381. extern "C" EXCEPTION_DISPOSITION __InternalCxxFrameHandler(
  382. EHExceptionRecord *pExcept, // Information for this exception
  383. EHRegistrationNode *pRN, // Dynamic information for this frame
  384. CONTEXT *pContext, // Context info
  385. DispatcherContext *pDC, // More dynamic info for this frame
  386. FuncInfo *pFuncInfo, // Static information for this frame
  387. int CatchDepth, // How deeply nested are we?
  388. EHRegistrationNode *pMarkerRN, // Marker node for when checking inside catch block
  389. BOOL recursive); // True if this is a translation exception
  390. //
  391. // __CxxFrameHandler - Real entry point to the runtime
  392. //
  393. extern "C" _CRTIMP EXCEPTION_DISPOSITION __CxxFrameHandler(
  394. EHExceptionRecord *pExcept, // Information for this exception
  395. __int64 MemoryStackFp, // SP of user program
  396. __int64 BackingStoreFp, // BSP of user program
  397. CONTEXT *pContext, // Context info
  398. DispatcherContext *pDC, // More dynamic info for this frame
  399. __int64 TargetGp // GP of user program
  400. ) {
  401. FuncInfo *pFuncInfo;
  402. EXCEPTION_DISPOSITION result;
  403. EHRegistrationNode EstablisherFrame = { MemoryStackFp, BackingStoreFp };
  404. _ImageBase = pDC->ImageBase;
  405. _TargetGp = TargetGp;
  406. _ThrowImageBase = (unsigned __int64)pExcept->params.pThrowImageBase;
  407. pFuncInfo = (FuncInfo*)(_ImageBase + *(PULONG)GetLanguageSpecificData(pDC->FunctionEntry, _ImageBase));
  408. result = __InternalCxxFrameHandler( pExcept, &EstablisherFrame, pContext, pDC, pFuncInfo, 0, NULL, FALSE );
  409. return result;
  410. }
  411. // Call the SEH to EH translator.
  412. BOOL _CallSETranslator(
  413. EHExceptionRecord *pExcept, // The exception to be translated
  414. EHRegistrationNode *pRN, // Dynamic info of function with catch
  415. CONTEXT *pContext, // Context info
  416. DispatcherContext *pDC, // More dynamic info of function with catch (ignored)
  417. FuncInfo *pFuncInfo, // Static info of function with catch
  418. ULONG CatchDepth, // How deeply nested in catch blocks are we?
  419. EHRegistrationNode *pMarkerRN // Marker for parent context
  420. ) {
  421. pRN;
  422. pDC;
  423. pFuncInfo;
  424. CatchDepth;
  425. // Call the translator.
  426. _EXCEPTION_POINTERS excptr = { (PEXCEPTION_RECORD)pExcept, pContext };
  427. __pSETranslator(PER_CODE(pExcept), &excptr);
  428. // If we got back, then we were unable to translate it.
  429. return FALSE;
  430. }
  431. //
  432. // This structure is the FuncInfo (HandlerData) for handler __TranslatorGuardHandler
  433. //
  434. struct TransGuardRec {
  435. FuncInfo *pFuncInfo; // Static info for subject function
  436. EHRegistrationNode *pFrame; // Dynamic info for subject function
  437. ULONG CatchDepth; // How deeply nested are we?
  438. EHRegistrationNode *pMarkerFrame; // Marker for parent context
  439. PVOID pContinue; // Continuation address within CallSEHTranslator
  440. PVOID pSP; // SP within CallSEHTranslator
  441. BOOL DidUnwind; // True if this frame was unwound
  442. };
  443. #if 0
  444. //
  445. // This routine is the handler for CallSETranslator which is defined in handlers.s
  446. //
  447. extern "C" _CRTIMP EXCEPTION_DISPOSITION __TranslatorGuardHandler(
  448. EHExceptionRecord *pExcept, // Information for this exception
  449. EHRegistrationNode *pFrame, // The translator guard frame
  450. CONTEXT *pContext, // Context info
  451. DispatcherContext *pDC // Dynamic info for this frame
  452. ) {
  453. //
  454. // The handler data is a pointer to an integer that is an offset to the TGRN structure
  455. // relative to the frame pointer.
  456. //
  457. TransGuardRec *pTransGuardData = (TransGuardRec*)((char*)pFrame->MemoryStackFp - *(int*)(pDC->FunctionEntry->HandlerData));
  458. if (IS_UNWINDING(PER_FLAGS(pExcept)))
  459. {
  460. pTransGuardData->DidUnwind = TRUE;
  461. return ExceptionContinueSearch;
  462. }
  463. else {
  464. //
  465. // Check for a handler:
  466. //
  467. __InternalCxxFrameHandler( pExcept,
  468. pTransGuardData->pFrame,
  469. pContext,
  470. pDC,
  471. pTransGuardData->pFuncInfo,
  472. pTransGuardData->CatchDepth,
  473. pTransGuardData->pMarkerFrame,
  474. TRUE );
  475. // Unreached.
  476. return ExceptionContinueSearch;
  477. }
  478. }
  479. #endif
  480. /////////////////////////////////////////////////////////////////////////////
  481. //
  482. // _GetRangeOfTrysToCheck - determine which try blocks are of interest, given
  483. // the current catch block nesting depth. We only check the trys at a single
  484. // depth.
  485. //
  486. // Returns:
  487. // Address of first try block of interest is returned
  488. // pStart and pEnd get the indices of the range in question
  489. //
  490. TryBlockMapEntry* _GetRangeOfTrysToCheck(
  491. EHRegistrationNode *pRN,
  492. FuncInfo *pFuncInfo,
  493. int CatchDepth,
  494. __ehstate_t curState,
  495. unsigned *pStart,
  496. unsigned *pEnd,
  497. DispatcherContext *pDC
  498. ) {
  499. TryBlockMapEntry *pEntry;
  500. unsigned num_of_try_blocks = FUNC_NTRYBLOCKS(*pFuncInfo);
  501. DASSERT( num_of_try_blocks > 0 );
  502. for( unsigned int index = 0; index < num_of_try_blocks; index++ ) {
  503. pEntry = FUNC_PTRYBLOCK(*pFuncInfo, index, pDC->ImageBase);
  504. if( curState >= TBME_LOW(*pEntry) && curState <= TBME_HIGH(*pEntry) ) {
  505. *pStart = index;
  506. *pEnd = FUNC_NTRYBLOCKS(*pFuncInfo);
  507. DASSERT( *pEnd <= num_of_try_blocks && *pStart < *pEnd );
  508. #if 1
  509. int SavedState = GetUnwindTryBlock(pRN, pDC, pFuncInfo);
  510. if( SavedState != -1 && SavedState >= curState )
  511. continue;
  512. #else
  513. int SavedTryNdx = GetUnwindTryBlock(pRN, pDC, pFuncInfo);
  514. if( SavedTryNdx != -1 ) {
  515. *pStart = SavedTryNdx + 1;
  516. if( *pStart < *pEnd && pEntry != NULL ) {
  517. pEntry = FUNC_PTRYBLOCK(*pFuncInfo, SavedTryNdx + 1, pDC->ImageBase);
  518. }
  519. }
  520. #endif
  521. return pEntry;
  522. }
  523. }
  524. *pStart = *pEnd = 0;
  525. return NULL;
  526. }
  527. #pragma optimize("",off)
  528. extern "C" unsigned __int64 __getReg(int);
  529. extern "C" void __setReg(int, unsigned __int64);
  530. #pragma intrinsic(__getReg)
  531. #pragma intrinsic(__setReg)
  532. extern "C" void _UnwindNestedFrames(
  533. EHRegistrationNode *pFrame, // Unwind up to (but not including) this frame
  534. EHExceptionRecord *pExcept, // The exception that initiated this unwind
  535. CONTEXT *pContext // Context info for current exception
  536. ) {
  537. CONTEXT LocalContext; // Create context for this routine to return from RtlUnwind
  538. CONTEXT ScratchContext; // Context record to pass to RtlUnwind2 to be used as scratch
  539. volatile int Unwound = FALSE; // Flag that assist to return from RtlUnwind2
  540. PVOID pReturnPoint = NULL; // The address we want to return from RtlUnwind2
  541. RtlCaptureContext(&LocalContext);
  542. //
  543. // set up the return label
  544. //
  545. _GetNextInstrOffset(&pReturnPoint);
  546. if(Unwound)
  547. goto LAB_UNWOUND;
  548. LocalContext.StIIP = (ULONGLONG)pReturnPoint;
  549. LocalContext.IntGp = __getReg(CV_IA64_IntR1);
  550. LocalContext.StIPSR &= ~IPSR_RI_MASK;
  551. pUnwindContext = &LocalContext; // save address of LocalContext in global/TLS pUnwindContext
  552. Unwound = TRUE;
  553. #ifdef _NT
  554. RtlUnwind2(*pFrame, (ULONG_PTR)pReturnPoint, (PEXCEPTION_RECORD)pExcept, NULL, &ScratchContext);
  555. #else
  556. RtlUnwind2(*pFrame, pReturnPoint, (PEXCEPTION_RECORD)pExcept, NULL, &ScratchContext);
  557. #endif
  558. LAB_UNWOUND:
  559. __setReg(CV_IA64_IntR1,LocalContext.IntGp);
  560. pContext->StIPSR &= ~IPSR_RI_MASK;
  561. PER_FLAGS(pExcept) &= ~EXCEPTION_UNWINDING;
  562. //
  563. // reset global/TLS pUnwindContext for future exceptions
  564. //
  565. pUnwindContext = NULL;
  566. }