Windbg Dump, созданный программно, не может быть отлажен - PullRequest
1 голос
/ 25 августа 2011

У меня есть простая программа:

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
        NULL, // 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;
}

Она создаст дамп ядра при возникновении исключения, используя функцию CreateCoreDump.Хотя файл дампа может быть сгенерирован успешно, он кажется бесполезным:
Если я открою этот файл дампа с помощью windbg, в стеке вызовов ничего не останется !!!

Но если яотладить это приложение непосредственно в windbg, установить точку останова в строке вызова CreateCoreDump, а затем запустить команду windbg:

.dump /mfh C:\Tmp\mydump.dmp

Открыть этот файл дампа с помощью WinDbg, я вижу полный стек вызовов.

Я что-то не так сделал, генерируя файл дампа или отлаживая файл дампа с помощью windbg?

Ответы [ 2 ]

2 голосов
/ 25 августа 2011

Когда вы присоединяете отладчик после возникновения исключения, отладчик не видит событие исключения. Он создает поток с точкой останова, поэтому стек в этом потоке выглядит примерно так:

0:001> kc
Call Site
ntdll!DbgBreakPoint
ntdll!DbgUiRemoteBreakin+0x38
kernel32!BaseThreadInitThunk+0xd
ntdll!RtlUserThreadStart+0x1d

Если вы вручную установите текущую нить в нить 0 (используйте ~0s), вы увидите свой стек

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

Когда вы запускаете вашу программу под отладчиком, происходят две вещи: во-первых, существует только один поток, а во-вторых, отладчик знает об исключении, поэтому он напечатает что-то вроде этого:

This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.

, который говорит вам, что вам нужно использовать команду .ecxr, чтобы перейти к интересному потоку. В этом случае вам это не нужно, поскольку текущий поток отладчика уже тот, который вам нужен.

1 голос
/ 30 августа 2011

Вы должны добавить запись об исключении в дамп. Например, я изменил ваш пример, чтобы получить информацию об исключении в фильтре и передать ее в командной строке при создании дампа.

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

Затем, когда вы открываете дамп в windgb, отладчик узнает о событии исключения. Вы можете использовать .ecxr, чтобы установить текущий поток и стек в точке исключения.

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