📄 frame.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/***
*frame.cpp - The frame handler and everything associated with it.
*
*
*Purpose:
* The frame handler and everything associated with it.
*
* Entry points:
* _CxxFrameHandler - the frame handler.
*
****/
#include "kernel.h"
#include "excpt.h"
#include "corecrtstorage.h"
#include "corecrt.h"
#include <mtdll.h> // CRT internal header file
#include <ehdata.h> // Declarations of all types used for EH
#include <trnsctrl.h> // Routines to handle transfer of control
#include <ehstate.h> // Declarations of state management stuff
#include <exception> // User-visible routines for eh
#include <ehhooks.h> // Declarations of hook variables and callbacks
#include <ehglobs.h> // EH global variables
#include <coredll.h> // Define debug zone information
#pragma hdrstop // PCH is created from here
// define CC_OUTERTRY for all platforms that use smd directory
#define CC_OUTERTRY
#if defined(_X86_)
#define __OffsetToAddress(a, b, c) OffsetToAddress(a, b)
#define DC_CONTEXTRECORD(pDC) (NULL)
#else
#define __OffsetToAddress(a, b, c) _OffsetToAddress(a, b, c)
#define DC_CONTEXTRECORD(pDC) (pDC->ContextRecord)
#endif
////////////////////////////////////////////////////////////////////////////////
//
// Forward declaration of local functions:
//
// M00TODO: all these parameters should be declared const
extern "C" void __FrameUnwindToState(
EHRegistrationNode *,
PDISPATCHER_CONTEXT,
FuncInfo *,
__ehstate_t
);
static BOOLEAN FindHandler(
EHExceptionRecord *,
EHRegistrationNode *,
CONTEXT *,
PDISPATCHER_CONTEXT,
FuncInfo *,
int
);
static void * CallCatchBlock(
EHExceptionRecord *,
EHRegistrationNode *,
CONTEXT *,
FuncInfo *,
void *,
int,
unsigned long
);
static void BuildCatchObject(
EHExceptionRecord *,
EHRegistrationNode *,
HandlerType *,
CatchableType *
);
static __inline int TypeMatch(
HandlerType *,
CatchableType *,
ThrowInfo *
);
static void * AdjustPointer(
void *,
const PMD&
);
static int FrameUnwindFilter(
EXCEPTION_POINTERS *
);
static BOOLEAN CanThisExceptionObjectBeDestructed(
EHExceptionRecord *pExcept,
BOOLEAN abnormalTermination
);
////////////////////////////////////////////////////////////////////////////////
//
// __InternalCxxFrameHandler - the frame handler for all functions with C++ EH
// information.
//
// If exception is handled, this doesn't return; otherwise, it returns
// ExceptionContinueSearch.
//
//
extern "C" EXCEPTION_DISPOSITION __cdecl __InternalCxxFrameHandler(
EHExceptionRecord *pExcept, // Information for this exception
EHRegistrationNode *pRN, // Dynamic information for this frame
CONTEXT *pContext, // Context info
PDISPATCHER_CONTEXT pDC, // Context within subject frame
FuncInfo *pFuncInfo, // Static information for this frame
int CatchDepth // How deeply nested are we?
)
{
DEBUGMSG(DBGEH,(TEXT("__InternalCxxFrameHandler: ENTER\r\n")));
DEBUGCHK(FUNC_MAGICNUM(*pFuncInfo) == EH_MAGIC_NUMBER1);
DEBUGMSG(DBGEH,(TEXT("__InternalCxxFrameHandler: pExcept=%08x pFuncInfo=%08x pRN=%08x CatchDepth=%d\r\n"),
pExcept, pFuncInfo, pRN, CatchDepth));
DEBUGMSG(DBGEH,(TEXT("__InternalCxxFrameHandler: ExceptionCode=%08x ExceptionFlags=%08x\r\n"),
pExcept->ExceptionCode, pExcept->ExceptionFlags));
DEBUGMSG(DBGEH,(TEXT("__InternalCxxFrameHandler: pDC->ControlPc=%08x\r\n"),
pDC->ControlPc));
DEBUGMSG(DBGEH,(TEXT("__InternalCxxFrameHandler: pExceptionObject=%08x pThrowInfo= %08x\r\n"),
PER_PEXCEPTOBJ(pExcept), PER_PTHROW(pExcept)));
if (IS_UNWINDING(PER_FLAGS(pExcept)))
{
// We're at the unwinding stage of things. Don't care about the
// exception itself.
DEBUGMSG(DBGEH,(TEXT("__InternalCxxFrameHandler: unwinding ...\r\n")));
if ( IS_TARGET_UNWIND(PER_FLAGS(pExcept) )){
DEBUGMSG(DBGEH,(TEXT("__InternalCxxFrameHandler: IS_TARGET_UNWIND\r\n")));
__ehstate_t targetState = TBME_LOW(*TargetEntry);
DEBUGMSG(DBGEH,(TEXT("__InternalCxxFrameHandler: targetState=%d from TargetEntry=%08x\r\n"),
targetState, TargetEntry));
__FrameUnwindToState(pRN, pDC, pFuncInfo, targetState);
#if defined(_X86_)
SetState(pRN, TBME_HIGH(*TargetEntry)+1);
#endif // _X86_
DEBUGMSG(DBGEH,(TEXT("__InternalCxxFrameHandler: after unwind, call CallCatchBlock\r\n")));
void * continuationAddress
= CallCatchBlock(pExcept,
pRN,
pContext,
pFuncInfo,
(void *)CONTEXT_TO_PROGRAM_COUNTER(pContext),
CatchDepth, 0x100);
DEBUGMSG(DBGEH,(TEXT("from CallCatchBlock: continuationAddress %08x\r\n"),
continuationAddress));
CONTEXT_TO_PROGRAM_COUNTER(pContext) = (ULONG)continuationAddress;
} else if (
#ifdef _X86_
FUNC_MAXSTATE(*pFuncInfo) != 0 && CatchDepth == 0
#else
FUNC_MAXSTATE(*pFuncInfo) != 0
#endif // _X86_
) {
// Only unwind if there's something to unwind
DEBUGMSG(DBGEH,(TEXT("InternalCxxFrameHandler: Unwind to empty state\n")));
__FrameUnwindToState(pRN, pDC, pFuncInfo, EH_EMPTY_STATE);
}
} else if (FUNC_NTRYBLOCKS(*pFuncInfo) != 0) {
//
// If try blocks are present, search for a handler:
//
DEBUGMSG(DBGEH,(TEXT("InternalCxxFrameHandler: NTRYBLOCKS=%d\r\n"),
FUNC_NTRYBLOCKS(*pFuncInfo)));
DEBUGMSG(DBGEH,(TEXT("InternalCxxFrameHandler: call FindHandler\r\n")));
if ( FindHandler(pExcept, pRN, pContext, pDC, pFuncInfo, CatchDepth) ) {
DEBUGMSG(DBGEH,(TEXT("InternalCxxFrameHandler: EXIT with pExcept(%08x): Handler Found %08x\n"),
pExcept, pDC->ControlPc));
return ExceptionExecuteHandler;
}
// If it returned FALSE, we didn't have any matches.
DEBUGMSG(DBGEH,(TEXT("InternalCxxFrameHandler: No Handler Found\r\n")));
}
// We had nothing to do with it or it was rethrown. Keep searching.
DEBUGMSG(DBGEH,(TEXT("InternalCxxFrameHandler EXIT with pExcept(%08x): ExceptionContinueSearch\r\n"), pExcept));
return ExceptionContinueSearch;
} // InternalCxxFrameHandler
#ifndef _X86_
//
// __CxxFrameHandler - Real entry point to the runtime
//
extern "C" _CRTIMP EXCEPTION_DISPOSITION __CxxFrameHandler(
EHExceptionRecord *pExcept, // Information for this exception
EHRegistrationNode *pRN, // Dynamic information for this frame
CONTEXT *pContext, // Context info
PDISPATCHER_CONTEXT pDC // More dynamic info for this frame
)
{
FuncInfo *pFuncInfo;
EXCEPTION_DISPOSITION result;
pFuncInfo = (FuncInfo*)pDC->FunctionEntry->HandlerData;
result = __InternalCxxFrameHandler(pExcept, pRN, pContext, pDC, pFuncInfo, 0);
return result;
} // __CxxFrameHandler
#endif // ifndef _X86_
////////////////////////////////////////////////////////////////////////////////
//
// FindHandler - find a matching handler on this frame, using all means
// available.
//
// Description:
// If the exception thrown was an MSC++ EH, search handlers for match.
// Otherwise, if we haven't already recursed, try to translate.
// If we have recursed (ie we're handling the translator's exception), and
// it isn't a typed exception, call _inconsistency.
//
// Returns:
// Returns TRUE if a handler was found
//
// Assumptions:
// Only called if there are handlers in this function.
static BOOLEAN FindHandler(
EHExceptionRecord *pExcept, // Information for this (logical) exception
EHRegistrationNode *pRN, // Dynamic information for subject frame
CONTEXT *pContext, // Context info
PDISPATCHER_CONTEXT pDC, // Context within subject frame
FuncInfo *pFuncInfo, // Static information for subject frame
int CatchDepth // Level of nested catch that is being checked
)
{
BOOLEAN Found = FALSE;
EHExceptionRecord *pNewExcept = pExcept ;
EHExceptionRecord *pRethrowException = NULL ;
// Get the current state (machine-dependent)
__ehstate_t curState = GetCurrentState(pRN, pDC, pFuncInfo);
DEBUGMSG(DBGEH,(TEXT("FindHandler: curState=GetCurrentState=%d\r\n"), curState));
DEBUGCHK(curState >= EH_EMPTY_STATE && curState < FUNC_MAXSTATE(*pFuncInfo));
// Check if it's a re-throw ( ie. no new object to throw ).
// Use the exception we stashed away if it is.
if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == NULL) {
DEBUGMSG(DBGEH,(TEXT("FindHandler: pExcept(0x%08x) is a rethrow of _pCurrentException(0x%08x)\r\n"),
pExcept, _pCurrentException));
if (_pCurrentException == NULL) {
// Oops! User re-threw a non-existant exception! Let it propogate.
return FALSE;
}
if ( PER_PTHROW(_pCurrentException) == NULL) {
DEBUGMSG(DBGEH,(TEXT("FindHandler: ThrowInfo is NULL\n"))) ;
#ifdef DBGEH
_exit (3) ;
#endif
}
pExcept = _pCurrentException;
pContext = _pCurrentExContext;
DEBUGMSG(DBGEH,(TEXT("FindHandler: reset pExcept=%08x pContext=%08x from _pCurrentException\r\n"),
pExcept, pContext));
pRethrowException = pExcept;
DEBUGMSG(DBGEH,(TEXT("FindHandler: rethrow: setting pRethrowException=%08x\r\n"),
pRethrowException));
DEBUGCHK(!PER_IS_MSVC_EH(pExcept) || PER_PTHROW(pExcept) != NULL);
}
#if !defined(_X86_)
FRAMEINFO *pFrameInfo;
if (pFrameInfo = FindFrameInfo(pRN))
{
//
// This frame called a catch block (after unwinding). reset curState
// to the state reached when the unwind occurred. NestLevel is the
// nesting level of the called catch block. This frame's nest level
// is one less.
//
curState = pFrameInfo->state;
CatchDepth = pFrameInfo->NestLevel - 1;
DEBUGMSG(DBGEH,(TEXT("FindHandler: from FindFrameInfo : curState: %d CatchDepth: %d "),
curState, CatchDepth));
DEBUGMSG(DBGEH,(TEXT(" FindHandler: pFrameInfo->pRN : %8.8x pFrameInfo->pCatchRN : %8.8lx\r\n"),
pFrameInfo->pRN, pFrameInfo->pCatchRN));
} else if ( pFrameInfo = FindCatchFrameInfo(pRN))
{
//
// This frame is a catch block which called a nested catch block.
// Dispatch based on the nested block's level.
//
CatchDepth = pFrameInfo->NestLevel;
DEBUGMSG(DBGEH,(TEXT("FindHandler: from FindCatchFrameInfo: curState: %d CatchDepth: %d "),
curState, CatchDepth));
DEBUGMSG(DBGEH,(TEXT("FindHandler: pFrameInfo->pRN : %8.8x pFrameInfo->pCatchRN : %8.8lx\r\n"),
pFrameInfo->pRN, pFrameInfo->pCatchRN));
} else
{
DEBUGMSG(DBGEH,(TEXT("FindHandler: ====Couldn't find FrameInfo/CatchFrameInfo from pFrameInfoChain(%08x)\r\n"), pFrameInfoChain));
DEBUGMSG(DBGEH,(TEXT("FindHandler: with pRN=%8.8x CatchDepth=%d curState=%d===\r\n"),
pRN, CatchDepth, curState));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -