📄 frame.cpp
字号:
#endif
// Determine range of try blocks to consider:
// Only try blocks which are at the current catch depth are of interest.
unsigned int curTryBlockIndex; // the index of current try block.
unsigned int endTryBlockIndex; // the index of try block to end search, itself excluded
TryBlockMapEntry *pEntry = _GetRangeOfTrysToCheck(pFuncInfo,
CatchDepth,
curState,
&curTryBlockIndex,
&endTryBlockIndex);
DEBUGMSG(DBGEH,(TEXT("FindHandler: TBME=%08x curTryBlockIndex=%d endTryBlockIndex=%d curState=%d\r\n"),
pEntry, curTryBlockIndex, endTryBlockIndex, curState));
// Scan the try blocks in the function:
for (; curTryBlockIndex < endTryBlockIndex; curTryBlockIndex++, pEntry++) {
DEBUGMSG(DBGEH,(TEXT("FindHandler: Scanning Try Block: pEntry=%08x curTryBlockIndex=%d curState=%d\r\n"),
pEntry, curTryBlockIndex, curState));
DEBUGMSG(DBGEH,(TEXT("FindHandler: TBME_LOW=%d TBME_HIGH=%d\r\n"),
TBME_LOW(*pEntry), TBME_HIGH(*pEntry)));
if (TBME_LOW(*pEntry) > curState || curState > TBME_HIGH(*pEntry)) {
DEBUGMSG(DBGEH,(TEXT("FindHandler: curState(%d) not in range. Skipping Try Block(%d)\r\n"),
curState, curTryBlockIndex));
continue;
}
#if !defined(_X86_)
//
// Only consider catch blocks at a higher nesting level:
//
DEBUGMSG(DBGEH,(TEXT("FindHandler: CatchDepth=%d HT_FRAMENEST=%d\r\n"),
CatchDepth, HT_FRAMENEST(TBME_CATCH(*pEntry, 0))));
if ( CatchDepth >= (int)HT_FRAMENEST(TBME_CATCH(*pEntry, 0)) ){
DEBUGMSG(DBGEH,(TEXT("FindHandler: Skipping Enclosing Catch Block. \r\n")));
continue;
}
#endif // !defined(_X86_)
DEBUGMSG(DBGEH,(TEXT("FindHandler: In Try block scope, TBME_NCATCHES=%d\r\n"),
TBME_NCATCHES(*pEntry)));
// Try block was in scope for current state. Scan catches for this try:
for (int catchIndex = 0; catchIndex < TBME_NCATCHES(*pEntry); catchIndex++){
HandlerType *pCatch;
CatchableType * const *ppCatchable;
// get pCatch with catchIndex
pCatch = TBME_PCATCH(*pEntry, catchIndex);
DEBUGMSG(DBGEH,(TEXT("FindHandler: catchIndex(%d) pCatch=%08x is trying to catch\r\n"),
catchIndex, pCatch));
if (!PER_IS_MSVC_EH(pExcept)){
//
// Non EH exception, check for an ellipsis handler
//
DEBUGMSG(DBGEH,(TEXT("FindHandler: Non Eh\r\n")));
Found = (HT_IS_TYPE_ELLIPSIS(TBME_CATCH(*pEntry, catchIndex))
&& (!HT_IS_STD_DOTDOT(TBME_CATCH(*pEntry, catchIndex))));
ppCatchable = NULL;
} else {
//
// Scan all types that thrown object can be converted to:
//
DEBUGMSG(DBGEH,(TEXT("FindHandler: to scan %d thrown objects ...\r\n"),
THROW_COUNT(*PER_PTHROW(pExcept))));
ppCatchable = THROW_CTLIST(*PER_PTHROW(pExcept));
for (int catchableIndex = 0;
catchableIndex < THROW_COUNT(*PER_PTHROW(pExcept));
catchableIndex++, ppCatchable++) {
DEBUGMSG(DBGEH,(TEXT("FindHandler: catchableIndex(%d) ppCatchable=%08x properties=%08x pCatch=%08x\r\n"),
catchableIndex, ppCatchable, CT_PROPERTIES(**ppCatchable), pCatch));
if (TypeMatch(pCatch, *ppCatchable, PER_PTHROW(pExcept))) {
DEBUGMSG(DBGEH,(TEXT("FindHandler: Found: *ppCatchable=%08x TypeMatched pCatch=%08x\r\n"),
*ppCatchable, pCatch));
Found = TRUE;
break;
}
} // Scan possible conversions
} // MSVC_EH exception
if ( Found ) {
DEBUGMSG(DBGEH,(TEXT("FindHandler: pNewExcept(0x%08x) obj(0x%08x) pthrow(0x%08x)\r\n"),
pNewExcept, PER_PEXCEPTOBJ(pNewExcept), PER_PTHROW(pNewExcept)));
_pCurrExceptRethrow = pRethrowException;
if (pRethrowException) {
DEBUGMSG(DBGEH,(TEXT("FindHandler: set pNewExcept(0x%08x) obj|pthrow to be pExcept(0x%08x)\r\n"),
pNewExcept, pExcept));
PER_PEXCEPTOBJ(pNewExcept) = PER_PEXCEPTOBJ(pExcept);
PER_PTHROW(pNewExcept) = PER_PTHROW(pExcept);
DEBUGMSG(DBGEH,(TEXT("FindHandler: pNewExcept(0x%08x) obj(0x%08x) pthrow(0x%08x)\r\n"),
pNewExcept, PER_PEXCEPTOBJ(pNewExcept), PER_PTHROW(pNewExcept)));
}
//
// A handler was found. Save current state and build a
// catch object.
//
TargetEntry = pEntry;
DEBUGMSG(DBGEH,(TEXT("FindHandler: Catch Block Found: Handler=%08x TargetState=%d\r\n"),
HT_HANDLER(*pCatch), TBME_LOW(*pEntry)));
DEBUGMSG(DBGEH,(TEXT("FindHandler: set TargetEntry=pEntry=%08x\r\n"),
pEntry));
//
// Set the Unwind continuation address to the address of
// the catch handler.
//
pDC->ControlPc = (ULONG)HT_HANDLER(*pCatch);
if (ppCatchable && *ppCatchable != NULL) {
DEBUGMSG(DBGEH,(TEXT("FindHandler: Call BuildCatchObject\r\n")));
BuildCatchObject(pExcept, pRN, pCatch, *ppCatchable);
}
DEBUGMSG(DBGEH,(TEXT("FindHandler: EXIT handler Found\r\n")));
return TRUE;
}
} // Scan catch clauses
} // Scan try blocks
DEBUGMSG(DBGEH,(TEXT("FindHandler: EXIT return search again\r\n")));
return FALSE;
} // FindHandler
////////////////////////////////////////////////////////////////////////////////
//
// TypeMatch - Check if the catch type matches the given throw conversion.
//
// Returns:
// TRUE if the catch can catch using this throw conversion, FALSE otherwise.
static __inline int TypeMatch(
HandlerType *pCatch, // Type of the 'catch' clause
CatchableType *pCatchable, // Type conversion under consideration
ThrowInfo *pThrow // General information about the thrown type.
)
{
// First, check for match with ellipsis:
if (HT_IS_TYPE_ELLIPSIS(*pCatch)) {
return TRUE;
}
// Not ellipsis; the basic types match if it's the same record *or* the
// names are identical.
if (HT_PTD(*pCatch) != CT_PTD(*pCatchable)
&& strcmp(HT_NAME(*pCatch), CT_NAME(*pCatchable)) != 0) {
return FALSE;
}
// Basic types match. The actual conversion is valid if:
// caught by ref if ref required *and*
// the qualifiers are compatible *and*
// the alignments match *and*
// the volatility matches
return (!CT_BYREFONLY(*pCatchable) || HT_ISREFERENCE(*pCatch))
&& (!THROW_ISCONST(*pThrow) || HT_ISCONST(*pCatch))
#if !defined(_X86_)
&& (!THROW_ISUNALIGNED(*pThrow) || HT_ISUNALIGNED(*pCatch))
#endif
&& (!THROW_ISVOLATILE(*pThrow) || HT_ISVOLATILE(*pCatch));
} // TypeMatch
////////////////////////////////////////////////////////////////////////////////
//
// FrameUnwindFilter - Allows possibility of continuing through SEH during
// unwind.
//
static int FrameUnwindFilter(
EXCEPTION_POINTERS *pExPtrs
)
{
EHExceptionRecord *pExcept = (EHExceptionRecord *)pExPtrs->ExceptionRecord;
switch (PER_CODE(pExcept)) {
case EH_EXCEPTION_NUMBER:
__ProcessingThrow = 0;
std::terminate();
#ifdef ALLOW_UNWIND_ABORT
case EH_ABORT_FRAME_UNWIND_PART:
return EXCEPTION_EXECUTE_HANDLER;
#endif
default:
return EXCEPTION_CONTINUE_SEARCH;
}
}
////////////////////////////////////////////////////////////////////////////////
//
// __FrameUnwindToState - Unwind this frame until specified state is reached.
//
// Returns:
// No return value.
//
// Side Effects:
// All objects on frame which go out of scope as a result of the unwind are
// destructed.
// Registration node is updated to reflect new state.
//
// Usage:
// This function is called both to do full-frame unwind during the unwind
// phase (targetState = -1), and to do partial unwinding when the current
// frame has an appropriate catch.
extern "C" void __FrameUnwindToState (
EHRegistrationNode *pRN, // Registration node for subject function
PDISPATCHER_CONTEXT pDC, // Context within subject frame
FuncInfo *pFuncInfo, // Static information for subject function
__ehstate_t targetState // State to unwind to
)
{
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: ENTER: pRN=%08x pDC->ControlPc=%08x targetState=%d\r\n"),
pRN, pDC->ControlPc, targetState));
__ehstate_t curState = GetCurrentState(pRN, pDC, pFuncInfo);
__ProcessingThrow++;
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: curState=GetCurrentState=%d\r\n"),
curState));
#if !defined(_X86_)
//
// If unwinding from a catch block which threw, use the unwind state from
// the catch block. (CatchExceptRN is set in CallCatchBlock)
//
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: CatchExceptRN=%08x CatchExceptState=%d\r\n"),
CatchExceptRN, CatchExceptState));
if ( pRN == CatchExceptRN ) {
curState = CatchExceptState;
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: pRN=CatchExceptRN=%08x\r\n"), pRN));
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: reset curState=%d\r\n"), curState));
}
CatchExceptRN = 0;
#endif // !defined(_X86_)
__try {
while (curState != targetState)
{
// The unwind-map may have a shortcut by using EH_EMPTY_STATE
if ( curState == EH_EMPTY_STATE ){
break;
}
DEBUGCHK((curState > EH_EMPTY_STATE) && (curState < FUNC_MAXSTATE(*pFuncInfo)));
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: curState=%d\r\n"), curState));
__try {
// Call the unwind action (if one exists):
if (UWE_ACTION(FUNC_UNWIND(*pFuncInfo, curState)) != NULL) {
#if defined(_M_ARM)
pRN = FindFrameForUnwind (pRN, pFuncInfo);
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: ARM adjusted pRN=%08x\r\n"),
UWE_ACTION(FUNC_UNWIND(*pFuncInfo, curState)), pRN));
// pass correct frame pointer for unwind funclet. In ARM
// the frame pointer is not stored in stack when catch
// block is called. so we need to pass the correct frame
// to access the locals
#endif // _M_ARM
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: to call _CallSettingFrame with action @%08x pRN=%08x\r\n"),
UWE_ACTION(FUNC_UNWIND(*pFuncInfo, curState)), pRN));
_CallSettingFrame(UWE_ACTION(FUNC_UNWIND(*pFuncInfo, curState)),
pRN, DC_CONTEXTRECORD(pDC), NULL);
}
else {
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: no action for curState=%d\r\n"),
curState));
}
} __except(FrameUnwindFilter(exception_info())) {
}
// Adjust the state:
curState = UWE_TOSTATE(FUNC_UNWIND(*pFuncInfo, curState));
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: adjust curState=%d\r\n"), curState));
}
} __finally {
if (__ProcessingThrow > 0) {
__ProcessingThrow--;
}
}
DEBUGCHK(curState == targetState);
DEBUGMSG(DBGEH,(TEXT("__FrameUnwindToState: EXIT curState=targetState=%d\r\n"), curState));
} // __FrameUnwindToState
#define IS_RETHROW(pNewExcept, pExcept) \
( pNewExcept && pExcept && pNewExcept!=pExcept \
&& PER_PEXCEPTOBJ(pNewExcept)==PER_PEXCEPTOBJ(pExcept) \
&& PER_PTHROW(pNewExcept)==PER_PTHROW(pExcept))
////////////////////////////////////////////////////////////////////////////////
//
// CanThisExceptionObjectBeDestructed
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -