⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 frame.cpp

📁 不错的东西 请查看 WINCE OS
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//  This function is invoked to determine that exception object can be destroyed
//  or not:
//  
//  return TRUE means that the object can be destructed; FALSE otherwise.
// 
//  Note:
//  The object we are trying to delete is from the throw line, constructed by
//  copy constructor. 
//  Example: throw a0; the copy of a0 is the exception object that
//  we are talking about here.
//  
// _pCurrentException is actually the previous exception besides pExcept
// 
static BOOLEAN CanThisExceptionObjectBeDestructed(EHExceptionRecord *pExcept, 
                                                  BOOLEAN abnormalTermination)
{
    BOOLEAN ret = FALSE;

    DEBUGMSG(DBGEH,(TEXT("Checking: pExcept(%08x), obj(%08x), abnormalTermination(%d)\r\n"), 
                    pExcept, PER_PEXCEPTOBJ(pExcept), abnormalTermination));
    DEBUGMSG(DBGEH,(TEXT("Checking:          _pCurrExceptRethrow(%08x), _pCurrentException(%08x)\r\n"), 
                    _pCurrExceptRethrow, _pCurrentException));

    if ( abnormalTermination ) 
    {
        // as long as pExcept is not the same as _pCurrExceptRethrow
        if ( pExcept!=_pCurrExceptRethrow )
        {
            ret = TRUE;
        }
    }
    else
    {
        // Important point:
        // Just because we found normal exit from a catch does not imply that we can destroy
        // the source of the local exception object (original exception object). This is
        // because a catch may be nested inside another. After exiting a nested catch, we
        // may find a rethrow of the original exception object. For this reason, we can only
        // destroy the original exception object once we have left the scope of the catch which
        // caught it.
        //
        // For normal termination we destroy pExcept if any of the following are true:
        // 1) No pCurrExceptRethrow at all.
        // 2) pExcept is the same of pCurrExceptRethrow, and pExcept itself 
        //    is not a rethrow of _pCurrentException.
        // 3) Exception is rethrow and _pCurrExceptRethrow is not the previous recorded exception
        //    because another rethrow might be thrown.
        if ( !_pCurrExceptRethrow || 
             ( pExcept==_pCurrExceptRethrow && 
               !IS_RETHROW(pExcept, _pCurrentException) ) || 
             ( IS_RETHROW((EHExceptionRecord *)_pCurrExceptRethrow, pExcept) &&
              _pCurrExceptRethrow!=_pCurrentException ) )
        {
            ret = TRUE;
        }
    }

    DEBUGMSG(DBGEH,(TEXT("Checking: EXIT ret:%08x\r\n"), 
                    ret));

    return ret;
}


////////////////////////////////////////////////////////////////////////////////
//
//  CallCatchBlock
//
//  This function is called after the shx\target frame has been unwound (all unwind
//  actions have been performed. The catch block is now invoked.
//
//

static void *CallCatchBlock(
    EHExceptionRecord  *pExcept,        // The exception thrown
    EHRegistrationNode *pRN,            // Dynamic info of function with catch
    CONTEXT            *pContext,       // Context info
    FuncInfo           *pFuncInfo,      // Static info of function with catch
    void               *handlerAddress, // Code address of handler
    int                 CatchDepth,     // How deeply nested in catch blocks
    unsigned long       NLGCode         // NLG destination code
    ) 
{
    // Address where execution resumes after exception handling completed.
    // Initialized to non-NULL (value doesn't matter) to distinguish from
    // re-throw in __finally.
    void *continuationAddress = handlerAddress;

#if !defined(_X86_)
    FRAMEINFO NewFrame;
#if defined(_M_ARM)
    CATCHFRAMEINFO NewCatchFrame;
#endif // _M_ARM
#endif // !defined(_X86_)

    DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: ENTER, to invoke handler @%08x  pRN=%08x\r\n"), 
                    handlerAddress, pRN));


    // Save the current exception in case of a rethrow.  Save the previous value
    // on the stack, to be restored when the catch exits.
    EHExceptionRecord *pSaveException ;
    CONTEXT *pSaveExContext ;
    // Save the current rethrow exception. This is because rethrows can be nested. To be
    // restored when the catch exits.
    EHExceptionRecord *pSaveRethrowException ;

    DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: save _pCurrentException=%08x _pCurrentExContext=%08x\r\n"), 
                    _pCurrentException, _pCurrentExContext));

    pSaveException = _pCurrentException;
    pSaveExContext = _pCurrentExContext;

    pSaveRethrowException = (EHExceptionRecord *)_pCurrExceptRethrow;
   
    _pCurrentException = pExcept;
    _pCurrentExContext = pContext;

    DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: put pExcept=%08x into _pCurrentException\r\n"), 
                    pExcept));
    DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: put pContext=%08x into _pCurrentExContext\r\n"), 
                    pContext));

    __try {

#if defined(_X86_)
        // The current stack pointer is stored just ahead of the
        // registration node.  We need to add it to the context
        // structure (for the continuation) before calling the catch
        // block because it will be changed in the catch block if
        // there's a nested try/catch block.
        pContext->Esp = *((unsigned long*)pRN - 1);
        continuationAddress = _CallCatchBlock2(pRN, pFuncInfo, handlerAddress,
                                               CatchDepth, 0);

        // Get frame pointer by looking past the exception
        // registration node on the stack per __CallSettingFrame
        pContext->Ebp = (unsigned long) pRN + sizeof(EHRegistrationNode);
#else
        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: Fill NewFrame fields all but pCatchRN...\r\n")));
        // this will be set in CallSetttingFrame
        NewFrame.pCatchRN = NULL;
        NewFrame.pRN = pRN;
        NewFrame.state = (FUNC_UNWIND(*pFuncInfo,
                                      TBME_LOW(*TargetEntry))).toState;
        NewFrame.NestLevel = HT_FRAMENEST(TBME_CATCH(*TargetEntry, 0));
        NewFrame.next = pFrameInfoChain;

        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: NewFrame=%08x pRN=%08x state=%d NestLevel=%d next=%08x\r\n"),
                        &NewFrame, NewFrame.pRN, NewFrame.state, NewFrame.NestLevel, NewFrame.next));

        pFrameInfoChain = &NewFrame;

        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: insert NewFrame=%08x into pFrameInfoChain\r\n"), 
                        &NewFrame));

#if defined(_M_ARM)
        NewCatchFrame.pRN=pRN;
        NewCatchFrame.NestLevel = HT_FRAMENEST(TBME_CATCH(*TargetEntry, 0));
        NewCatchFrame.pFuncInfo = pFuncInfo ;
        NewCatchFrame.next = pCatchChain;
        pCatchChain = &NewCatchFrame;
        pRN=FindCatchFrame (pRN, HT_FRAMENEST(TBME_CATCH(*TargetEntry, 0)));
#endif // _M_ARM

        continuationAddress = _CallSettingFrame(handlerAddress, pRN,
                                                pContext, &NewFrame );

        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: from _CallSettingFrame: pCatchRN=%08x\r\n"), 
                        NewFrame.pCatchRN));

#endif // _X86_

        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: from _CallSettingFrame continuationAddress %08x\r\n"), 
                        continuationAddress));

    } __finally {

        // DEBUGCHK(pExcept==_pCurrentException);

        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: Restore the _pCurrentException\r\n")));
        
        _pCurrentException = pSaveException;
        _pCurrentExContext = pSaveExContext;

        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: _pCurrentException=%08x _pCurrentExContext=%08x\r\n"),
                        _pCurrentException, _pCurrentExContext));

        // Destroy the original exception object if we're not exiting on a
        // re-throw.  Note that the catch handles destruction of its parameter.

        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: pExcept(0x%08x), PER_PTHROW(pExcept):%08x, PER_PEXCEPTOBJ(pExcept):%08x _pCurrentException=%08x\r\n"),
                        pExcept, PER_PTHROW(pExcept), PER_PEXCEPTOBJ(pExcept), _pCurrentException));

#if !defined(_X86_)

        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: abnormal_termination(%d) _pCurrExceptRethrow(0x%08x)\r\n"),
                        abnormal_termination(), _pCurrExceptRethrow));
#endif // !defined(_X86_)

        if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) != NULL
            && CanThisExceptionObjectBeDestructed(pExcept, abnormal_termination()))
        {
            DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: calling DestructExceptionObject pExcept=%08x, obj(%08x)\r\n"),
                            pExcept, PER_PEXCEPTOBJ(pExcept)));
            _DestructExceptionObject(pExcept, abnormal_termination());
        }

        _pCurrExceptRethrow = pSaveRethrowException;

#if !defined(_X86_)
        //
        //  If the catch block raised an exception, save the pRN and state
        //  for unwinding through the associated try block. The lifetime of
        //  these values is from here until the next call to FrameUnwindToState
        //
        if (abnormal_termination()) {
            DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: abnormal_termination. Catch Block Raised an exception ")));
            CatchExceptRN = NewFrame.pRN;
            CatchExceptState = NewFrame.state;
            DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: save CatchExceptRN=%08x CatchExceptState=%d from NewFrame\r\n"), 
                            CatchExceptRN, CatchExceptState));
        }

#if defined(_M_ARM)
        //
        // Remove current catch frame from list
        //
        CATCHFRAMEINFO *lcurFrame = pCatchChain;
        CATCHFRAMEINFO **lnextFrame = &pCatchChain;
        while ( lcurFrame != NULL ){
            if (lcurFrame == &NewCatchFrame ) {

                *lnextFrame = lcurFrame->next;
                DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: Removing %08x: pCatchChain=%08x\r\n"),
                                lcurFrame, pCatchChain));
            }
            lnextFrame = &lcurFrame->next;
            lcurFrame = lcurFrame->next;
        }
#endif // _M_ARM
#endif // !defined(_X86_)

    } // finally

#ifndef _M_IX86 

    // to update pFrameInfoChain here.
    // we remove not only NewFrame when normal_termination occurs, but also residing FrameInfo
    // which had been created by previous CallCatchBlock while abnormal_termination happened.
    // If the state of pFrameInfo on the pFrameInfoChain is bigger than NewFrame's state,
    // we are sure that pFrameInfo is enclosed by NewFrame's state, given that try/catch
    // can not be overlapped.
    {
        FRAMEINFO *prevFrame = NULL;
        FRAMEINFO *curFrame = pFrameInfoChain;

        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: normal_termination. update pFrameChainInfo ")));
        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: remove NewFrame(%08x) from pFrameInfoChain(%08x)\r\n"),
                        &NewFrame, pFrameInfoChain));

        // iterate the pFrameInfoChain to look for NewFrame to remove

        // Assumption: stack grows while memory decreases.

        while ( curFrame != NULL ) {

            if ( curFrame->pRN <= NewFrame.pRN ) {
                // curFrame's establisher frame was established after NewFrame's.
                // curFrame can be safely removed from the chain.

                DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: Removing curFrame=%08x from pFrameInfoChain=%08x\r\n"),
                                curFrame, pFrameInfoChain));

                if ( curFrame == pFrameInfoChain ) {
                    pFrameInfoChain = curFrame->next;
                } else {
                    prevFrame->next = curFrame->next;
                }

                DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: curFrame: pRN=%08x CatchRN=%08x state=%d NestLevel=%d\r\n"), 
                                curFrame->pRN, curFrame->pCatchRN,
                                curFrame->state, curFrame->NestLevel));

            }
            prevFrame = curFrame;
            curFrame = curFrame->next;
        }
        DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: After removal NewFrame(%08x), pFrameInfoChain(%08x)\r\n"),
                        &NewFrame, pFrameInfoChain));
    }
#endif // _M_IX86 

    DEBUGMSG(DBGEH,(TEXT("CallCatchBlock: EXIT pExcept(%08x) with continuationAddress=%08x\r\n"),
                    pExcept, continuationAddress));
         
    return continuationAddress;

} // CallCatchBlock


////////////////////////////////////////////////////////////////////////////////
//
// BuildCatchObject - Copy or construct the catch object from the object thrown.
//
// Returns:
//     nothing.
//
// Side-effects:
//     A buffer in the subject function's frame is initialized.
//
// Open issues:
//     What happens if the constructor throws?  (or faults?)

static void BuildCatchObject(
    EHExceptionRecord  *pExcept,     // Original exception thrown
    EHRegistrationNode *pRN,         // Registration node of catching function
    HandlerType        *pCatch,      // The catch clause that got it
    CatchableType      *pConv        // The conversion to use
    ) 
{
    // If the catch is by ellipsis, then there is no object to construct.
    // If the catch is by type(No Catch Object), then leave too!
    if (HT_IS_TYPE_ELLIPSIS(*pCatch) || !HT_DISPCATCH(*pCatch)) {
        return;
    }

    void **pCatchBuffer = (void **)__OffsetToAddress(HT_DISPCATCH(*pCatch), pRN,
                                                     HT_FRAMENEST(*pCatch));
#ifndef _M_IX86 
    DEBUGMSG(DBGEH,(TEXT("BuildCatchObject pRN=%08x Level=%d\r\n"),pRN,
                    HT_FRAMENEST(*pCatch)));
#endif // _M_IX86

    __try {
        if (HT_ISREFERENCE(*pCatch)) {

            // The catch is of form 'reference to T'.  At the throw point we
            // treat both 'T' and 'reference to T' the same, i.e.
            // pExceptionObject is a (machine) pointer to T.  Adjust as
            // required.

            DEBUGMSG(DBGEH,(TEXT("Object thrown is HT_ISREFERENCE\r\n")));

            *pCatchBuffer = PER_PEXCEPTOBJ(pExcept);
            *pCatchBuffer = AdjustPointer(*pCatchBuffer, CT_THISDISP(*pConv));

        } else if (CT_ISSIMPLETYPE(*pConv)) {

            // Object thrown is of simple type (this including pointers) copy

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -