Windbg Dump Generated programmatically can't be Debugged
I have a simple program:
int ExecuteCommand(wchar_t* commandLine)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL bRet;
DWORD lpExitCode;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
bRet = CreateProcess(
NULL, // pointer to name of executable module
commandLine, // pointer to command line string
NULL, // process security attributes
NULL, // thread security attributes
FALSE, // handle inheritance flag
NORMAL_PRIORITY_CLASS, // creation flags
NULL, // pointer to new environment block
NUL开发者_Python百科L, // pointer to current directory name
&si, // pointer to STARTUPINFO
&pi // pointer to PROCESS_INFORMATION
);
if(bRet) WaitForSingleObject(pi.hProcess, INFINITE); // wait for process to finish
GetExitCodeProcess(pi.hProcess, &lpExitCode);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return lpExitCode;
}
void CreateCoreDump()
{
wchar_t buffer[256];
wsprintf(buffer, _T("windbg -p %d -c \".dump /mfh /u C:\\Tmp\\crashdump.dmp\""), GetCurrentProcessId());
ExecuteCommand(buffer);
}
DWORD ExceptionFilter()
{
CreateCoreDump();
return EXCEPTION_CONTINUE_SEARCH;
}
int _tmain(int argc, _TCHAR* argv[])
{
__try
{
int* p = NULL;
*p = 100;
}
__except(ExceptionFilter())
{
}
return 0;
}
It will generate a core dump when there is an exception, using function CreateCoreDump. Although the dump file could be generated successfully, it seems useless:
If I open this dump file using windbg, there is nothing in call stack!!!But, if I debug this application directly in windbg, and set breakpoint at the line of calling CreateCoreDump, and then run windbg command:
.dump /mfh C:\Tmp\mydump.dmp
Open this dump file with WinDbg, I can see the full call stack.
Did I do something wrong, either in generating the dump file, or debugging the dump file using windbg?
When you attach the debugger after the exception happens, the debugger does not see the exception event. It creates a thread that has a breakpoint so the stack on that thread looks something like this:
0:001> kc
Call Site
ntdll!DbgBreakPoint
ntdll!DbgUiRemoteBreakin+0x38
kernel32!BaseThreadInitThunk+0xd
ntdll!RtlUserThreadStart+0x1d
If you manually set the current thread to thread 0 (use ~0s
) you will see your stack
0:001> ~0s
ntdll!ZwWaitForSingleObject+0xa:
00000000`76e5135a c3 ret
0:000> kc
Call Site
ntdll!ZwWaitForSingleObject
KERNELBASE!WaitForSingleObjectEx
tmp!ExceptionFilter
tmp!main$filt$0
ntdll!__C_specific_handler
ntdll!RtlpExecuteHandlerForException
ntdll!RtlDispatchException
ntdll!KiUserExceptionDispatch
tmp!main
tmp!__mainCRTStartup
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
When you start your program under the debugger two things happen, first, there is only one thread, and second the debugger knows about the exception so it will print something like this:
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
which tells you that you need to use the .ecxr
commmand to get to the interesting thread. In this case you do not need to because the current debugger thread is already the one you want.
You have to add the exception record to the dump. For instance, I changed your sample to retrieve the exception information in the filter and pass it on the command line when generating the dump.
void CreateCoreDump(LPEXCEPTION_POINTERS p)
{
wchar_t buffer[256];
// I used the command line debugger, cdb, and added a "qd" command for it to exit after dumping.
wsprintf(buffer, _T("cdb.exe -p %d -c \".dump /mfh /u /xt 0x%x /xp 0x%p C:\\Tmp\\crashdump.dmp\";qd"), GetCurrentProcessId(), GetCurrentThreadId(), p);
ExecuteCommand(buffer);
}
DWORD ExceptionFilter(LPEXCEPTION_POINTERS p)
{
CreateCoreDump(p);
return EXCEPTION_CONTINUE_SEARCH;
}
int _tmain(int argc, _TCHAR* argv[])
{
__try
{
int* p = NULL;
*p = 100;
}
__except(ExceptionFilter(GetExceptionInformation()))
{
}
return 0;
}
Then when you open the dump in windgb, the debugger knows about the exception event. You can use .ecxr
to set the current thread and stack at the exception point.
0:000> .ecxr
eax=00000000 ebx=00000000 ecx=6ec4471c edx=00000000 esi=00000001 edi=010c337c
eip=010c108b esp=0038f5e8 ebp=0038f818 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
test!wmain+0x14:
010c108b c70064000000 mov dword ptr [eax],64h ds:002b:00000000=????????
0:000> kc
test!wmain
test!__tmainCRTStartup
kernel32!BaseThreadInitThunk
ntdll!__RtlUserThreadStart
ntdll!_RtlUserThreadStart
精彩评论