why drwtson32 fails to generate the dump for 2nd C++ exception!
原贴地址:
http://eparg.spaces.msn.com/blog/cns!59BFC22C0E7E1A76!1213.entry
原贴时间:
2006-06-21
原贴作者:
eparg
int _tmain(int argc, _TCHAR* argv[])
{
throw 1;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
int *p=0;
*p=0;
return 0;
}
Use “drwtsn32.exe –i” to register Dr. Watson and execute above code. For unhandled C++ exception, Dr. Watson fails to generate the dump. For unhandled AV, the dump is created fine.
If we change the AeDebug/Debugger in registry to use windbg as the following, the dump is created fine even for unhandled C++ exception.
C:/debuggers/windbg.exe -p %ld -e %ld -c ".dump /mfh C:/myfile.dmp ;q"
Why the drwtson32 ignores the dump for unhandled C++ exception?
With almost 6 hours research, got the answer, here are the steps:
My 1st step is to check if drwtson32 is launched. In AeDebug, I set Debugger as drwtson32 and set Auto to 0. I also add drwtson32.exe key in Image File Execution Options, and set the debugger to windbg.exe.
When the C++ EH occurs, windbg gets launched and attached to drwtson32. It means the unhandled C++ EH triggers drwtson32 successfully.
The next step is to check why drwtson32 fails to write the dump. Since I’ve no idea about the code logic of drwtson32, I switch to AV sample as research.
The AV triggers drwtson32 with windbg attached. I set bp on CreateFile API and it stops on the following call stack:
kernel32!CreateFileW
dbgeng!WriteDumpFile+0x2c]
dbgeng!DebugClient::WriteDumpFileInternal+0x6e
dbgeng!DebugClient::WriteDumpFile2+0x34
drwtsn32!CreateDumpFile+0xda
drwtsn32!DispatchDebugEventThread+0x1c7
kernel32!BaseThreadStart+0x34
Now I know the dump writing logic is in DispatchDebugEventThread function. I restart with AV Sample and go through the DispatchDebugEventThread to understand the logic. The function waits for debugging event, and handles it. For DEBUG_EVENT_EXCEPTION event, it queries for the ExceptionRecord. For the AV sample, when it gets the AV ExceptionRecord, it creates the dump.
With above understanding, I switch back to test The C++ EH sample. The DispatchDebugEventThread function is also invoked. However, drwtson32 does not get the C++ EH ExceptionRecord so there is no dump created.
Ok, our next question is, why there is no C++ EH ExceptionRecord passed in.
Just some days ago, I posted “How to debug UnhandleExceptionHandler”. The handler should be the last chain to do with the unhandled exception. So I decide to use my own handler as a test. When my handler returns 0, no matter AV or C++ EH, drwtson32 saves the dump correctly! When my handler returns 1, the debugger in AeDebug is not triggered at all.
Above test shows that the problem is somehow related to the UnhandleExceptionHandler. Since CRT uses special handler to deal with C++ EH, I decide to trace the CRT handler.
Since windbg is convenient, I change the AeDebug to use windbg. When windbg is triggered, it shows the following two callstacks for the two samples:
0012f864 7c822114 ntdll!KiFastSystemCallRet
0012f868 77e99c32 ntdll!ZwWaitForMultipleObjects+0xc
0012fb30 78138c06 kernel32!UnhandledExceptionFilter+0x746
0012fb50 0040119e MSVCR80!_XcptFilter+0x6a
0012fb5c 7813dfc4 win32!__tmainCRTStartup+0x137
0012fb70 7813bc8d MSVCR80!_EH4_CallFilterFunc+0x12
0012fb98 00401644 MSVCR80!_except_handler4_common+0x8d
0012fbb4 7c82eeb2 win32!_except_handler4+0x1f
0012fbd8 7c82ee84 ntdll!ExecuteHandler2+0x26
0012fc80 7c82ecc6 ntdll!ExecuteHandler+0x24
0012fc80 00401002 ntdll!KiUserExceptionDispatcher+0xe
0012ff7c 00401176 win32!main+0x2
0012ffc0 77e523cd win32!__tmainCRTStartup+0x10f
0012fff0 00000000 kernel32!BaseProcessStart+0x23
0012f210 7c822114 ntdll!KiFastSystemCallRet
0012f214 77e99c32 ntdll!ZwWaitForMultipleObjects+0xc
0012f4dc 7813adda kernel32!UnhandledExceptionFilter+0x746
0012f814 781346b6 MSVCR80!abort+0xeb
0012f844 7815e4ae MSVCR80!terminate+0x4d
0012f84c 77e995f7 MSVCR80!__CxxUnhandledExceptionFilter+0x39
0012faa4 78138c06 kernel32!UnhandledExceptionFilter+0xac
0012fac4 004011f9 MSVCR80!_XcptFilter+0x6a
0012fad0 7813dfc4 win32!__tmainCRTStartup+0x137
0012fae4 7813bc8d MSVCR80!_EH4_CallFilterFunc+0x12
0012fb0c 00401754 MSVCR80!_except_handler4_common+0x8d
0012fb28 7c82eeb2 win32!_except_handler4+0x1f
0012fb4c 7c82ee84 ntdll!ExecuteHandler2+0x26
0012fbf4 7c82eda4 ntdll!ExecuteHandler+0x24
0012fed4 77e55dea ntdll!RtlRaiseException+0x3d
0012ff34 78158dc3 kernel32!RaiseException+0x53
0012ff6c 00401018 MSVCR80!_CxxThrowException+0x46
0012ff7c 004011d1 win32!main+0x18
0012ffc0 77e523cd win32!__tmainCRTStartup+0x10f
0012fff0 00000000 kernel32!BaseProcessStart+0x23
The difference is the kernel32!UnhandledExceptionFilter reenters for C++ EH. The 2nd call of kernel32!UnhandledExceptionFilter is invoked by MSVCR80!abort.
MSVCR80!abort builds Exception record on stack and set ExceptionRecord.ExceptionCode to STATUS_FATAL_APP_EXIT. After that it clears the CRT CxxUnhandledExceptionFilte and calls kernel32!UnhandledExceptionFilter with the new created exception record. It seems the new built ExceptionRecord hides the original C++ EH, and prevents the C++ EH to pass to drwtson32.
With above information, I tried VC6 and VS2003 with the same samples. The drwtson32 is even not triggered with the C++ EH sample. By understanding the logic of the CxxUnhandledExceptionFilter and abort function, the earlier version before VC8 terminates the process in CRT handler directly so there is no reentry of kernel32!UnhandledExceptionFilter to trigger the debugger set in AeDebug.
As a summary, drwtson32 is not a reliable tool to obtain the dump file. We can try the following alternative:
1. Use IIS DebugDiag
2. In AeDebug, change debugger setting to the following to use windbg instead:
C:/debuggers/windbg -p %ld -e %ld -c ".dump /mfh C:/myfile.dmp ;q"
3. In Image File Execution Options setting, create a key with the target exe name. Change the debugger to the following:
C:/Debuggers/autodump.bat
Use the following as the bat file:
cscript.exe C:/Debuggers/adplus.vbs -crash -o C:/dumps -quiet -sc %1