Bootstrap

Window端Qt Create dmp的生成与解析

资源下载

Window端Qt Create dmp的生成与解析

生成

.pro 中的配置

在 pro中加入以下内容,否在在 release下 无法生成pdb

QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO /DEBUG


#加入调试信息
QMAKE_CFLAGS_RELEASE += -g
QMAKE_CXXFLAGS_RELEASE += -g
#禁止优化
QMAKE_CFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE -= -O2
#release在最后link时默认有"-s”参数,表示"Omit all symbol information from the output file",因此要去掉该参数
QMAKE_LFLAGS_RELEASE = -mthreads #-Wl

LIBS += -lDbgHelp
在main 函数 添加如下代码
头文件
#ifdef Q_OS_WIN
    #include <windows.h>
    #include <dbghelp.h>
#endif

dmp文件的存儲方法
static LONG WINAPI exceptionCallback(struct _EXCEPTION_POINTERS* exceptionInfo)
{
    QCoreApplication *app = QApplication::instance();

    QString savePath = app->applicationDirPath() + "dump/";
    qDebug()<<"save path :"<<savePath;
    QDir dir(savePath);
    if (!dir.exists() && !dir.mkpath(savePath)) {
        app->exit(E_UNEXPECTED);
        return EXCEPTION_EXECUTE_HANDLER;
    }

    savePath.append("assit_");
    savePath.append(QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"));
    savePath.append(".dmp");

    HANDLE dump = CreateFileW(savePath.toStdWString().c_str(), GENERIC_WRITE,
        0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == dump) {
        app->exit(E_UNEXPECTED);
        return EXCEPTION_EXECUTE_HANDLER;
    }

    MINIDUMP_EXCEPTION_INFORMATION miniDumpExceptionInfo;
    miniDumpExceptionInfo.ExceptionPointers = exceptionInfo;
    miniDumpExceptionInfo.ThreadId = GetCurrentThreadId();
    miniDumpExceptionInfo.ClientPointers = TRUE;
    DWORD idProcess = GetCurrentProcessId();
    MiniDumpWriteDump(GetCurrentProcess(), idProcess, dump,
        MiniDumpNormal, &miniDumpExceptionInfo, NULL, NULL);

    CloseHandle(dump);

    app->exit(E_UNEXPECTED);
    return EXCEPTION_EXECUTE_HANDLER;
}
mian中調用
#ifdef Q_OS_WIN
    SetUnhandledExceptionFilter(exceptionCallback);
#endif
測試方法
void crash() { volatile int* a = (int*)(NULL); *a = 1; }

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);


#ifdef Q_OS_WIN
    SetUnhandledExceptionFilter(exceptionCallback);
#endif

    MainWindow w;
    w.show();

    crash();

    return a.exec();
}
完整代碼
#include "mainwindow.h"
#include <QApplication>

#include <QDir>
#include <qdebug.h>
#include <QDateTime>
#include <QFile>
#include <qglobal.h>

#ifdef Q_OS_WIN
#include <windows.h>
#include <dbghelp.h>
#endif


#ifdef Q_OS_WIN
static LONG WINAPI exceptionCallback(struct _EXCEPTION_POINTERS* exceptionInfo)
{
    QCoreApplication *app = QApplication::instance();

    QString savePath = app->applicationDirPath() + "dump/";
    qDebug()<<"save path :"<<savePath;
    QDir dir(savePath);
    if (!dir.exists() && !dir.mkpath(savePath)) {
        app->exit(E_UNEXPECTED);
        return EXCEPTION_EXECUTE_HANDLER;
    }

    savePath.append("assit_");
    savePath.append(QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"));
    savePath.append(".dmp");

    HANDLE dump = CreateFileW(savePath.toStdWString().c_str(), GENERIC_WRITE,
        0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == dump) {
        app->exit(E_UNEXPECTED);
        return EXCEPTION_EXECUTE_HANDLER;
    }

    MINIDUMP_EXCEPTION_INFORMATION miniDumpExceptionInfo;
    miniDumpExceptionInfo.ExceptionPointers = exceptionInfo;
    miniDumpExceptionInfo.ThreadId = GetCurrentThreadId();
    miniDumpExceptionInfo.ClientPointers = TRUE;
    DWORD idProcess = GetCurrentProcessId();
    MiniDumpWriteDump(GetCurrentProcess(), idProcess, dump,
        MiniDumpNormal, &miniDumpExceptionInfo, NULL, NULL);

    CloseHandle(dump);

    app->exit(E_UNEXPECTED);
    return EXCEPTION_EXECUTE_HANDLER;
}
#endif



void crash() { volatile int* a = (int*)(NULL); *a = 1; }

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);


#ifdef Q_OS_WIN
    SetUnhandledExceptionFilter(exceptionCallback);
#endif

    MainWindow w;
    w.show();

    crash();

    return a.exec();
}

運行之後,我們發現編譯生成的目錄結構如下 可以看到在debugdump 目錄下生成了.dmp

│ .qmake.stash
│ contents.txt
│ list.bat
│ Makefile
│ Makefile.Debug
│ Makefile.Release
│ ui_mainwindow.h

├─debug
│ Demo.exe
│ main.o
│ mainwindow.o
│ moc_mainwindow.cpp
│ moc_mainwindow.o
│ moc_predefs.h

├─debugdump
│ assit_20200408095624048.dmp

└─release

解析

在Window工具目錄下會有如下文件:

D:/Project/DumTools/
	| cv2pdb.exe
    | dbg_amd64.msi
生成pdb

將編譯運行的程序以及dmp文件拷貝到該文件目錄下,打開終端輸入下入命令

./CV2pdb.exe Demo.exe

之後則會在該目錄下生成pdb,我們會發現文件結構如下:

D:/Project/DumTools/
	| assit_20200408100730098.dmp
	| cv2pdb.exe
	| dbg_amd64.msi
	| Demo.exe
	| Demo.pdb
安裝windbg.exe

直接點擊該目錄下的dbg_amd64.msi 安裝完成之後,在所按章的目錄下會有一個 windbg.exe 程序。 打開該程序並完成以下配置

依次完成如下配置

打開File 需要完成 Symbol File Path 、Source File Path、Image File Path 的配置

1、Symbol File Path :這裏就是加載pdb文件的路徑,我們直接使用

D:/Project/DumTools/

2、 Source File Path: 加载程序代码 存放的路径(注意切回發佈版本的代碼

D:/Project/Demo/

3、Image File Path: 加載exe 存放的路徑

D:/Project/DumTools/

4、選擇Open Crash Dump 導入生成的dmp文件

5、 输入命令 !analyze -v ,等待几秒后会打印出错误信息

最終完整的解析信息如下:


Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.


Loading Dump File [D:\tiertime_window\window\assit_20200408100730098.dmp]
User Mini Dump File: Only registers, stack and portions of memory are available

WARNING: Minidump contains unknown stream type 0x15
WARNING: Minidump contains unknown stream type 0x16
Symbol search path is: D:\tiertime_window\window
Executable search path is: D:\tiertime_window\window
Windows 7 Version 18362 MP (4 procs) Free x64
Product: WinNt, suite: SingleUserTS
Machine Name:
Debug session time: Wed Apr  8 10:07:30.000 2020 (UTC + 8:00)
System Uptime: not available
Process Uptime: 0 days 0:00:07.000
................................................................
..........................
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(4e04.49f0): Access violation - code c0000005 (first/second chance not available)
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll - 
ntdll!ZwGetContextThread+0x14:
00007ffa`2a1dde54 c3              ret
0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

*** ERROR: Symbol file could not be found.  Defaulted to export symbols for kernel32.dll - 
***** OS symbols are WRONG. Please fix symbols to do analysis.

*************************************************************************
***                                                                   ***
***                                                                   ***
***    Your debugger is not using the correct symbols                 ***
***                                                                   ***
***    In order for this command to work properly, your symbol path   ***
***    must point to .pdb files that have full type information.      ***
***                                                                   ***
***    Certain .pdb files (such as the public OS symbols) do not      ***
***    contain the required information.  Contact the group that      ***
***    provided you with these symbols if you need this command to    ***
***    work.                                                          ***
***                                                                   ***
***    Type referenced: nt!IMAGE_NT_HEADERS32                         ***
***                                                                   ***
*************************************************************************
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ole32.dll - 
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for Qt5Core.dll - 
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for combase.dll - 
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for SogouPY.ime - 
Failed calling InternetOpenUrl, GLE=12029

FAULTING_IP: 
Demo!crash+14 [..\Demo\main.cpp @ 56]
00000000`0040191b c70001000000    mov     dword ptr [rax],1

EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 000000000040191b (Demo!crash+0x0000000000000014)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 0000000000000001
   Parameter[1]: 0000000000000000
Attempt to write to address 0000000000000000

PROCESS_NAME:  Demo.exe

ADDITIONAL_DEBUG_TEXT:  
Use '!findthebuild' command to search for the target build information.
If the build information is available, run '!findthebuild -s ; .reload' to set symbol path and load symbols.

MODULE_NAME: Demo

FAULTING_MODULE: 00007ffa2a140000 ntdll

DEBUG_FLR_IMAGE_TIMESTAMP:  5e8d31d9

ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - 0x%p

EXCEPTION_PARAMETER1:  0000000000000001

EXCEPTION_PARAMETER2:  0000000000000000

WRITE_ADDRESS:  0000000000000000 

FOLLOWUP_IP: 
Demo!crash+14 [..\Demo\main.cpp @ 56]
00000000`0040191b c70001000000    mov     dword ptr [rax],1

MOD_LIST: <ANALYSIS/>

FAULTING_THREAD:  00000000000049f0

BUGCHECK_STR:  APPLICATION_FAULT_NULL_POINTER_WRITE_WRONG_SYMBOLS

PRIMARY_PROBLEM_CLASS:  NULL_POINTER_WRITE

DEFAULT_BUCKET_ID:  NULL_POINTER_WRITE

LAST_CONTROL_TRANSFER:  from 0000000000401994 to 000000000040191b

STACK_TEXT:  
00000000`0073fce0 00000000`00401994 : 00000000`0073fd20 00000000`00000000 ffffffff`00000056 00000000`00070000 : Demo!crash+0x14 [..\Demo\main.cpp @ 56]
00000000`0073fd00 00000000`00403550 : 00000000`00000001 00000000`001c6f60 00000000`02c02490 00000000`00000056 : Demo!qMain+0x6c [..\Demo\main.cpp @ 72]
00000000`0073fd90 00000000`004013c7 : 00000000`00000000 00000000`00000056 00000000`00409970 00000000`00000000 : Demo!GLOBAL__sub_I.00101__ZN10MainWindow18qt_static_metacallEP7QObjectN11QMetaObject4CallEiPPv+0x18da
00000000`0073fe30 00000000`004014cb : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : Demo!public_all+0x3c7
00000000`0073ff00 00007ffa`29347bd4 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : Demo!public_all+0x4cb
00000000`0073ff30 00007ffa`2a1aced1 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0x14
00000000`0073ff60 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21


STACK_COMMAND:  ~0s; .ecxr ; kb

FAULTING_SOURCE_CODE:  
    52: }
    53: #endif
    54: 
    55: 
>   56: 
    57: void crash() { volatile int* a = (int*)(NULL); *a = 1; }
    58: 
    59: int main(int argc, char *argv[])
    60: {
    61:     QApplication a(argc, argv);


SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  demo!crash+14

FOLLOWUP_NAME:  MachineOwner

IMAGE_NAME:  Demo.exe

BUCKET_ID:  WRONG_SYMBOLS

FAILURE_BUCKET_ID:  NULL_POINTER_WRITE_c0000005_Demo.exe!crash

WATSON_STAGEONE_URL:  http://watson.microsoft.com/StageOne/Demo_exe/0_0_0_0/5e8d31d9/Demo_exe/0_0_0_0/5e8d31d9/c0000005/0000191b.htm?Retriage=1

Followup: MachineOwner
---------


可以看到 具體的崩潰代碼行 以及具體的方法。

;