c++异常处理
int main(){
try
{
throw 1;
}
catch ( int e )
{
printf("catch int\r\n");
}
catch ( float e)
{
printf("catch float\r\n");
}
}
函数开始,注册异常处理函数
008C8660 55 push ebp
008C8661 8B EC mov ebp,esp
008C8663 6A FF push 0FFFFFFFFh
008C8665 68 C0 83 97 00 push 9783C0h //异常处理函数
008C866A 64 A1 00 00 00 00 mov eax,dword ptr fs:[00000000h] //eax中存放SEH中的next*指针
008C8670 50 push eax //next*入栈(相当于seh新节点的next*)
008C8671 51 push ecx
008C8672 81 EC E4 00 00 00 sub esp,0E4h
008C8678 53 push ebx
008C8679 56 push esi
008C867A 57 push edi
008C867B 8D BD 0C FF FF FF lea edi,[ebp-0F4h]
008C8681 B9 39 00 00 00 mov ecx,39h
008C8686 B8 CC CC CC CC mov eax,0CCCCCCCCh
008C868B F3 AB rep stos dword ptr es:[edi]
008C868D A1 04 20 9A 00 mov eax,dword ptr [__security_cookie (09A2004h)]
008C8692 33 C5 xor eax,ebp
008C8694 50 push eax
008C8695 8D 45 F4 lea eax,[ebp-0Ch] //取next*地址
008C8698 64 A3 00 00 00 00 mov dword ptr fs:[00000000h],eax//相当于seh链表插入新节点的next*,指向的是原来的next*指针
008C869E 89 65 F0 mov dword ptr [ebp-10h],esp
9783C0h
__ehhandler$_main:
009783C0 8B 54 24 08 mov edx,dword ptr [esp+8]
009783C4 8D 42 0C lea eax,[edx+0Ch]
009783C7 8B 8A 08 FF FF FF mov ecx,dword ptr [edx-0F8h]
009783CD 33 C8 xor ecx,eax
009783CF E8 3A AB F4 FF call @__security_check_cookie@4 (08C2F0Eh)
009783D4 B8 0C 03 9A 00 mov eax,9A030Ch //EAX=FuncInfo *pFuncInfo, // Static information for this frame
009783D9 E9 AF 9A F4 FF jmp ___CxxFrameHandler3 (08C1E8Dh)
__CxxFrameHandler
EXCEPTION_DISPOSITION __CxxFrameHandler(
EHExceptionRecord *pExcept,
EHRegistrationNode *pRN,
void *pContext,
DispatcherContext *pDC
)
Parameters
pExcept
Exception record that is passed to the possible catch
statements.
pRN
Dynamic information about the stack frame that is used to handle the exception. For more information, see ehdata.h.
pContext
Context. (Not used on Intel processors.)
pDC
Additional information about the function entry and stack frame.
Return Value
One of the filter expression values used by the try-except Statement.
br
- pContext
名称 | 值 | 类型 | |
---|---|---|---|
pContext | 0x00cff468 | void * | |
pDC | 0x00cff3a4 | void * | |
pExcept | 0x00cff418 {ExceptionCode=0xe06d7363 ExceptionFlags=0x00000001 ExceptionRecord=0x00000000 <NULL> ...} | EHExceptionRecord * | |
pFuncInfo | Excepction.exe!0x009a030c {magicNumber=0x19930522 bbtFlags=0x00000000 maxState=0x00000002 ...} | const _s_FuncInfo * | |
pRN | 0x00cffa00 {pNext=0x00cffa6c {pNext=0x00cffae8 {pNext=0x00cffb00 {pNext=0xffffffff {pNext=??? frameHandler=...} ...} ...} ...} ...} | EHRegistrationNode * |
- pExcept
名称 | 值 | 类型 | |
---|---|---|---|
◢ | pExcept | 0x00cff418 {ExceptionCode=0xe06d7363 ExceptionFlags=0x00000001 ExceptionRecord=0x00000000 <NULL> ...} | EHExceptionRecord * |
ExceptionCode | 0xe06d7363 | unsigned long | |
ExceptionFlags | 0x00000001 | unsigned long | |
ExceptionRecord | 0x00000000 <NULL> | _EXCEPTION_RECORD * | |
ExceptionAddress | KernelBase.dll!0x74cfb022 (加载符号以获取其他信息) | void * | |
NumberParameters | 0x00000003 | unsigned long | |
params | {magicNumber=0x19930520 pExceptionObject=0x00cff91c pThrowInfo=0x009a0428 {Excepction.exe!__TI1H} {attributes=...} } | EHExceptionRecord::EHParameters |
- pFuncInfo
名称 | 值 | 类型 | |
---|---|---|---|
◢ | pFuncInfo | Excepction.exe!0x009a030c {magicNumber=0x19930522 bbtFlags=0x00000000 maxState=0x00000002 ...} | const _s_FuncInfo * |
magicNumber | 0x19930522 | unsigned int | |
bbtFlags | 0x00000000 | unsigned int | |
maxState | 0x00000002 | int | |
pUnwindMap | Excepction.exe!0x009a02c8 {toState=0xffffffff action=0x00000000 } | const _s_UnwindMapEntry * | |
nTryBlocks | 0x00000001 | unsigned int | |
pTryBlockMap | Excepction.exe!0x009a02d8 {tryLow=0x00000000 tryHigh=0x00000000 catchHigh=0x00000001 ...} | const _s_TryBlockMapEntry * | |
nIPMapEntries | 0x00000000 | unsigned int | |
pIPtoStateMap | 0x00000000 | void * | |
pESTypeList | 0x00000000 <NULL> | const _s_ESTypeList * | |
EHFlags | 0x00000001 | int |
- pRN
名称 | 值 | 类型 | |
---|---|---|---|
◢ | pRN | 0x00cffa00 {pNext=0x00cffa6c {pNext=0x00cffae8 {pNext=0x00cffb00 {pNext=0xffffffff {pNext=??? frameHandler=...} ...} ...} ...} ...} | EHRegistrationNode * |
◢ pNext | 0x00cffa6c {pNext=0x00cffae8 {pNext=0x00cffb00 {pNext=0xffffffff {pNext=??? frameHandler=??? state=??? } ...} ...} ...} | EHRegistrationNode * | |
◢ pNext | 0x00cffae8 {pNext=0x00cffb00 {pNext=0xffffffff {pNext=??? frameHandler=??? state=??? } frameHandler=...} ...} | EHRegistrationNode * | |
◢ pNext | 0x00cffb00 {pNext=0xffffffff {pNext=??? frameHandler=??? state=??? } frameHandler=ntdll.dll!0x772051a0 ...} | EHRegistrationNode * | |
pNext | 0xffffffff {pNext=??? frameHandler=??? state=??? } | EHRegistrationNode * | |
frameHandler | ntdll.dll!0x772051a0 (加载符号以获取其他信息) | void * | |
state | 0x00000000 | int | |
frameHandler | ntdll.dll!0x771f86d0 (加载符号以获取其他信息) | void * | |
state | 0x86f8a54a | int | |
frameHandler | 0x008cc890 {Excepction.exe!_except_handler4(_EXCEPTION_RECORD *, _EXCEPTION_REGISTRATION_RECORD *, _CONTEXT *, void *)} | void * | |
state | 0xcb1e6901 | int | |
frameHandler | 0x009783c0 {内部 Excepction.exe!_wcschr()} | void * | |
state | 0x00000000 | int |
__CxxFrameHandler3
//
// __CxxFrameHandler3 - Real entry point to the runtime
// __CxxFrameHandler2 is an alias for __CxxFrameHandler3
// since they are compatible in VC version of CRT
// These function should be separated out if a change makes
// __CxxFrameHandler3 incompatible with __CxxFrameHandler2
//
extern "C" _VCRTIMP __declspec(naked) DECLSPEC_GUARD_SUPPRESS EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler3(
/*
EAX=FuncInfo *pFuncInfo, // Static information for this frame
*/
EHExceptionRecord *pExcept, // Information for this exception
EHRegistrationNode *pRN, // Dynamic information for this frame
void *pContext, // Context info (we don't care what's in it)
DispatcherContext *pDC // More dynamic info for this frame (ignored on Intel)
) {
FuncInfo *pFuncInfo;
EXCEPTION_DISPOSITION result; __asm {
//
// Standard function prolog
//
push ebp
mov ebp, esp
sub esp, __LOCAL_SIZE
push ebx
push esi
push edi
cld // A bit of paranoia -- Our code-gen assumes this //
// Save the extra parameter
//
mov pFuncInfo, eax
} EHTRACE_ENTER_FMT1("pRN = 0x%p", pRN); result = __InternalCxxFrameHandler<RENAME_EH_EXTERN(__FrameHandler3)>( pExcept, pRN, (PCONTEXT)pContext, pDC, pFuncInfo, 0, nullptr, FALSE ); EHTRACE_HANDLER_EXIT(result); __asm {
pop edi
pop esi
pop ebx
mov eax, result
mov esp, ebp
pop ebp
ret 0
}
}
__InternalCxxFrameHandler函数主要完成了标记检查、展开、查找和派发等工作
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // __InternalCxxFrameHandler - the frame handler for all functions with C++ EH
4 // information.
5 //
6 // If exception is handled, this doesn't return; otherwise, it returns
7 // ExceptionContinueSearch.
8 //
9 // Note that this is called three ways:
10 // From __CxxFrameHandler: primary usage, called to inspect whole function.
11 // CatchDepth == 0, pMarkerRN == nullptr
12 // From CatchGuardHandler: If an exception occurred within a catch, this is
13 // called to check for try blocks within that catch only, and does not
14 // handle unwinds.
15 // From TranslatorGuardHandler: Called to handle the translation of a
16 // non-C++ EH exception. Context considered is that of parent.
17
18 template <class T>
19 EXCEPTION_DISPOSITION __InternalCxxFrameHandler(
20 EHExceptionRecord *pExcept, // Information for this exception
21 EHRegistrationNode *pRN, // Dynamic information for this frame
22 CONTEXT *pContext, // Context info
23 DispatcherContext *pDC, // Context within subject frame
24 typename T::FuncInfo *pFuncInfo, // Static information for this frame
25 int CatchDepth, // How deeply nested are we?
26 EHRegistrationNode *pMarkerRN, // Marker node for when checking inside
27 // catch block
28 BOOLEAN recursive // Are we handling a translation?
29 ) {
30
31 #if defined(_M_HYBRID_X86_ARM64) && !defined(_CHPE_X86_ARM64_EH_)
32 _HybridGenerateThunks(__InternalCxxFrameHandler<T>, 1);
33 #endif
34
35 EHTRACE_ENTER_FMT2("%s, pRN = 0x%p",
36 IS_UNWINDING(PER_FLAGS(pExcept)) ? "Unwinding" : "Searching",
37 pRN);
38
39 __except_validate_context_record(pContext);
40
41 if ((cxxReThrow == false) && (PER_CODE(pExcept) != EH_EXCEPTION_NUMBER) &&
42 #if defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_HYBRID)
43 /* On the 64 bit/ARM platforms, ExceptionCode maybe set to STATUS_UNWIND_CONSOLIDATE
44 when called from _UnwindNestedFrames during Logical Unwind. _UnwindNestedFrames
45 will also set EH_MAGIC_NUMBER1 in the 8 element */
46 (!((PER_CODE(pExcept) == STATUS_UNWIND_CONSOLIDATE) && (PER_NPARAMS(pExcept) == 15) && (PER_EXCEPTINFO(pExcept)[8] == EH_MAGIC_NUMBER1))) &&
47 #endif
48 (PER_CODE(pExcept) != STATUS_LONGJUMP) &&
49 (T::getMagicNum(pFuncInfo) >= EH_MAGIC_NUMBER3) &&
50 (T::isEHs(pFuncInfo)))
51 {
52 /*
53 * This function was compiled /EHs so we don't need to do anything in
54 * this handler.
55 */
56 return ExceptionContinueSearch;
57 }
58
59 if (IS_UNWINDING(PER_FLAGS(pExcept)))
60 {
61 // We're at the unwinding stage of things. Don't care about the
62 // exception itself. (Check this first because it's easier)
63
64 if (T::GetMaxState(pDC, pFuncInfo) != 0 && CatchDepth == 0)
65 {
66 // Only unwind if there's something to unwind
67 // AND we're being called through the primary RN.
68
69 #if defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
70
71 if (IS_TARGET_UNWIND(PER_FLAGS(pExcept)) && PER_CODE(pExcept) == STATUS_LONGJUMP) {
72 __ehstate_t target_state = T::StateFromIp(
73 pFuncInfo,
74 pDC,
75 #if defined(_M_X64)
76 pDC->TargetIp
77 #elif defined(_M_ARM) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
78 pDC->TargetPc
79 #endif
80 );
81
82 DASSERT(target_state >= EH_EMPTY_STATE
83 && target_state < T::GetMaxState(pDC, pFuncInfo));
84
85 T::FrameUnwindToState(pRN, pDC, pFuncInfo, target_state);
86 EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
87 return ExceptionContinueSearch;
88 } else if(IS_TARGET_UNWIND(PER_FLAGS(pExcept)) &&
89 PER_CODE(pExcept) == STATUS_UNWIND_CONSOLIDATE)
90 {
91 PEXCEPTION_RECORD pSehExcept = (PEXCEPTION_RECORD)pExcept;
92 __ehstate_t target_state = (__ehstate_t)pSehExcept->ExceptionInformation[3];
93
94 DASSERT(target_state >= EH_EMPTY_STATE
95 && target_state < T::GetMaxState(pDC, pFuncInfo));
96 T::FrameUnwindToState((EHRegistrationNode *)pSehExcept->ExceptionInformation[1],
97 pDC,
98 pFuncInfo,
99 target_state);
100 EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
101 return ExceptionContinueSearch;
102 }
103 #endif // defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
104 T::FrameUnwindToEmptyState(pRN, pDC, pFuncInfo);
105 }
106 EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
107 return ExceptionContinueSearch; // I don't think this value matters
108
109 }
110 else
111 {
112 auto tryBlockMap = T::TryBlockMap(pFuncInfo, pDC);
113 if (tryBlockMap.getNumTryBlocks() != 0
114 //
115 // If the function has no try block, we still want to call the
116 // frame handler if there is an exception specification
117 //
118 || (T::getMagicNum(pFuncInfo) >= EH_MAGIC_NUMBER2 && (T::getESTypes(pFuncInfo) != nullptr))
119 || (T::getMagicNum(pFuncInfo) >= EH_MAGIC_NUMBER3 && (T::isNoExcept(pFuncInfo) != 0)))
120 {
121
122 // NT is looking for handlers. We've got handlers.
123 // Let's check this puppy out. Do we recognize it?
124
125 int(__cdecl *pfn)(...);
126
127 if (PER_CODE(pExcept) == EH_EXCEPTION_NUMBER
128 && PER_NPARAMS(pExcept) >= 3
129 && PER_MAGICNUM(pExcept) > EH_MAGIC_NUMBER3
130 && (pfn = THROW_FORWARDCOMPAT(*PER_PTHROW(pExcept))) != nullptr) {
131
132 // Forward compatibility: The thrown object appears to have been
133 // created by a newer version of our compiler. Let that version's
134 // frame handler do the work (if one was specified).
135
136 #if defined(_DEBUG)
137 if (_ValidateExecute((FARPROC)(PVOID)pfn)) {
138 #endif
139 EXCEPTION_DISPOSITION result =
140 (EXCEPTION_DISPOSITION)pfn(pExcept, pRN, pContext, pDC,
141 pFuncInfo, CatchDepth,
142 pMarkerRN, recursive);
143 EHTRACE_HANDLER_EXIT(result);
144 return result;
145 #if defined(_DEBUG)
146 }
147 else {
148 terminate(); // Does not return; TKB
149 }
150 #endif
151
152 }
153 else {
154
155 // Anything else: we'll handle it here.
156 FindHandler<T>(pExcept, pRN, pContext, pDC, pFuncInfo, recursive, CatchDepth, pMarkerRN);
157 }
158
159 // If it returned, we didn't have any matches.
160
161 } // NT was looking for a handler
162 }
163
164 // We had nothing to do with it or it was rethrown. Keep searching.
165 EHTRACE_HANDLER_EXIT(ExceptionContinueSearch);
166 return ExceptionContinueSearch;
167
168 } // __InternalCxxFrameHandler
汇编:
008CEC70 55 push ebp
008CEC71 8B EC mov ebp,esp
008CEC73 83 EC 14 sub esp,14h
008CEC76 8B 45 10 mov eax,dword ptr [pContext]
008CEC79 50 push eax
008CEC7A E8 50 36 FF FF call ___except_validate_context_record (08C22CFh)
008CEC7F 83 C4 04 add esp,4
008CEC82 E8 FD 49 FF FF call ___vcrt_getptd (08C3684h)
008CEC87 83 78 20 00 cmp dword ptr [eax+20h],0
008CEC8B 75 46 jne __InternalCxxFrameHandler<__FrameHandler3>+63h (08CECD3h)
008CEC8D 8B 4D 08 mov ecx,dword ptr [pExcept]
008CEC90 81 39 63 73 6D E0 cmp dword ptr [ecx],0E06D7363h
008CEC96 74 3B je __InternalCxxFrameHandler<__FrameHandler3>+63h (08CECD3h)
008CEC98 8B 55 08 mov edx,dword ptr [pExcept]
008CEC9B 81 3A 26 00 00 80 cmp dword ptr [edx],80000026h
008CECA1 74 30 je __InternalCxxFrameHandler<__FrameHandler3>+63h (08CECD3h)
008CECA3 8B 45 18 mov eax,dword ptr [pFuncInfo]
008CECA6 50 push eax
008CECA7 E8 88 35 FF FF call __FrameHandler3::getMagicNum (08C2234h)
008CECAC 83 C4 04 add esp,4
008CECAF 3D 22 05 93 19 cmp eax,19930522h
008CECB4 72 1D jb __InternalCxxFrameHandler<__FrameHandler3>+63h (08CECD3h)
008CECB6 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CECB9 51 push ecx
008CECBA E8 55 23 FF FF call __FrameHandler3::isEHs (08C1014h)
008CECBF 83 C4 04 add esp,4
008CECC2 0F B6 D0 movzx edx,al
008CECC5 85 D2 test edx,edx
008CECC7 74 0A je __InternalCxxFrameHandler<__FrameHandler3>+63h (08CECD3h)
008CECC9 B8 01 00 00 00 mov eax,1
008CECCE E9 73 01 00 00 jmp __InternalCxxFrameHandler<__FrameHandler3>+1D6h (08CEE46h)
008CECD3 8B 45 08 mov eax,dword ptr [pExcept]
008CECD6 8B 48 04 mov ecx,dword ptr [eax+4]
008CECD9 83 E1 66 and ecx,66h
008CECDC 74 3D je __InternalCxxFrameHandler<__FrameHandler3>+0ABh (08CED1Bh)
008CECDE 8B 55 18 mov edx,dword ptr [pFuncInfo]
008CECE1 52 push edx
008CECE2 8B 45 14 mov eax,dword ptr [pDC]
008CECE5 50 push eax
008CECE6 E8 52 27 FF FF call __FrameHandler3::GetMaxState (08C143Dh)
008CECEB 83 C4 08 add esp,8
008CECEE 85 C0 test eax,eax
008CECF0 74 1A je __InternalCxxFrameHandler<__FrameHandler3>+9Ch (08CED0Ch)
008CECF2 83 7D 1C 00 cmp dword ptr [CatchDepth],0
008CECF6 75 14 jne __InternalCxxFrameHandler<__FrameHandler3>+9Ch (08CED0Ch)
008CECF8 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CECFB 51 push ecx
008CECFC 8B 55 14 mov edx,dword ptr [pDC]
008CECFF 52 push edx
008CED00 8B 45 0C mov eax,dword ptr [pRN]
008CED03 50 push eax
008CED04 E8 4D 59 FF FF call __FrameHandler3::FrameUnwindToEmptyState (08C4656h)
008CED09 83 C4 0C add esp,0Ch
008CED0C B8 01 00 00 00 mov eax,1
008CED11 E9 30 01 00 00 jmp __InternalCxxFrameHandler<__FrameHandler3>+1D6h (08CEE46h)
008CED16 E9 26 01 00 00 jmp __InternalCxxFrameHandler<__FrameHandler3>+1D1h (08CEE41h)
008CED1B 8B 4D 14 mov ecx,dword ptr [pDC]
008CED1E 51 push ecx
008CED1F 8B 55 18 mov edx,dword ptr [pFuncInfo]
008CED22 52 push edx
008CED23 8D 4D EC lea ecx,[ebp-14h]
008CED26 E8 8B 58 FF FF call __FrameHandler3::TryBlockMap::TryBlockMap (08C45B6h)
008CED2B 8D 4D EC lea ecx,[ebp-14h]
008CED2E E8 46 31 FF FF call __FrameHandler3::TryBlockMap::getNumTryBlocks (08C1E79h)
008CED33 85 C0 test eax,eax
008CED35 75 51 jne __InternalCxxFrameHandler<__FrameHandler3>+118h (08CED88h)
008CED37 8B 45 18 mov eax,dword ptr [pFuncInfo]
008CED3A 50 push eax
008CED3B E8 F4 34 FF FF call __FrameHandler3::getMagicNum (08C2234h)
008CED40 83 C4 04 add esp,4
008CED43 3D 21 05 93 19 cmp eax,19930521h
008CED48 72 10 jb __InternalCxxFrameHandler<__FrameHandler3>+0EAh (08CED5Ah)
008CED4A 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CED4D 51 push ecx
008CED4E E8 FE 26 FF FF call __FrameHandler3::getESTypes (08C1451h)
008CED53 83 C4 04 add esp,4
008CED56 85 C0 test eax,eax
008CED58 75 2E jne __InternalCxxFrameHandler<__FrameHandler3>+118h (08CED88h)
008CED5A 8B 55 18 mov edx,dword ptr [pFuncInfo]
008CED5D 52 push edx
008CED5E E8 D1 34 FF FF call __FrameHandler3::getMagicNum (08C2234h)
008CED63 83 C4 04 add esp,4
008CED66 3D 22 05 93 19 cmp eax,19930522h
008CED6B 0F 82 D0 00 00 00 jb __InternalCxxFrameHandler<__FrameHandler3>+1D1h (08CEE41h)
008CED71 8B 45 18 mov eax,dword ptr [pFuncInfo]
008CED74 50 push eax
008CED75 E8 61 51 FF FF call __FrameHandler3::isNoExcept (08C3EDBh)
008CED7A 83 C4 04 add esp,4
008CED7D 0F B6 C8 movzx ecx,al
008CED80 85 C9 test ecx,ecx
008CED82 0F 84 B9 00 00 00 je __InternalCxxFrameHandler<__FrameHandler3>+1D1h (08CEE41h)
008CED88 8B 55 08 mov edx,dword ptr [pExcept]
008CED8B 81 3A 63 73 6D E0 cmp dword ptr [edx],0E06D7363h
008CED91 0F 85 81 00 00 00 jne __InternalCxxFrameHandler<__FrameHandler3>+1A8h (08CEE18h)
008CED97 8B 45 08 mov eax,dword ptr [pExcept]
008CED9A 83 78 10 03 cmp dword ptr [eax+10h],3
008CED9E 72 78 jb __InternalCxxFrameHandler<__FrameHandler3>+1A8h (08CEE18h)
008CEDA0 8B 4D 08 mov ecx,dword ptr [pExcept]
008CEDA3 81 79 14 22 05 93 19 cmp dword ptr [ecx+14h],19930522h
008CEDAA 76 6C jbe __InternalCxxFrameHandler<__FrameHandler3>+1A8h (08CEE18h)
008CEDAC 8B 55 08 mov edx,dword ptr [pExcept]
008CEDAF 8B 42 1C mov eax,dword ptr [edx+1Ch]
008CEDB2 8B 48 08 mov ecx,dword ptr [eax+8]
008CEDB5 89 4D FC mov dword ptr [ebp-4],ecx
008CEDB8 83 7D FC 00 cmp dword ptr [ebp-4],0
008CEDBC 74 5A je __InternalCxxFrameHandler<__FrameHandler3>+1A8h (08CEE18h)
008CEDBE 8B 55 FC mov edx,dword ptr [ebp-4]
008CEDC1 52 push edx
008CEDC2 E8 EC 50 FF FF call _ValidateExecute (08C3EB3h)
008CEDC7 83 C4 04 add esp,4
008CEDCA 0F B6 C0 movzx eax,al
008CEDCD 85 C0 test eax,eax
008CEDCF 74 40 je __InternalCxxFrameHandler<__FrameHandler3>+1A1h (08CEE11h)
008CEDD1 0F B6 4D 24 movzx ecx,byte ptr [recursive]
008CEDD5 51 push ecx
008CEDD6 8B 55 20 mov edx,dword ptr [pMarkerRN]
008CEDD9 52 push edx
008CEDDA 8B 45 1C mov eax,dword ptr [CatchDepth]
008CEDDD 50 push eax
008CEDDE 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CEDE1 51 push ecx
008CEDE2 8B 55 14 mov edx,dword ptr [pDC]
008CEDE5 52 push edx
008CEDE6 8B 45 10 mov eax,dword ptr [pContext]
008CEDE9 50 push eax
008CEDEA 8B 4D 0C mov ecx,dword ptr [pRN]
008CEDED 51 push ecx
008CEDEE 8B 55 08 mov edx,dword ptr [pExcept]
008CEDF1 52 push edx
008CEDF2 8B 45 FC mov eax,dword ptr [ebp-4]
008CEDF5 89 45 F8 mov dword ptr [ebp-8],eax
008CEDF8 8B 4D F8 mov ecx,dword ptr [ebp-8]
008CEDFB FF 15 00 60 9A 00 call dword ptr [__guard_check_icall_fptr (09A6000h)]
008CEE01 FF 55 F8 call dword ptr [ebp-8]
008CEE04 83 C4 20 add esp,20h
008CEE07 89 45 F4 mov dword ptr [ebp-0Ch],eax
008CEE0A 8B 45 F4 mov eax,dword ptr [ebp-0Ch]
008CEE0D EB 37 jmp __InternalCxxFrameHandler<__FrameHandler3>+1D6h (08CEE46h)
008CEE0F EB 05 jmp __InternalCxxFrameHandler<__FrameHandler3>+1A6h (08CEE16h)
008CEE11 E8 5D 27 FF FF call _terminate (08C1573h)
008CEE16 EB 29 jmp __InternalCxxFrameHandler<__FrameHandler3>+1D1h (08CEE41h)
008CEE18 8B 4D 20 mov ecx,dword ptr [pMarkerRN]
008CEE1B 51 push ecx
008CEE1C 8B 55 1C mov edx,dword ptr [CatchDepth]
008CEE1F 52 push edx
008CEE20 0F B6 45 24 movzx eax,byte ptr [recursive]
008CEE24 50 push eax
008CEE25 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CEE28 51 push ecx
008CEE29 8B 55 14 mov edx,dword ptr [pDC]
008CEE2C 52 push edx
008CEE2D 8B 45 10 mov eax,dword ptr [pContext]
008CEE30 50 push eax
008CEE31 8B 4D 0C mov ecx,dword ptr [pRN]
008CEE34 51 push ecx
008CEE35 8B 55 08 mov edx,dword ptr [pExcept]
008CEE38 52 push edx
008CEE39 E8 C2 F4 FF FF call FindHandler<__FrameHandler3> (08CE300h) //
008CEE3E 83 C4 20 add esp,20h
008CEE41 B8 01 00 00 00 mov eax,1
008CEE46 8B E5 mov esp,ebp
008CEE48 5D pop ebp
008CEE49 C3 ret
FindHandler<__FrameHandler3>(EHExceptionRecord *, EHRegistrationNode *, _CONTEXT *, void *, const _s_FuncInfo *, unsigned char, int, EHRegistrationNode *)
1 template <class T>
2 static void FindHandler(
3 EHExceptionRecord *pExcept, // Information for this (logical)
4 // exception
5 EHRegistrationNode *pRN, // Dynamic information for subject frame
6 CONTEXT *pContext, // Context info
7 DispatcherContext *pDC, // Context within subject frame
8 typename T::FuncInfo *pFuncInfo, // Static information for subject frame
9 BOOLEAN recursive, // TRUE if we're handling the
10 // translation
11 int CatchDepth, // Level of nested catch that is being
12 // checked
13 EHRegistrationNode *pMarkerRN // Extra marker RN for nested catch
14 // handling
15 )
16 {
17
18 #if defined(_M_HYBRID_X86_ARM64) && !defined(_CHPE_X86_ARM64_EH_)
19 _HybridGenerateThunks(FindHandler<T>, 1);
20 #endif
21
22 EHTRACE_ENTER;
23
24 BOOLEAN IsRethrow = FALSE;
25 BOOLEAN gotMatch = FALSE;
26
27 // Get the current state (machine-dependent)
28 __ehstate_t curState = EH_EMPTY_STATE;
29 #if defined(_M_X64) || defined(_M_ARM_NT) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
30 curState = T::GetHandlerSearchState(pRN, pDC, pFuncInfo);
31 #else
32 curState = T::GetCurrentState(pRN, pDC, pFuncInfo);
33 #endif
34 DASSERT(curState >= EH_EMPTY_STATE && curState < T::GetMaxState(pDC, pFuncInfo));
35
36 // Check if it's a re-throw. Use the exception we stashed away if it is.
37 if (PER_IS_MSVC_EH(pExcept) && PER_PTHROW(pExcept) == nullptr) {
38
39 if (_pCurrentException == nullptr) {
40 // Oops! User re-threw a non-existent exception! Let it propagate.
41 EHTRACE_EXIT;
42 return;
43 }
44
45 pExcept = _pCurrentException;
46 pContext = _pCurrentExContext;
47 IsRethrow = TRUE;
48 #if _EH_RELATIVE_TYPEINFO
49 _SetThrowImageBase((ptrdiff_t)pExcept->params.pThrowImageBase);
50 #endif
51
52 DASSERT(_ValidateRead(pExcept));
53 DASSERT(!PER_IS_MSVC_EH(pExcept) || PER_PTHROW(pExcept) != nullptr);
54
55 //
56 // We know it is a rethrow -- did we come here as a result of an
57 // exception re-thrown from CallUnexpected() ?
58 //
59 if( _pCurrentFuncInfo != nullptr )
60 {
61 ESTypeList* pCurrentFuncInfo = _pCurrentFuncInfo; // remember it in a local variable
62 _pCurrentFuncInfo = nullptr; // and reset it immediately -- so we don't forget to do it later
63
64 // Does the exception thrown by CallUnexpected belong to the exception specification?
65
66 if( IsInExceptionSpec(pExcept, pCurrentFuncInfo) )
67 {
68 // Yes it does -- so "continue the search for another handler at the call of the function
69 // whose exception-specification was violated"
70 ;
71 }
72 else
73 {
74 // Nope, it does not. Is std::bad_exception allowed by the spec?
75
76 if( Is_bad_exception_allowed(pCurrentFuncInfo) )
77 {
78 // yup -- so according to the standard, we need to replace the thrown
79 // exception by an implementation-defined object of the type std::bad_exception
80 // and continue the search for another handler at the call of the function
81 // whose exception-specification was violated.
82
83 // Just throw bad_exception -- we will then come into FindHandler for the third time --
84 // but make sure we will not get here again
85
86 __DestructExceptionObject(pExcept, TRUE); // destroy the original object
87
88 throw std::bad_exception();
89 }
90 else
91 {
92 terminate();
93 }
94 }
95 }
96 }
97
98 auto tryBlockMap = T::TryBlockMap(pFuncInfo, pDC);
99
100 if (PER_IS_MSVC_EH(pExcept)) {
101 // Looks like it's ours. Let's see if we have a match:
102 //
103 // First, determine range of try blocks to consider:
104 // Only try blocks which are at the current catch depth are of interest.
105
106 if (tryBlockMap.getNumTryBlocks() > 0)
107 {
108 auto startStop = T::GetRangeOfTrysToCheck(tryBlockMap, curState, CatchDepth);
109 // Scan the try blocks in the function:
110 for (auto iter = startStop.first; iter < startStop.second; ++iter) {
111 auto tryBlock = *iter;
112
113 #if _EH_RELATIVE_TYPEINFO
114 __int32 const *ppCatchable;
115 #else
116 CatchableType * const *ppCatchable;
117 #endif
118 CatchableType *pCatchable;
119
120 if (tryBlock->tryLow > curState || curState > tryBlock->tryHigh) {
121 continue;
122 }
123
124 // Try block was in scope for current state. Scan catches for this
125 // try:
126 T::HandlerMap handlerMap = T::HandlerMap(tryBlock, pDC);
127 for (auto handler : handlerMap)
128 {
129 // Scan all types that thrown object can be converted to:
130 ppCatchable = THROW_CTLIST(*PER_PTHROW(pExcept));
131 for (int catchables = THROW_COUNT(*PER_PTHROW(pExcept));
132 catchables > 0; catchables--, ppCatchable++) {
133
134 #if _EH_RELATIVE_TYPEINFO
135 pCatchable = (CatchableType *)(_GetThrowImageBase() + *ppCatchable);
136 #else
137 pCatchable = *ppCatchable;
138 #endif
139
140 if (!T::TypeMatch(handler, pCatchable, PER_PTHROW(pExcept))) {
141 continue;
142 }
143
144 // OK. We finally found a match. Activate the catch. If
145 // control gets back here, the catch did a re-throw, so
146 // keep searching.
147
148 gotMatch = TRUE;
149
150 CatchIt<T>(pExcept,
151 pRN,
152 pContext,
153 pDC,
154 pFuncInfo,
155 handler,
156 pCatchable,
157 tryBlock,
158 CatchDepth,
159 pMarkerRN,
160 IsRethrow
161 #if defined (_M_X64) || defined(_M_ARM_NT) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
162 , recursive
163 #endif
164 );
165 goto NextTryBlock;
166
167 } // Scan posible conversions
168 } // Scan catch clauses
169 NextTryBlock: ;
170 } // Scan try blocks
171 } // if FUNC_NTRYBLOCKS( pFuncInfo ) > 0
172 #if defined(_DEBUG)
173 else
174 {
175 //
176 // This can only happen if the function has an exception specification
177 // but no try/catch blocks
178 //
179 DASSERT(T::getMagicNum(pFuncInfo) >= EH_MAGIC_NUMBER2);
180 DASSERT(T::getESTypes(pFuncInfo) != nullptr);
181 }
182 #endif
183
184 #if defined(_M_IX86) && !defined(_CHPE_X86_ARM64_EH_)
185 if (recursive) {
186 //
187 // A translation was provided, but this frame didn't catch it.
188 // Destruct the translated object before returning; if destruction
189 // raises an exception, terminate.
190 //
191 // This is not done for Win64 platforms. On those, the translated
192 // object is destructed in __CxxCallCatchBlock.
193 //
194 __DestructExceptionObject(pExcept, TRUE);
195 }
196 #endif
197
198 // FH4 doesn't support Exception Specifications aside from NoExcept
199 if constexpr (std::is_same_v<T, RENAME_EH_EXTERN(__FrameHandler4)>)
200 {
201 if (!gotMatch && T::isNoExcept(pFuncInfo) &&
202 #if defined(_M_IX86) && !defined(_CHPE_X86_ARM64_EH_)
203 CatchDepth == 0
204 #else
205 !T::ExecutionInCatch(pDC, pFuncInfo)
206 #endif
207 )
208 {
209 terminate();
210 }
211 }
212 else
213 {
214 //
215 // We haven't found the match -- let's look at the exception spec and see if our try
216 // matches one of the listed types.
217 //
218 // This block also handles noexcept termination if the current function is noexcept and
219 // we are not handling a nested throw or re-throw. e.g.:
220 //
221 // try {
222 // try { throw 1; } (1)
223 // catch(int) { throw; /* or throw <something new>; */ } (2)
224 // } catch(int) {} (3)
225 //
226 // During the initial search for a handler when throwing the original exception (1)
227 // we find and execute catch handler (2). This throws, which re-enters this function
228 // while in the context of a catch, but which cannot find a handler. We cannot terminate here,
229 // we're in a recursive context. Just let it go, and we'll return back to the original search
230 // from (1) and find (3). If we fail to find a handler, e.g. (3) didn't match, we would
231 // then terminate at this point as we are not in a catch block.
232 //
233 // Catch block detection uses CatchDepth on X86, or _ExecutionInCatch on other platforms. On
234 // these platforms CatchDepth is always 0 - we don't maintain a stack of entered try/catch
235 // states.
236 if (!gotMatch && FUNC_MAGICNUM(*pFuncInfo) >= EH_MAGIC_HAS_ES &&
237 (T::getESTypes(pFuncInfo) != nullptr || (T::isNoExcept(pFuncInfo) &&
238 #if defined(_M_IX86) && !defined(_CHPE_X86_ARM64_EH_)
239 CatchDepth == 0
240 #else
241 !T::ExecutionInCatch(pDC, pFuncInfo)
242 #endif
243 )))
244 {
245 // Are we noexcept?
246 if (T::isNoExcept(pFuncInfo))
247 {
248 terminate();
249 }
250
251 if (!IsInExceptionSpec(pExcept, T::getESTypes(pFuncInfo)))
252 {
253 // Nope, it does not. Call unexpected
254
255 //
256 // We must unwind the stack before calling unexpected -- this makes it work
257 // as if it were inside catch(...) clause
258 //
259 #if defined (_M_X64) || defined(_M_ARM_NT) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
260 EHRegistrationNode *pEstablisher = pRN;
261 EHRegistrationNode EstablisherFramePointers;
262 pEstablisher = T::GetEstablisherFrame(pRN, pDC, pFuncInfo, &EstablisherFramePointers);
263 T::UnwindNestedFrames(pRN,
264 pExcept,
265 pContext,
266 pEstablisher,
267 nullptr,
268 pFuncInfo,
269 EH_EMPTY_STATE,
270 EH_EMPTY_STATE,
271 nullptr,
272 pDC,
273 recursive
274 );
275 #else
276
277 _pCurrentException = pExcept;
278 _pCurrentExContext = pContext;
279
280 if (pMarkerRN == nullptr) {
281 RENAME_EH_EXTERN(_UnwindNestedFrames)(pRN, pExcept);
282 }
283 else {
284 RENAME_EH_EXTERN(_UnwindNestedFrames)(pMarkerRN, pExcept);
285 }
286 T::FrameUnwindToEmptyState(pRN, pDC, pFuncInfo);
287
288 CallUnexpected(T::getESTypes(pFuncInfo));
289 _pCurrentException = pExcept;
290 _pCurrentExContext = pContext;
291 #endif
292 }
293 }
294 }
295 } // It was a C++ EH exception
296 else
297 {
298 // Not ours. But maybe someone told us how to make it ours.
299 if (tryBlockMap.getNumTryBlocks() > 0)
300 {
301 if (!recursive) {
302 FindHandlerForForeignException<T>(pExcept, pRN, pContext, pDC,
303 pFuncInfo, curState, CatchDepth, pMarkerRN);
304 } else {
305 // We're recursive, and the exception wasn't a C++ EH!
306 // Translator threw something uninteligable.
307
308 // Two choices here: we could let the new exception take over, or we could abort. We abort.
309 terminate();
310 }
311 }
312 } // It wasn't our exception
313
314 DASSERT( _pCurrentFuncInfo == nullptr ); // never leave it initialized with something
315
316 EHTRACE_EXIT;
317 }
函数_InternalCxxFrameHandler的主要功能是完成异常类型的检查,最终调用查找try块和catch块的函数FindHandler。这个函数是完成异常处理的关键部分,完成了查找try块中抛出的异常对应的catch语句块的过程。
008CE300 55 push ebp
008CE301 8B EC mov ebp,esp
008CE303 83 EC 68 sub esp,68h
008CE306 C6 45 FF 00 mov byte ptr [IsRethrow],0
008CE30A C6 45 FE 00 mov byte ptr [gotMatch],0
008CE30E C7 45 F8 FF FF FF FF mov dword ptr [curState],0FFFFFFFFh
008CE315 8B 45 18 mov eax,dword ptr [pFuncInfo]
008CE318 50 push eax
008CE319 8B 4D 14 mov ecx,dword ptr [pDC]
008CE31C 51 push ecx
008CE31D 8B 55 0C mov edx,dword ptr [pRN]
008CE320 52 push edx
008CE321 E8 DC 39 FF FF call __FrameHandler3::GetCurrentState (08C1D02h)
008CE326 83 C4 0C add esp,0Ch
008CE329 89 45 F8 mov dword ptr [curState],eax
008CE32C 83 7D F8 FF cmp dword ptr [curState],0FFFFFFFFh
008CE330 7C 17 jl FindHandler<__FrameHandler3>+49h (08CE349h)
008CE332 8B 45 18 mov eax,dword ptr [pFuncInfo]
008CE335 50 push eax
008CE336 8B 4D 14 mov ecx,dword ptr [pDC]
008CE339 51 push ecx
008CE33A E8 FE 30 FF FF call __FrameHandler3::GetMaxState (08C143Dh)
008CE33F 83 C4 08 add esp,8
008CE342 39 45 F8 cmp dword ptr [curState],eax
008CE345 7D 02 jge FindHandler<__FrameHandler3>+49h (08CE349h)
008CE347 EB 05 jmp FindHandler<__FrameHandler3>+4Eh (08CE34Eh)
008CE349 E8 25 32 FF FF call _terminate (08C1573h)
008CE34E 8B 55 08 mov edx,dword ptr [pExcept]
008CE351 81 3A 63 73 6D E0 cmp dword ptr [edx],0E06D7363h
008CE357 0F 85 47 01 00 00 jne FindHandler<__FrameHandler3>+1A4h (08CE4A4h)
008CE35D 8B 45 08 mov eax,dword ptr [pExcept]
008CE360 83 78 10 03 cmp dword ptr [eax+10h],3
008CE364 0F 85 3A 01 00 00 jne FindHandler<__FrameHandler3>+1A4h (08CE4A4h)
008CE36A 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE36D 81 79 14 20 05 93 19 cmp dword ptr [ecx+14h],19930520h
008CE374 74 1C je FindHandler<__FrameHandler3>+92h (08CE392h)
008CE376 8B 55 08 mov edx,dword ptr [pExcept]
008CE379 81 7A 14 21 05 93 19 cmp dword ptr [edx+14h],19930521h
008CE380 74 10 je FindHandler<__FrameHandler3>+92h (08CE392h)
008CE382 8B 45 08 mov eax,dword ptr [pExcept]
008CE385 81 78 14 22 05 93 19 cmp dword ptr [eax+14h],19930522h
008CE38C 0F 85 12 01 00 00 jne FindHandler<__FrameHandler3>+1A4h (08CE4A4h)
008CE392 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE395 83 79 1C 00 cmp dword ptr [ecx+1Ch],0
008CE399 0F 85 05 01 00 00 jne FindHandler<__FrameHandler3>+1A4h (08CE4A4h)
008CE39F E8 E0 52 FF FF call ___vcrt_getptd (08C3684h)
008CE3A4 83 78 10 00 cmp dword ptr [eax+10h],0
008CE3A8 75 05 jne FindHandler<__FrameHandler3>+0AFh (08CE3AFh)
008CE3AA E9 60 04 00 00 jmp NextTryBlock+1A6h (08CE80Fh)
008CE3AF E8 D0 52 FF FF call ___vcrt_getptd (08C3684h)
008CE3B4 8B 50 10 mov edx,dword ptr [eax+10h]
008CE3B7 89 55 08 mov dword ptr [pExcept],edx
008CE3BA E8 C5 52 FF FF call ___vcrt_getptd (08C3684h)
008CE3BF 8B 40 14 mov eax,dword ptr [eax+14h]
008CE3C2 89 45 10 mov dword ptr [pContext],eax
008CE3C5 C6 45 FF 01 mov byte ptr [IsRethrow],1
008CE3C9 6A 01 push 1
008CE3CB 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE3CE 51 push ecx
008CE3CF E8 4C 48 FF FF call _ValidateRead (08C2C20h)
008CE3D4 83 C4 08 add esp,8
008CE3D7 0F B6 D0 movzx edx,al
008CE3DA 85 D2 test edx,edx
008CE3DC 74 02 je FindHandler<__FrameHandler3>+0E0h (08CE3E0h)
008CE3DE EB 05 jmp FindHandler<__FrameHandler3>+0E5h (08CE3E5h)
008CE3E0 E8 8E 31 FF FF call _terminate (08C1573h)
008CE3E5 8B 45 08 mov eax,dword ptr [pExcept]
008CE3E8 81 38 63 73 6D E0 cmp dword ptr [eax],0E06D7363h
008CE3EE 75 3B jne FindHandler<__FrameHandler3>+12Bh (08CE42Bh)
008CE3F0 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE3F3 83 79 10 03 cmp dword ptr [ecx+10h],3
008CE3F7 75 32 jne FindHandler<__FrameHandler3>+12Bh (08CE42Bh)
008CE3F9 8B 55 08 mov edx,dword ptr [pExcept]
008CE3FC 81 7A 14 20 05 93 19 cmp dword ptr [edx+14h],19930520h
008CE403 74 18 je FindHandler<__FrameHandler3>+11Dh (08CE41Dh)
008CE405 8B 45 08 mov eax,dword ptr [pExcept]
008CE408 81 78 14 21 05 93 19 cmp dword ptr [eax+14h],19930521h
008CE40F 74 0C je FindHandler<__FrameHandler3>+11Dh (08CE41Dh)
008CE411 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE414 81 79 14 22 05 93 19 cmp dword ptr [ecx+14h],19930522h
008CE41B 75 0E jne FindHandler<__FrameHandler3>+12Bh (08CE42Bh)
008CE41D 8B 55 08 mov edx,dword ptr [pExcept]
008CE420 83 7A 1C 00 cmp dword ptr [edx+1Ch],0
008CE424 75 05 jne FindHandler<__FrameHandler3>+12Bh (08CE42Bh)
008CE426 E8 48 31 FF FF call _terminate (08C1573h)
008CE42B E8 54 52 FF FF call ___vcrt_getptd (08C3684h)
008CE430 83 78 1C 00 cmp dword ptr [eax+1Ch],0
008CE434 74 6E je FindHandler<__FrameHandler3>+1A4h (08CE4A4h)
008CE436 E8 49 52 FF FF call ___vcrt_getptd (08C3684h)
008CE43B 8B 40 1C mov eax,dword ptr [eax+1Ch]
008CE43E 89 45 E8 mov dword ptr [ebp-18h],eax
008CE441 E8 3E 52 FF FF call ___vcrt_getptd (08C3684h)
008CE446 C7 40 1C 00 00 00 00 mov dword ptr [eax+1Ch],0
008CE44D 8B 4D E8 mov ecx,dword ptr [ebp-18h]
008CE450 51 push ecx
008CE451 8B 55 08 mov edx,dword ptr [pExcept]
008CE454 52 push edx
008CE455 E8 66 14 00 00 call IsInExceptionSpec (08CF8C0h)
008CE45A 83 C4 08 add esp,8
008CE45D 0F B6 C0 movzx eax,al
008CE460 85 C0 test eax,eax
008CE462 74 02 je FindHandler<__FrameHandler3>+166h (08CE466h)
008CE464 EB 3E jmp FindHandler<__FrameHandler3>+1A4h (08CE4A4h)
008CE466 8B 4D E8 mov ecx,dword ptr [ebp-18h]
008CE469 51 push ecx
008CE46A E8 31 15 00 00 call Is_bad_exception_allowed (08CF9A0h)
008CE46F 83 C4 04 add esp,4
008CE472 0F B6 D0 movzx edx,al
008CE475 85 D2 test edx,edx
008CE477 74 26 je FindHandler<__FrameHandler3>+19Fh (08CE49Fh)
008CE479 6A 01 push 1
008CE47B 8B 45 08 mov eax,dword ptr [pExcept]
008CE47E 50 push eax
008CE47F E8 FC 3C FF FF call ___DestructExceptionObject (08C2180h)
008CE484 83 C4 08 add esp,8
008CE487 8D 4D A8 lea ecx,[ebp-58h]
008CE48A E8 D2 38 FF FF call std::bad_exception::bad_exception (08C1D61h)
008CE48F 68 78 06 9A 00 push offset __TI2?AVbad_exception@std@@ (09A0678h)
008CE494 8D 4D A8 lea ecx,[ebp-58h]
008CE497 51 push ecx
008CE498 E8 D1 62 FF FF call __CxxThrowException@8 (08C476Eh)
008CE49D EB 05 jmp FindHandler<__FrameHandler3>+1A4h (08CE4A4h)
008CE49F E8 CF 30 FF FF call _terminate (08C1573h)
008CE4A4 8B 55 14 mov edx,dword ptr [pDC]
008CE4A7 52 push edx
008CE4A8 8B 45 18 mov eax,dword ptr [pFuncInfo]
008CE4AB 50 push eax
008CE4AC 8D 4D C4 lea ecx,[tryBlockMap]
008CE4AF E8 02 61 FF FF call __FrameHandler3::TryBlockMap::TryBlockMap (08C45B6h)
008CE4B4 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE4B7 81 39 63 73 6D E0 cmp dword ptr [ecx],0E06D7363h
008CE4BD 0F 85 F7 02 00 00 jne NextTryBlock+151h (08CE7BAh)
008CE4C3 8B 55 08 mov edx,dword ptr [pExcept]
008CE4C6 83 7A 10 03 cmp dword ptr [edx+10h],3
008CE4CA 0F 85 EA 02 00 00 jne NextTryBlock+151h (08CE7BAh)
008CE4D0 8B 45 08 mov eax,dword ptr [pExcept]
008CE4D3 81 78 14 20 05 93 19 cmp dword ptr [eax+14h],19930520h
008CE4DA 74 1C je FindHandler<__FrameHandler3>+1F8h (08CE4F8h)
008CE4DC 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE4DF 81 79 14 21 05 93 19 cmp dword ptr [ecx+14h],19930521h
008CE4E6 74 10 je FindHandler<__FrameHandler3>+1F8h (08CE4F8h)
008CE4E8 8B 55 08 mov edx,dword ptr [pExcept]
008CE4EB 81 7A 14 22 05 93 19 cmp dword ptr [edx+14h],19930522h
008CE4F2 0F 85 C2 02 00 00 jne NextTryBlock+151h (08CE7BAh)
008CE4F8 8D 4D C4 lea ecx,[tryBlockMap]
008CE4FB E8 79 39 FF FF call __FrameHandler3::TryBlockMap::getNumTryBlocks (08C1E79h)
008CE500 85 C0 test eax,eax
008CE502 0F 86 68 01 00 00 jbe NextTryBlock+7h (08CE670h)
008CE508 8B 45 20 mov eax,dword ptr [CatchDepth]
008CE50B 50 push eax
008CE50C 8B 4D F8 mov ecx,dword ptr [curState]
008CE50F 51 push ecx
008CE510 8D 55 C4 lea edx,[tryBlockMap]
008CE513 52 push edx
008CE514 8D 45 98 lea eax,[ebp-68h]
008CE517 50 push eax
008CE518 E8 7D 54 FF FF call __FrameHandler3::GetRangeOfTrysToCheck (08C399Ah)
008CE51D 83 C4 10 add esp,10h
008CE520 8B 4D 98 mov ecx,dword ptr [ebp-68h]
008CE523 89 4D D4 mov dword ptr [ebp-2Ch],ecx
008CE526 8B 55 9C mov edx,dword ptr [ebp-64h]
008CE529 89 55 D8 mov dword ptr [ebp-28h],edx
008CE52C EB 08 jmp FindHandler<__FrameHandler3>+236h (08CE536h)
008CE52E 8D 4D D4 lea ecx,[ebp-2Ch]
008CE531 E8 85 4C FF FF call __FrameHandler3::TryBlockMap::iterator::operator++ (08C31BBh)
008CE536 8D 45 A0 lea eax,[ebp-60h]
008CE539 50 push eax
008CE53A 8D 4D D4 lea ecx,[ebp-2Ch]
008CE53D E8 BE 2F FF FF call __FrameHandler3::TryBlockMap::iterator::operator< (08C1500h)
008CE542 0F B6 C8 movzx ecx,al
008CE545 85 C9 test ecx,ecx
008CE547 0F 84 21 01 00 00 je NextTryBlock+5h (08CE66Eh)
008CE54D 8D 4D D4 lea ecx,[ebp-2Ch]
008CE550 E8 B7 3C FF FF call __FrameHandler3::TryBlockMap::iterator::operator* (08C220Ch)
008CE555 89 45 F4 mov dword ptr [ebp-0Ch],eax
008CE558 8B 55 F4 mov edx,dword ptr [ebp-0Ch]
008CE55B 8B 02 mov eax,dword ptr [edx]
008CE55D 3B 45 F8 cmp eax,dword ptr [curState]
008CE560 7F 0B jg FindHandler<__FrameHandler3>+26Dh (08CE56Dh)
008CE562 8B 4D F4 mov ecx,dword ptr [ebp-0Ch]
008CE565 8B 55 F8 mov edx,dword ptr [curState]
008CE568 3B 51 04 cmp edx,dword ptr [ecx+4]
008CE56B 7E 02 jle FindHandler<__FrameHandler3>+26Fh (08CE56Fh)
008CE56D EB BF jmp FindHandler<__FrameHandler3>+22Eh (08CE52Eh)
008CE56F 8B 45 14 mov eax,dword ptr [pDC]
008CE572 50 push eax
008CE573 8B 4D F4 mov ecx,dword ptr [ebp-0Ch]
008CE576 51 push ecx
008CE577 8D 4D BC lea ecx,[ebp-44h]
008CE57A E8 F1 4B FF FF call __FrameHandler3::HandlerMap::HandlerMap (08C3170h)
008CE57F 8D 55 BC lea edx,[ebp-44h]
008CE582 89 55 E4 mov dword ptr [ebp-1Ch],edx
008CE585 8D 45 CC lea eax,[ebp-34h]
008CE588 50 push eax
008CE589 8B 4D E4 mov ecx,dword ptr [ebp-1Ch]
008CE58C E8 84 42 FF FF call __FrameHandler3::HandlerMap::begin (08C2815h)
008CE591 8D 4D B4 lea ecx,[ebp-4Ch]
008CE594 51 push ecx
008CE595 8B 4D E4 mov ecx,dword ptr [ebp-1Ch]
008CE598 E8 E5 57 FF FF call __FrameHandler3::HandlerMap::end (08C3D82h)
008CE59D EB 08 jmp FindHandler<__FrameHandler3>+2A7h (08CE5A7h)
008CE59F 8D 4D CC lea ecx,[ebp-34h]
008CE5A2 E8 9E 3A FF FF call __FrameHandler3::HandlerMap::iterator::operator++ (08C2045h)
008CE5A7 8D 55 B4 lea edx,[ebp-4Ch]
008CE5AA 52 push edx
008CE5AB 8D 4D CC lea ecx,[ebp-34h]
008CE5AE E8 76 4C FF FF call __FrameHandler3::HandlerMap::iterator::operator!= (08C3229h)
008CE5B3 0F B6 C0 movzx eax,al
008CE5B6 85 C0 test eax,eax
008CE5B8 0F 84 AB 00 00 00 je NextTryBlock (08CE669h)
008CE5BE 8D 4D CC lea ecx,[ebp-34h]
008CE5C1 E8 9D 58 FF FF call __FrameHandler3::HandlerMap::iterator::operator* (08C3E63h)
008CE5C6 89 45 DC mov dword ptr [ebp-24h],eax
008CE5C9 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE5CC 8B 51 1C mov edx,dword ptr [ecx+1Ch]
008CE5CF 8B 42 0C mov eax,dword ptr [edx+0Ch]
008CE5D2 83 C0 04 add eax,4
008CE5D5 89 45 EC mov dword ptr [ebp-14h],eax
008CE5D8 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE5DB 8B 51 1C mov edx,dword ptr [ecx+1Ch]
008CE5DE 8B 42 0C mov eax,dword ptr [edx+0Ch]
008CE5E1 8B 08 mov ecx,dword ptr [eax]
008CE5E3 89 4D F0 mov dword ptr [ebp-10h],ecx
008CE5E6 EB 12 jmp FindHandler<__FrameHandler3>+2FAh (08CE5FAh)
008CE5E8 8B 55 F0 mov edx,dword ptr [ebp-10h]
008CE5EB 83 EA 01 sub edx,1
008CE5EE 89 55 F0 mov dword ptr [ebp-10h],edx
008CE5F1 8B 45 EC mov eax,dword ptr [ebp-14h]
008CE5F4 83 C0 04 add eax,4
008CE5F7 89 45 EC mov dword ptr [ebp-14h],eax
008CE5FA 83 7D F0 00 cmp dword ptr [ebp-10h],0
008CE5FE 7E 64 jle FindHandler<__FrameHandler3>+364h (08CE664h)
008CE600 8B 4D EC mov ecx,dword ptr [ebp-14h]
008CE603 8B 11 mov edx,dword ptr [ecx]
008CE605 89 55 E0 mov dword ptr [ebp-20h],edx
008CE608 8B 45 08 mov eax,dword ptr [pExcept]
008CE60B 8B 48 1C mov ecx,dword ptr [eax+1Ch]
008CE60E 51 push ecx
008CE60F 8B 55 E0 mov edx,dword ptr [ebp-20h]
008CE612 52 push edx
008CE613 8B 45 DC mov eax,dword ptr [ebp-24h]
008CE616 50 push eax
008CE617 E8 2C 50 FF FF call __FrameHandler3::TypeMatch (08C3648h)//异常匹配的判定
008CE61C 83 C4 0C add esp,0Ch
008CE61F 85 C0 test eax,eax
008CE621 75 02 jne FindHandler<__FrameHandler3>+325h (08CE625h)
008CE623 EB C3 jmp FindHandler<__FrameHandler3>+2E8h (08CE5E8h)
008CE625 C6 45 FE 01 mov byte ptr [gotMatch],1
008CE629 0F B6 4D FF movzx ecx,byte ptr [IsRethrow]
008CE62D 51 push ecx
008CE62E 8B 55 24 mov edx,dword ptr [pMarkerRN]
008CE631 52 push edx
008CE632 8B 45 20 mov eax,dword ptr [CatchDepth]
008CE635 50 push eax
008CE636 8B 4D F4 mov ecx,dword ptr [ebp-0Ch]
008CE639 51 push ecx
008CE63A 8B 55 E0 mov edx,dword ptr [ebp-20h]
008CE63D 52 push edx
008CE63E 8B 45 DC mov eax,dword ptr [ebp-24h]
008CE641 50 push eax
008CE642 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CE645 51 push ecx
008CE646 8B 55 14 mov edx,dword ptr [pDC]
008CE649 52 push edx
008CE64A 8B 45 10 mov eax,dword ptr [pContext]
008CE64D 50 push eax
008CE64E 8B 4D 0C mov ecx,dword ptr [pRN]
008CE651 51 push ecx
008CE652 8B 55 08 mov edx,dword ptr [pExcept]
008CE655 52 push edx
008CE656 E8 A5 FB FF FF call CatchIt<__FrameHandler3> (08CE200h) //catch对象的构造与析构过程,并跳转到catch结束地址
008CE65B 83 C4 2C add esp,2Ch
008CE65E EB 09 jmp NextTryBlock (08CE669h)
008CE660 EB 07 jmp NextTryBlock (08CE669h)
008CE662 EB 84 jmp FindHandler<__FrameHandler3>+2E8h (08CE5E8h)
008CE664 E9 36 FF FF FF jmp FindHandler<__FrameHandler3>+29Fh (08CE59Fh)
008CE669 E9 C0 FE FF FF jmp FindHandler<__FrameHandler3>+22Eh (08CE52Eh)
008CE66E EB 31 jmp NextTryBlock+38h (08CE6A1h)
008CE670 8B 45 18 mov eax,dword ptr [pFuncInfo]
008CE673 50 push eax
008CE674 E8 BB 3B FF FF call __FrameHandler3::getMagicNum (08C2234h)
008CE679 83 C4 04 add esp,4
008CE67C 3D 21 05 93 19 cmp eax,19930521h
008CE681 72 02 jb NextTryBlock+1Ch (08CE685h)
008CE683 EB 05 jmp NextTryBlock+21h (08CE68Ah)
008CE685 E8 E9 2E FF FF call _terminate (08C1573h)
008CE68A 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CE68D 51 push ecx
008CE68E E8 BE 2D FF FF call __FrameHandler3::getESTypes (08C1451h)
008CE693 83 C4 04 add esp,4
008CE696 85 C0 test eax,eax
008CE698 74 02 je NextTryBlock+33h (08CE69Ch)
008CE69A EB 05 jmp NextTryBlock+38h (08CE6A1h)
008CE69C E8 D2 2E FF FF call _terminate (08C1573h)
008CE6A1 0F B6 55 1C movzx edx,byte ptr [recursive]
008CE6A5 85 D2 test edx,edx
008CE6A7 74 0E je NextTryBlock+4Eh (08CE6B7h)
008CE6A9 6A 01 push 1
008CE6AB 8B 45 08 mov eax,dword ptr [pExcept]
008CE6AE 50 push eax
008CE6AF E8 CC 3A FF FF call ___DestructExceptionObject (08C2180h)
008CE6B4 83 C4 08 add esp,8
008CE6B7 0F B6 4D FE movzx ecx,byte ptr [gotMatch]
008CE6BB 85 C9 test ecx,ecx
008CE6BD 0F 85 F5 00 00 00 jne NextTryBlock+14Fh (08CE7B8h)
008CE6C3 8B 55 18 mov edx,dword ptr [pFuncInfo]
008CE6C6 8B 02 mov eax,dword ptr [edx]
008CE6C8 25 FF FF FF 1F and eax,1FFFFFFFh
008CE6CD 3D 21 05 93 19 cmp eax,19930521h
008CE6D2 0F 82 E0 00 00 00 jb NextTryBlock+14Fh (08CE7B8h)
008CE6D8 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CE6DB 51 push ecx
008CE6DC E8 70 2D FF FF call __FrameHandler3::getESTypes (08C1451h)
008CE6E1 83 C4 04 add esp,4
008CE6E4 85 C0 test eax,eax
008CE6E6 75 21 jne NextTryBlock+0A0h (08CE709h)
008CE6E8 8B 55 18 mov edx,dword ptr [pFuncInfo]
008CE6EB 52 push edx
008CE6EC E8 EA 57 FF FF call __FrameHandler3::isNoExcept (08C3EDBh)
008CE6F1 83 C4 04 add esp,4
008CE6F4 0F B6 C0 movzx eax,al
008CE6F7 85 C0 test eax,eax
008CE6F9 0F 84 B9 00 00 00 je NextTryBlock+14Fh (08CE7B8h)
008CE6FF 83 7D 20 00 cmp dword ptr [CatchDepth],0
008CE703 0F 85 AF 00 00 00 jne NextTryBlock+14Fh (08CE7B8h)
008CE709 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CE70C 51 push ecx
008CE70D E8 C9 57 FF FF call __FrameHandler3::isNoExcept (08C3EDBh)
008CE712 83 C4 04 add esp,4
008CE715 0F B6 D0 movzx edx,al
008CE718 85 D2 test edx,edx
008CE71A 74 05 je NextTryBlock+0B8h (08CE721h)
008CE71C E8 52 2E FF FF call _terminate (08C1573h)
008CE721 8B 45 18 mov eax,dword ptr [pFuncInfo]
008CE724 50 push eax
008CE725 E8 27 2D FF FF call __FrameHandler3::getESTypes (08C1451h)
008CE72A 83 C4 04 add esp,4
008CE72D 50 push eax
008CE72E 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE731 51 push ecx
008CE732 E8 89 11 00 00 call IsInExceptionSpec (08CF8C0h)
008CE737 83 C4 08 add esp,8
008CE73A 0F B6 D0 movzx edx,al
008CE73D 85 D2 test edx,edx
008CE73F 75 77 jne NextTryBlock+14Fh (08CE7B8h)
008CE741 E8 3E 4F FF FF call ___vcrt_getptd (08C3684h)
008CE746 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE749 89 48 10 mov dword ptr [eax+10h],ecx
008CE74C E8 33 4F FF FF call ___vcrt_getptd (08C3684h)
008CE751 8B 55 10 mov edx,dword ptr [pContext]
008CE754 89 50 14 mov dword ptr [eax+14h],edx
008CE757 83 7D 24 00 cmp dword ptr [pMarkerRN],0
008CE75B 75 0F jne NextTryBlock+103h (08CE76Ch)
008CE75D 8B 45 08 mov eax,dword ptr [pExcept]
008CE760 50 push eax
008CE761 8B 4D 0C mov ecx,dword ptr [pRN]
008CE764 51 push ecx
008CE765 E8 32 32 FF FF call _UnwindNestedFrames (08C199Ch)
008CE76A EB 0D jmp NextTryBlock+110h (08CE779h)
008CE76C 8B 55 08 mov edx,dword ptr [pExcept]
008CE76F 52 push edx
008CE770 8B 45 24 mov eax,dword ptr [pMarkerRN]
008CE773 50 push eax
008CE774 E8 23 32 FF FF call _UnwindNestedFrames (08C199Ch)
008CE779 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CE77C 51 push ecx
008CE77D 8B 55 14 mov edx,dword ptr [pDC]
008CE780 52 push edx
008CE781 8B 45 0C mov eax,dword ptr [pRN]
008CE784 50 push eax
008CE785 E8 CC 5E FF FF call __FrameHandler3::FrameUnwindToEmptyState (08C4656h)
008CE78A 83 C4 0C add esp,0Ch
008CE78D 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
008CE790 51 push ecx
008CE791 E8 BB 2C FF FF call __FrameHandler3::getESTypes (08C1451h)
008CE796 83 C4 04 add esp,4
008CE799 50 push eax
008CE79A E8 C1 0D 00 00 call CallUnexpected (08CF560h)
008CE79F 83 C4 04 add esp,4
008CE7A2 E8 DD 4E FF FF call ___vcrt_getptd (08C3684h)
008CE7A7 8B 55 08 mov edx,dword ptr [pExcept]
008CE7AA 89 50 10 mov dword ptr [eax+10h],edx
008CE7AD E8 D2 4E FF FF call ___vcrt_getptd (08C3684h)
008CE7B2 8B 4D 10 mov ecx,dword ptr [pContext]
008CE7B5 89 48 14 mov dword ptr [eax+14h],ecx
008CE7B8 EB 43 jmp NextTryBlock+194h (08CE7FDh)
008CE7BA 8D 4D C4 lea ecx,[tryBlockMap]
008CE7BD E8 B7 36 FF FF call __FrameHandler3::TryBlockMap::getNumTryBlocks (08C1E79h)
008CE7C2 85 C0 test eax,eax
008CE7C4 76 37 jbe NextTryBlock+194h (08CE7FDh)
008CE7C6 0F B6 55 1C movzx edx,byte ptr [recursive]
008CE7CA 85 D2 test edx,edx
008CE7CC 75 2A jne NextTryBlock+18Fh (08CE7F8h)
008CE7CE 8B 45 24 mov eax,dword ptr [pMarkerRN]
008CE7D1 50 push eax
008CE7D2 8B 4D 20 mov ecx,dword ptr [CatchDepth]
008CE7D5 51 push ecx
008CE7D6 8B 55 F8 mov edx,dword ptr [curState]
008CE7D9 52 push edx
008CE7DA 8B 45 18 mov eax,dword ptr [pFuncInfo]
008CE7DD 50 push eax
008CE7DE 8B 4D 14 mov ecx,dword ptr [pDC]
008CE7E1 51 push ecx
008CE7E2 8B 55 10 mov edx,dword ptr [pContext]
008CE7E5 52 push edx
008CE7E6 8B 45 0C mov eax,dword ptr [pRN]
008CE7E9 50 push eax
008CE7EA 8B 4D 08 mov ecx,dword ptr [pExcept]
008CE7ED 51 push ecx
008CE7EE E8 6D 01 00 00 call FindHandlerForForeignException<__FrameHandler3> (08CE960h)
008CE7F3 83 C4 20 add esp,20h
008CE7F6 EB 05 jmp NextTryBlock+194h (08CE7FDh)
008CE7F8 E8 76 2D FF FF call _terminate (08C1573h)
008CE7FD E8 82 4E FF FF call ___vcrt_getptd (08C3684h)
008CE802 83 78 1C 00 cmp dword ptr [eax+1Ch],0
008CE806 75 02 jne NextTryBlock+1A1h (08CE80Ah)
008CE808 EB 05 jmp NextTryBlock+1A6h (08CE80Fh)
008CE80A E8 64 2D FF FF call _terminate (08C1573h)
008CE80F 8B E5 mov esp,ebp
008CE811 5D pop ebp
008CE812 C3 ret
int RENAME_EH_EXTERN(__FrameHandler3)::TypeMatch(
HandlerType *pCatch,
CatchableType *pCatchable,
ThrowInfo *pThrow
)
TypeMatch函数完成了对异常匹配的判定
int RENAME_EH_EXTERN(__FrameHandler3)::TypeMatch(
HandlerType *pCatch,
CatchableType *pCatchable,
ThrowInfo *pThrow
)
{
return TypeMatchHelper<HandlerType>(pCatch, pCatchable, pThrow);
};
1 template <class T>
2 int TypeMatchHelper(
3 T *pCatch, // Type of the 'catch' clause
4 CatchableType *pCatchable, // Type conversion under consideration
5 ThrowInfo *pThrow // General information about the thrown
6 // type.
7 ) {
8 // First, check for match with ellipsis:
9 if (HT_IS_TYPE_ELLIPSIS(*pCatch)) {
10 return TRUE;
11 }
12
13 if (HT_ISBADALLOCCOMPAT(*pCatch) && CT_ISSTDBADALLOC(*pCatchable))
14 {
15 return true;
16 }
17
18 // Not ellipsis; the basic types match if it's the same record *or* the
19 // names are identical.
20 if (HT_PTD(*pCatch) != CT_PTD(*pCatchable)
21 && strcmp(HT_NAME(*pCatch), CT_NAME(*pCatchable)) != 0) {
22 return FALSE;
23 }
24
25 // Basic types match. The actual conversion is valid if:
26 // caught by ref if ref required *and*
27 // the qualifiers are compatible *and*
28 // the alignments match *and*
29 // the volatility matches
30
31 return (!CT_BYREFONLY(*pCatchable) || HT_ISREFERENCE(*pCatch))
32 && (!THROW_ISCONST(*pThrow) || HT_ISCONST(*pCatch))
33 #if defined(_M_X64) || defined(_M_ARM_NT) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
34 && (!THROW_ISUNALIGNED(*pThrow) || HT_ISUNALIGNED(*pCatch))
35 #endif
36 && (!THROW_ISVOLATILE(*pThrow) || HT_ISVOLATILE(*pCatch));
37 }
CatchIt<__FrameHandler3>(EHExceptionRecord *, EHRegistrationNode *, _CONTEXT *, void *, const _s_FuncInfo *, const _s_HandlerType *, const _s_CatchableType *, const _s_TryBlockMapEntry *, int, EHRegistrationNode *, unsigned char)
函数主要由四部分组成:异常对象的产生,析构try中的对象,跳转到对应的catch地址,返回到异常catch块的结尾地址。
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // CatchIt - A handler has been found for the thrown type. Do the work to
4 // transfer control.
5 //
6 // Description:
7 // Builds the catch object
8 // Unwinds the stack to the point of the try
9 // Calls the address of the handler (funclet) with the frame set up for that
10 // function but without resetting the stack.
11 // Handler funclet returns address to continue execution, or nullptr if the
12 // handler re-threw ("throw;" lexically in handler)
13 // If the handler throws an EH exception whose exception info is nullptr, then
14 // it's a re-throw from a dynamicly enclosed scope.
15 //
16 // It is an open question whether the catch object is built before or after the local unwind.
17 //
18 // Returns:
19 // No return value. Returns iff handler re-throws.
20 template <class T>
21 static void CatchIt(
22 EHExceptionRecord *pExcept, // The exception thrown
23 EHRegistrationNode *pRN, // Dynamic info of function with catch
24 CONTEXT *pContext, // Context info
25 DispatcherContext *pDC, // Context within subject frame
26 typename T::FuncInfo *pFuncInfo, // Static info of function with catch
27 typename T::HandlerType *pCatch, // The catch clause selected
28 CatchableType *pConv, // The rules for making the conversion
29 typename T::TryBlockMapEntry *pEntry, // Description of the try block
30 int CatchDepth, // How many catches are we nested in?
31 EHRegistrationNode *pMarkerRN, // Special node if nested in catch
32 BOOLEAN IsRethrow // Is this a rethrow ?
33 #if defined(_M_X64) || defined(_M_ARM_NT) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
34 , BOOLEAN recursive
35 #endif // defined(_POWERPC)
36 ) {
37
38 // These parameters are not used in some compilations
39 UNREFERENCED_PARAMETER(CatchDepth);
40 UNREFERENCED_PARAMETER(pMarkerRN);
41 UNREFERENCED_PARAMETER(IsRethrow);
42
43 EHTRACE_ENTER_FMT1("Catching object @ 0x%p", PER_PEXCEPTOBJ(pExcept));
44
45 EHRegistrationNode *pEstablisher = pRN;
46
47 #if defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
48 EHRegistrationNode EstablisherFramePointers;
49 pEstablisher = T::GetEstablisherFrame(pRN, pDC, pFuncInfo, &EstablisherFramePointers);
50 #else
51 void *continuationAddress;
52 #endif // defined(_POWERPC)
53
54 // Copy the thrown object into a buffer in the handler's stack frame,
55 // unless the catch was by elipsis (no conversion) OR the catch was by
56 // type without an actual 'catch object'.
57
58 if (pConv != nullptr) {
59 T::BuildCatchObject(pExcept, pEstablisher, pCatch, pConv);
60 }
61
62 // Unwind stack objects to the entry of the try that caught this exception.
63
64 #if defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_)
65 // This call will never return. This call will end up calling CxxCallCatchBlock
66 // through RtlUnwind (STATUS_CONSULIDATE_FRAMES) mechanism.
67 T::UnwindNestedFrames(
68 pRN,
69 pExcept,
70 pContext,
71 pEstablisher,
72 __GetAddress(HT_HANDLER(*pCatch), pDC),
73 pFuncInfo,
74 pEntry->tryLow,
75 pEntry->catchHigh,
76 pCatch,
77 pDC,
78 recursive
79 );
80
81 #else
82
83 if constexpr (std::is_same_v<T, RENAME_EH_EXTERN(__FrameHandler4)>)
84 {
85 // TODO: x86
86 DASSERT(!"NYI");
87 }
88 else
89 {
90 if (pMarkerRN == nullptr) {
91 RENAME_EH_EXTERN(_UnwindNestedFrames)(pRN, pExcept);
92 }
93 else {
94 RENAME_EH_EXTERN(_UnwindNestedFrames)(pMarkerRN, pExcept);
95 }
96
97
98 T::FrameUnwindToState(pEstablisher, pDC, pFuncInfo, TBME_LOW(*pEntry));
99
100 // Call the catch. Separated out because it introduces a new registration
101 // node.
102
103 EHTRACE_FMT2("Move from state %d to state %d", T::GetCurrentState(pRN, pDC, pFuncInfo), TBME_HIGH(*pEntry) + 1);
104 T::SetState(pRN, pFuncInfo, TBME_HIGH(*pEntry) + 1);
105
106 continuationAddress = CallCatchBlock(pExcept,
107 pEstablisher,
108 pContext,
109 pFuncInfo,
110 __GetAddress(HT_HANDLER(*pCatch), pDC),
111 CatchDepth,
112 0x100);
113
114 // Transfer control to the continuation address. If no continuation then
115 // it's a re-throw, so return.
116
117 if (continuationAddress != nullptr) {
118
119 _JumpToContinuation(continuationAddress, pRN);
120 // No return.
121
122 }
123 EHTRACE_EXIT;
124 }
125 #endif
126 }
00B4E200 55 push ebp
00B4E201 8B EC mov ebp,esp
00B4E203 83 EC 08 sub esp,8
00B4E206 8B 45 0C mov eax,dword ptr [pRN]
00B4E209 89 45 FC mov dword ptr [pEstablisher],eax
00B4E20C 83 7D 20 00 cmp dword ptr [pConv],0
00B4E210 74 18 je CatchIt<__FrameHandler3>+2Ah (0B4E22Ah)
00B4E212 8B 4D 20 mov ecx,dword ptr [pConv]
00B4E215 51 push ecx
00B4E216 8B 55 1C mov edx,dword ptr [pCatch]
00B4E219 52 push edx
00B4E21A 8B 45 FC mov eax,dword ptr [pEstablisher]
00B4E21D 50 push eax
00B4E21E 8B 4D 08 mov ecx,dword ptr [pExcept]
00B4E221 51 push ecx
00B4E222 E8 D5 59 FF FF call __FrameHandler3::BuildCatchObject (0B43BFCh) //使用BuildCatchObject函数对抛出的异常对象进行处理
00B4E227 83 C4 10 add esp,10h
00B4E22A 83 7D 2C 00 cmp dword ptr [pMarkerRN],0
00B4E22E 75 0F jne CatchIt<__FrameHandler3>+3Fh (0B4E23Fh)
00B4E230 8B 55 08 mov edx,dword ptr [pExcept]
00B4E233 52 push edx
00B4E234 8B 45 0C mov eax,dword ptr [pRN]
00B4E237 50 push eax
00B4E238 E8 5F 37 FF FF call _UnwindNestedFrames (0B4199Ch)
00B4E23D EB 0D jmp CatchIt<__FrameHandler3>+4Ch (0B4E24Ch)
00B4E23F 8B 4D 08 mov ecx,dword ptr [pExcept]
00B4E242 51 push ecx
00B4E243 8B 55 2C mov edx,dword ptr [pMarkerRN]
00B4E246 52 push edx
00B4E247 E8 50 37 FF FF call _UnwindNestedFrames (0B4199Ch)
00B4E24C 8B 45 24 mov eax,dword ptr [pEntry]
00B4E24F 8B 08 mov ecx,dword ptr [eax]
00B4E251 51 push ecx
00B4E252 8B 55 18 mov edx,dword ptr [pFuncInfo]
00B4E255 52 push edx
00B4E256 8B 45 14 mov eax,dword ptr [pDC]
00B4E259 50 push eax
00B4E25A 8B 4D FC mov ecx,dword ptr [pEstablisher]
00B4E25D 51 push ecx
00B4E25E E8 94 40 FF FF call __FrameHandler3::FrameUnwindToState (0B422F7h)//处理展开流程
00B4E263 83 C4 10 add esp,10h
00B4E266 8B 55 24 mov edx,dword ptr [pEntry]
00B4E269 8B 42 04 mov eax,dword ptr [edx+4]
00B4E26C 83 C0 01 add eax,1
00B4E26F 50 push eax
00B4E270 8B 4D 18 mov ecx,dword ptr [pFuncInfo]
00B4E273 51 push ecx
00B4E274 8B 55 0C mov edx,dword ptr [pRN]
00B4E277 52 push edx
00B4E278 E8 B9 3D FF FF call __FrameHandler3::SetState (0B42036h)
00B4E27D 83 C4 0C add esp,0Ch
00B4E280 68 00 01 00 00 push 100h
00B4E285 8B 45 28 mov eax,dword ptr [CatchDepth]
00B4E288 50 push eax
00B4E289 8B 4D 1C mov ecx,dword ptr [pCatch]
00B4E28C 8B 51 0C mov edx,dword ptr [ecx+0Ch]
00B4E28F 52 push edx
00B4E290 8B 45 18 mov eax,dword ptr [pFuncInfo]
00B4E293 50 push eax
00B4E294 8B 4D 10 mov ecx,dword ptr [pContext]
00B4E297 51 push ecx
00B4E298 8B 55 FC mov edx,dword ptr [pEstablisher]
00B4E29B 52 push edx
00B4E29C 8B 45 08 mov eax,dword ptr [pExcept]
00B4E29F 50 push eax
00B4E2A0 E8 AB 0F 00 00 call CallCatchBlock (0B4F250h) //进入catch块进行处理,返回catch结束地址
00B4E2A5 83 C4 1C add esp,1Ch
00B4E2A8 89 45 F8 mov dword ptr [continuationAddress],eax
00B4E2AB 83 7D F8 00 cmp dword ptr [continuationAddress],0
00B4E2AF 74 0D je CatchIt<__FrameHandler3>+0BEh (0B4E2BEh)
00B4E2B1 8B 4D 0C mov ecx,dword ptr [pRN]
00B4E2B4 51 push ecx
00B4E2B5 8B 55 F8 mov edx,dword ptr [continuationAddress]
00B4E2B8 52 push edx
00B4E2B9 E8 0D 4E FF FF call _JumpToContinuation (0B430CBh) //跳转到catch块的结束
00B4E2BE 8B E5 mov esp,ebp
00B4E2C0 5D pop ebp
00B4E2C1 C3 ret
CallCatchBlock(EHExceptionRecord *, EHRegistrationNode *, _CONTEXT *, const _s_FuncInfo *, void *, int, unsigned long)
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // CallCatchBlock - continuation of CatchIt.
4 //
5 // This is separated from CatchIt because it needs to introduce an SEH/EH frame
6 // in case the catch block throws. This frame cannot be added until unwind of
7 // nested frames has been completed (otherwise this frame would be the first
8 // to go).
9
10 static __declspec(guard(ignore)) void *CallCatchBlock(
11 EHExceptionRecord *pExcept, // The exception thrown
12 EHRegistrationNode *pRN, // Dynamic info of function with catch
13 CONTEXT *pContext, // Context info
14 FuncInfo *pFuncInfo, // Static info of function with catch
15 void *handlerAddress, // Code address of handler
16 int CatchDepth, // How deeply nested in catch blocks
17 // are we?
18 unsigned long NLGCode // NLG destination code
19 ) {
20 EHTRACE_ENTER;
21
22 // Address where execution resumes after exception handling completed.
23 // Initialized to non-nullptr (value doesn't matter) to distinguish from
24 // re-throw in __finally.
25 void *continuationAddress = handlerAddress;
26
27 BOOL ExceptionObjectDestroyed = FALSE;
28
29 // The stack pointer at entry to the try must be saved, in case there is
30 // another try inside this catch. We'll restore it on our way out.
31 void *saveESP = PRN_STACK(pRN);
32
33 // Push this catch block's frame info on a linked list
34 FRAMEINFO FrameInfo;
35 FRAMEINFO *pFrameInfo = RENAME_EH_EXTERN(_CreateFrameInfo)(&FrameInfo, PER_PEXCEPTOBJ(pExcept));
36
37 // Save the current exception in case of a rethrow. Save the previous value
38 // on the stack, to be restored when the catch exits.
39 EHExceptionRecord *pSaveException = _pCurrentException;
40 CONTEXT *pSaveExContext = _pCurrentExContext;
41
42 _pCurrentException = pExcept;
43 _pCurrentExContext = pContext;
44
45 __try {
46 __try {
47 // Execute the handler as a funclet, whose return value is the
48 // address to resume execution.
49 continuationAddress = _CallCatchBlock2(pRN, pFuncInfo,
50 handlerAddress, CatchDepth, NLGCode);
51 } __except(EHTRACE_EXCEPT(ExFilterRethrow(exception_info()))) {
52 cxxReThrow=false;
53 // Here we are exiting the catch block on rethrow out of this
54 // catch block. To keep the order of destruction and construction
55 // same when the the rethrow was from function or was inline, here
56 // we unwind to the parent state for this catch.
57 UnwindMapEntry *pUnwindMap = pFuncInfo->pUnwindMap;
58 int cState = RENAME_EH_EXTERN(__FrameHandler3)::GetCurrentState(pRN, handlerAddress, pFuncInfo);
59 TryBlockMapEntry *pTryBlockMap = pFuncInfo->pTryBlockMap;
60 unsigned int i;
61 for (i = 0; i < pFuncInfo->nTryBlocks; i++) {
62 if (cState > pTryBlockMap[i].tryHigh &&
63 cState <= pTryBlockMap[i].catchHigh) {
64 cState = pTryBlockMap[i].tryHigh +1;
65 cState = pUnwindMap[cState].toState;
66 break;
67 }
68 }
69 RENAME_EH_EXTERN(__FrameHandler3)::FrameUnwindToState(pRN, nullptr, pFuncInfo, cState);
70 // If the handler threw a typed exception without exception info or
71 // exception object, then it's a re-throw, so return. Otherwise
72 // it's a new exception, which takes precedence over this one.
73 continuationAddress = nullptr;
74 }
75 } __finally {
76 EHTRACE_SAVE_LEVEL;
77 EHTRACE_FMT1("Executing __finally, %snormal termination", _abnormal_termination() ? "ab" : "");
78
79 // Restore the saved stack pointer, so the stack can be reset when
80 // we're done.
81 PRN_STACK(pRN) = saveESP;
82
83 // Pop this catch block's frame info
84 RENAME_EH_EXTERN(_FindAndUnlinkFrame)(pFrameInfo);
85
86 // Restore the 'current exception' for a possibly enclosing catch
87 _pCurrentException = pSaveException;
88 _pCurrentExContext = pSaveExContext;
89
90 // Destroy the original exception object if we're not exiting on a
91 // re-throw and the object isn't also in use by a more deeply nested
92 // catch. Note that the catch handles destruction of its parameter.
93
94 if (PER_IS_MSVC_EH(pExcept) && !ExceptionObjectDestroyed
95 && continuationAddress != nullptr
96 && _IsExceptionObjectToBeDestroyed(PER_PEXCEPTOBJ(pExcept)))
97 {
98 __DestructExceptionObject(pExcept, abnormal_termination() != FALSE);
99 }
100
101 EHTRACE_RESTORE_LEVEL(!!_abnormal_termination());
102 }
103 EHTRACE_EXIT;
104 return continuationAddress;
105 }
00B4F250 55 push ebp
00B4F251 8B EC mov ebp,esp
00B4F253 6A FE push 0FFFFFFFEh
00B4F255 68 A8 05 C2 00 push 0C205A8h
00B4F25A 68 90 C8 B4 00 push offset _except_handler4 (0B4C890h)
00B4F25F 64 A1 00 00 00 00 mov eax,dword ptr fs:[00000000h]
00B4F265 50 push eax
00B4F266 83 C4 C0 add esp,0FFFFFFC0h
00B4F269 53 push ebx
00B4F26A 56 push esi
00B4F26B 57 push edi
00B4F26C A1 04 20 C2 00 mov eax,dword ptr [__security_cookie (0C22004h)]
00B4F271 31 45 F8 xor dword ptr [ebp-8],eax
00B4F274 33 C5 xor eax,ebp
00B4F276 50 push eax
00B4F277 8D 45 F0 lea eax,[ebp-10h]
00B4F27A 64 A3 00 00 00 00 mov dword ptr fs:[00000000h],eax
00B4F280 89 65 E8 mov dword ptr [ebp-18h],esp
00B4F283 8B 45 18 mov eax,dword ptr [handlerAddress]
00B4F286 89 45 D8 mov dword ptr [continuationAddress],eax
00B4F289 C7 45 BC 00 00 00 00 mov dword ptr [ExceptionObjectDestroyed],0
00B4F290 B9 04 00 00 00 mov ecx,4
00B4F295 6B D1 FF imul edx,ecx,0FFFFFFFFh
00B4F298 8B 45 0C mov eax,dword ptr [pRN]
00B4F29B 8B 0C 10 mov ecx,dword ptr [eax+edx]
00B4F29E 89 4D CC mov dword ptr [saveESP],ecx
00B4F2A1 8B 55 08 mov edx,dword ptr [pExcept]
00B4F2A4 8B 42 18 mov eax,dword ptr [edx+18h]
00B4F2A7 50 push eax
00B4F2A8 8D 4D B0 lea ecx,[FrameInfo]
00B4F2AB 51 push ecx
00B4F2AC E8 C8 26 FF FF call __CreateFrameInfo (0B41979h)
00B4F2B1 83 C4 08 add esp,8
00B4F2B4 89 45 C8 mov dword ptr [pFrameInfo],eax
00B4F2B7 E8 C8 43 FF FF call ___vcrt_getptd (0B43684h)
00B4F2BC 8B 50 10 mov edx,dword ptr [eax+10h]
00B4F2BF 89 55 C4 mov dword ptr [pSaveException],edx
00B4F2C2 E8 BD 43 FF FF call ___vcrt_getptd (0B43684h)
00B4F2C7 8B 40 14 mov eax,dword ptr [eax+14h]
00B4F2CA 89 45 C0 mov dword ptr [pSaveExContext],eax
00B4F2CD E8 B2 43 FF FF call ___vcrt_getptd (0B43684h)
00B4F2D2 8B 4D 08 mov ecx,dword ptr [pExcept]
00B4F2D5 89 48 10 mov dword ptr [eax+10h],ecx
00B4F2D8 E8 A7 43 FF FF call ___vcrt_getptd (0B43684h)
00B4F2DD 8B 55 10 mov edx,dword ptr [pContext]
00B4F2E0 89 50 14 mov dword ptr [eax+14h],edx
00B4F2E3 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
00B4F2EA C7 45 B8 01 00 00 00 mov dword ptr [ebp-48h],1
00B4F2F1 C7 45 FC 01 00 00 00 mov dword ptr [ebp-4],1
00B4F2F8 8B 45 20 mov eax,dword ptr [NLGCode]
00B4F2FB 50 push eax
00B4F2FC 8B 4D 1C mov ecx,dword ptr [CatchDepth]
00B4F2FF 51 push ecx
00B4F300 8B 55 18 mov edx,dword ptr [handlerAddress]
00B4F303 52 push edx
00B4F304 8B 45 14 mov eax,dword ptr [pFuncInfo]
00B4F307 50 push eax
00B4F308 8B 4D 0C mov ecx,dword ptr [pRN]
00B4F30B 51 push ecx
00B4F30C E8 79 2E FF FF call _CallCatchBlock2 (0B4218Ah)
00B4F311 83 C4 14 add esp,14h
00B4F314 89 45 D8 mov dword ptr [continuationAddress],eax
00B4F317 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
00B4F31E E9 C7 00 00 00 jmp CallCatchBlock+19Ah (0B4F3EAh)
$LN24:
00B4F323 8B 55 EC mov edx,dword ptr [ebp-14h]
00B4F326 52 push edx
00B4F327 E8 E4 02 00 00 call ExFilterRethrow (0B4F610h)
00B4F32C 83 C4 04 add esp,4
$LN22:
00B4F32F C3 ret
$LN19:
00B4F330 8B 65 E8 mov esp,dword ptr [ebp-18h]
00B4F333 E8 4C 43 FF FF call ___vcrt_getptd (0B43684h)
00B4F338 C7 40 20 00 00 00 00 mov dword ptr [eax+20h],0
00B4F33F 8B 45 14 mov eax,dword ptr [pFuncInfo]
00B4F342 8B 48 08 mov ecx,dword ptr [eax+8]
00B4F345 89 4D D0 mov dword ptr [ebp-30h],ecx
00B4F348 8B 55 14 mov edx,dword ptr [pFuncInfo]
00B4F34B 52 push edx
00B4F34C 8B 45 18 mov eax,dword ptr [handlerAddress]
00B4F34F 50 push eax
00B4F350 8B 4D 0C mov ecx,dword ptr [pRN]
00B4F353 51 push ecx
00B4F354 E8 A9 29 FF FF call __FrameHandler3::GetCurrentState (0B41D02h)
00B4F359 83 C4 0C add esp,0Ch
00B4F35C 89 45 DC mov dword ptr [ebp-24h],eax
00B4F35F 8B 55 14 mov edx,dword ptr [pFuncInfo]
00B4F362 8B 42 10 mov eax,dword ptr [edx+10h]
00B4F365 89 45 D4 mov dword ptr [ebp-2Ch],eax
00B4F368 C7 45 E0 00 00 00 00 mov dword ptr [ebp-20h],0
00B4F36F EB 09 jmp CallCatchBlock+12Ah (0B4F37Ah)
00B4F371 8B 4D E0 mov ecx,dword ptr [ebp-20h]
00B4F374 83 C1 01 add ecx,1
00B4F377 89 4D E0 mov dword ptr [ebp-20h],ecx
00B4F37A 8B 55 14 mov edx,dword ptr [pFuncInfo]
00B4F37D 8B 45 E0 mov eax,dword ptr [ebp-20h]
00B4F380 3B 42 0C cmp eax,dword ptr [edx+0Ch]
00B4F383 73 41 jae CallCatchBlock+176h (0B4F3C6h)
00B4F385 6B 4D E0 14 imul ecx,dword ptr [ebp-20h],14h
00B4F389 8B 55 D4 mov edx,dword ptr [ebp-2Ch]
00B4F38C 8B 45 DC mov eax,dword ptr [ebp-24h]
00B4F38F 3B 44 0A 04 cmp eax,dword ptr [edx+ecx+4]
00B4F393 7E 2F jle CallCatchBlock+174h (0B4F3C4h)
00B4F395 6B 4D E0 14 imul ecx,dword ptr [ebp-20h],14h
00B4F399 8B 55 D4 mov edx,dword ptr [ebp-2Ch]
00B4F39C 8B 45 DC mov eax,dword ptr [ebp-24h]
00B4F39F 3B 44 0A 08 cmp eax,dword ptr [edx+ecx+8]
00B4F3A3 7F 1F jg CallCatchBlock+174h (0B4F3C4h)
00B4F3A5 6B 4D E0 14 imul ecx,dword ptr [ebp-20h],14h
00B4F3A9 8B 55 D4 mov edx,dword ptr [ebp-2Ch]
00B4F3AC 8B 44 0A 04 mov eax,dword ptr [edx+ecx+4]
00B4F3B0 83 C0 01 add eax,1
00B4F3B3 89 45 DC mov dword ptr [ebp-24h],eax
00B4F3B6 8B 4D DC mov ecx,dword ptr [ebp-24h]
00B4F3B9 8B 55 D0 mov edx,dword ptr [ebp-30h]
00B4F3BC 8B 04 CA mov eax,dword ptr [edx+ecx*8]
00B4F3BF 89 45 DC mov dword ptr [ebp-24h],eax
00B4F3C2 EB 02 jmp CallCatchBlock+176h (0B4F3C6h)
00B4F3C4 EB AB jmp CallCatchBlock+121h (0B4F371h)
00B4F3C6 8B 4D DC mov ecx,dword ptr [ebp-24h]
00B4F3C9 51 push ecx
00B4F3CA 8B 55 14 mov edx,dword ptr [pFuncInfo]
00B4F3CD 52 push edx
00B4F3CE 6A 00 push 0
00B4F3D0 8B 45 0C mov eax,dword ptr [pRN]
00B4F3D3 50 push eax
00B4F3D4 E8 1E 2F FF FF call __FrameHandler3::FrameUnwindToState (0B422F7h)
00B4F3D9 83 C4 10 add esp,10h
00B4F3DC C7 45 D8 00 00 00 00 mov dword ptr [continuationAddress],0
00B4F3E3 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
00B4F3EA C7 45 FC FE FF FF FF mov dword ptr [ebp-4],0FFFFFFFEh
00B4F3F1 C7 45 B8 00 00 00 00 mov dword ptr [ebp-48h],0
00B4F3F8 E8 05 00 00 00 call CallCatchBlock+1B2h (0B4F402h)
00B4F3FD E9 AC 00 00 00 jmp $LN17 (0B4F4AEh)
00B4F402 B9 04 00 00 00 mov ecx,4
00B4F407 6B D1 FF imul edx,ecx,0FFFFFFFFh
00B4F40A 8B 45 0C mov eax,dword ptr [pRN]
00B4F40D 8B 4D CC mov ecx,dword ptr [saveESP]
00B4F410 89 0C 10 mov dword ptr [eax+edx],ecx
00B4F413 8B 55 C8 mov edx,dword ptr [pFrameInfo]
00B4F416 52 push edx
00B4F417 E8 F2 49 FF FF call __FindAndUnlinkFrame (0B43E0Eh)
00B4F41C 83 C4 04 add esp,4
00B4F41F E8 60 42 FF FF call ___vcrt_getptd (0B43684h)
00B4F424 8B 4D C4 mov ecx,dword ptr [pSaveException]
00B4F427 89 48 10 mov dword ptr [eax+10h],ecx
00B4F42A E8 55 42 FF FF call ___vcrt_getptd (0B43684h)
00B4F42F 8B 55 C0 mov edx,dword ptr [pSaveExContext]
00B4F432 89 50 14 mov dword ptr [eax+14h],edx
00B4F435 8B 45 08 mov eax,dword ptr [pExcept]
00B4F438 81 38 63 73 6D E0 cmp dword ptr [eax],0E06D7363h
00B4F43E 75 6D jne CallCatchBlock+25Dh (0B4F4ADh)
00B4F440 8B 4D 08 mov ecx,dword ptr [pExcept]
00B4F443 83 79 10 03 cmp dword ptr [ecx+10h],3
00B4F447 75 64 jne CallCatchBlock+25Dh (0B4F4ADh)
00B4F449 8B 55 08 mov edx,dword ptr [pExcept]
00B4F44C 81 7A 14 20 05 93 19 cmp dword ptr [edx+14h],19930520h
00B4F453 74 18 je CallCatchBlock+21Dh (0B4F46Dh)
00B4F455 8B 45 08 mov eax,dword ptr [pExcept]
00B4F458 81 78 14 21 05 93 19 cmp dword ptr [eax+14h],19930521h
00B4F45F 74 0C je CallCatchBlock+21Dh (0B4F46Dh)
00B4F461 8B 4D 08 mov ecx,dword ptr [pExcept]
00B4F464 81 79 14 22 05 93 19 cmp dword ptr [ecx+14h],19930522h
00B4F46B 75 40 jne CallCatchBlock+25Dh (0B4F4ADh)
00B4F46D 83 7D BC 00 cmp dword ptr [ExceptionObjectDestroyed],0
00B4F471 75 3A jne CallCatchBlock+25Dh (0B4F4ADh)
00B4F473 83 7D D8 00 cmp dword ptr [continuationAddress],0
00B4F477 74 34 je CallCatchBlock+25Dh (0B4F4ADh)
00B4F479 8B 55 08 mov edx,dword ptr [pExcept]
00B4F47C 8B 42 18 mov eax,dword ptr [edx+18h]
00B4F47F 50 push eax
00B4F480 E8 45 38 FF FF call __IsExceptionObjectToBeDestroyed (0B42CCAh)
00B4F485 83 C4 04 add esp,4
00B4F488 85 C0 test eax,eax
00B4F48A 74 21 je CallCatchBlock+25Dh (0B4F4ADh)
00B4F48C 83 7D B8 00 cmp dword ptr [ebp-48h],0
00B4F490 74 06 je CallCatchBlock+248h (0B4F498h)
00B4F492 C6 45 E7 01 mov byte ptr [ebp-19h],1
00B4F496 EB 04 jmp CallCatchBlock+24Ch (0B4F49Ch)
00B4F498 C6 45 E7 00 mov byte ptr [ebp-19h],0
00B4F49C 0F B6 4D E7 movzx ecx,byte ptr [ebp-19h]
00B4F4A0 51 push ecx
00B4F4A1 8B 55 08 mov edx,dword ptr [pExcept]
00B4F4A4 52 push edx
00B4F4A5 E8 D6 2C FF FF call ___DestructExceptionObject (0B42180h)
00B4F4AA 83 C4 08 add esp,8
$LN23:
00B4F4AD C3 ret
00B4F4AE 8B 45 D8 mov eax,dword ptr [continuationAddress]
00B4F4B1 8B 4D F0 mov ecx,dword ptr [ebp-10h]
00B4F4B4 64 89 0D 00 00 00 00 mov dword ptr fs:[0],ecx
00B4F4BB 59 pop ecx
00B4F4BC 5F pop edi
00B4F4BD 5E pop esi
00B4F4BE 5B pop ebx
00B4F4BF 8B E5 mov esp,ebp
00B4F4C1 5D pop ebp
00B4F4C2 C3 ret
抛出异常(throw)
ThrowInfo
//
// ThrowInfo - information describing the thrown object, statically built
// at the throw site.
//
// pExceptionObject (the dynamic part of the throw; see below) is always a
// reference, whether or not it is logically one. If 'isSimpleType' is true,
// it is a reference to the simple type, which is 'size' bytes long. If
// 'isReference' and 'isSimpleType' are both false, then it's a UDT or
// a pointer to any type (i.e. pExceptionObject points to a pointer). If it's
// a pointer, copyFunction is NULL, otherwise it is a pointer to a copy
// constructor or copy constructor closure.
//
// The pForwardCompat function pointer is intended to be filled in by future
// versions, so that if say a DLL built with a newer version (say C10) throws,
// and a C9 frame attempts a catch, the frame handler attempting the catch (C9)
// can let the version that knows all the latest stuff do the work.
//
typedef const struct _s_ThrowInfo {
unsigned int attributes; // Throw Info attributes (Bit field)
PMFN pmfnUnwind; // Destructor to call when exception has been handled or aborted
#if _EH_RELATIVE_TYPEINFO && !defined(BUILDING_C1XX_FORCEINCLUDE)
int pForwardCompat; // Image relative offset of Forward compatibility frame handler
int pCatchableTypeArray; // Image relative offset of CatchableTypeArray
#else
int (__cdecl * pForwardCompat)(...); // Forward compatibility frame handler
CatchableTypeArray* pCatchableTypeArray; // Pointer to list of pointers to types
#endif
} ThrowInfo;
_CxxThrowException
// _CxxThrowException - implementation of 'throw'
//
// Description:
// Builds the NT Exception record, and calls the NT runtime to initiate
// exception processing.
//
// Why is pThrowInfo defined as _ThrowInfo? Because _ThrowInfo is secretly
// snuck into the compiler, as is the prototype for _CxxThrowException, so
// we have to use the same type to keep the compiler happy.
//
// Another result of this is that _CRTIMP can't be used here. Instead, we
// synthesisze the -export directive below.
//
// Returns:
// NEVER. (until we implement resumable exceptions, that is)
//
extern "C" __declspec(noreturn) void __stdcall
_CxxThrowException(
void* pExceptionObject, // The object thrown
_ThrowInfo* pThrowInfo // Everything we need to know about it
) {
EHTRACE_ENTER_FMT1("Throwing object @ 0x%p", pExceptionObject); static const EHExceptionRecord ExceptionTemplate = { // A generic exception record
EH_EXCEPTION_NUMBER, // Exception number
EXCEPTION_NONCONTINUABLE, // Exception flags (we don't do resume)
nullptr, // Additional record (none)
nullptr, // Address of exception (OS fills in)
EH_EXCEPTION_PARAMETERS, // Number of parameters
{ EH_MAGIC_NUMBER1, // Our version control magic number
nullptr, // pExceptionObject
nullptr,
#if EH_EXCEPTION_PARAMETERS == 4
nullptr // Image base of thrown object
#endif
} // pThrowInfo
};
EHExceptionRecord ThisException = ExceptionTemplate; // This exception ThrowInfo* pTI = (ThrowInfo*)pThrowInfo;
if (pTI && (THROW_ISWINRT( (*pTI) ) ) )
{
ULONG_PTR *exceptionInfoPointer = *reinterpret_cast<ULONG_PTR**>(pExceptionObject);
exceptionInfoPointer--; // The pointer to the ExceptionInfo structure is stored sizeof(void*) infront of each WinRT Exception Info. WINRTEXCEPTIONINFO** ppWei = reinterpret_cast<WINRTEXCEPTIONINFO**>(exceptionInfoPointer);
pTI = (*ppWei)->throwInfo; (*ppWei)->PrepareThrow( ppWei );
} //
// Fill in the blanks:
//
ThisException.params.pExceptionObject = pExceptionObject;
ThisException.params.pThrowInfo = pTI;
#if _EH_RELATIVE_TYPEINFO
PVOID ThrowImageBase = RtlPcToFileHeader((PVOID)pTI, &ThrowImageBase);
ThisException.params.pThrowImageBase = ThrowImageBase;
#endif //
// If the throw info indicates this throw is from a pure region,
// set the magic number to the Pure one, so only a pure-region
// catch will see it.
//
// Also use the Pure magic number on Win64 if we were unable to
// determine an image base, since that was the old way to determine
// a pure throw, before the TI_IsPure bit was added to the FuncInfo
// attributes field.
//
if (pTI != nullptr)
{
if (THROW_ISPURE(*pTI))
{
ThisException.params.magicNumber = EH_PURE_MAGIC_NUMBER1;
}
#if _EH_RELATIVE_TYPEINFO
else if (ThrowImageBase == nullptr)
{
ThisException.params.magicNumber = EH_PURE_MAGIC_NUMBER1;
}
#endif
} //
// Hand it off to the OS:
// EHTRACE_EXIT;
RaiseException( ThisException.ExceptionCode,
ThisException.ExceptionFlags,
ThisException.NumberParameters,
(PULONG_PTR)&ThisException.params );
}
函数_InternalCxxFrameHandler的主要功能是完成异常类型的检查,最终调用查找try块和catch块的函数FindHandler。这个函数是完成异常处理的关键部分,完成了查找try块中抛出的异常对应的catch语句块的过程