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 - 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