VS2010下使用dmp檔案和pdb檔案定位到dll中崩潰位置的方法
2018-01-15 建立人:Ruo_Xiao
郵箱:xclsoftware@163.com
一、基礎連結
http://blog.csdn.net/itworld123/article/details/79041500
http://blog.csdn.net/itworld123/article/details/79047788
http://blog.csdn.net/itworld123/article/details/79061296
二、原始碼
1、DLL程式碼(工程1)
#pragma once
#ifdef __XError_Export__
#define __XError_DLL__ _declspec(dllexport)
#else
#define __XError_DLL__ _declspec(dllimport)
#endif
class __XError_DLL__ XError
{
public:
XError(void);
~XError(void);
public:
void ErrorFun(int *p);
};
--------------------------------------------------------------
void XError::ErrorFun(int *p)
{
p[2] = 10; //崩潰位置,原始碼中顯示第16行
}
2、測試程式碼(工程2)
#include "stdafx.h"
#include "source/ErrorDLL/XError.h"
#include <windows.h>
#include <DbgHelp.h>
#pragma comment(lib,"Dbghelp.lib")
static long __stdcall CrashInfocallback(_EXCEPTION_POINTERS *pexcp);
int _tmain(int argc, _TCHAR* argv[])
{
::SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)CrashInfocallback);
XError X;
int *p = NULL;
X.ErrorFun(p); //呼叫dll中含有崩潰程式碼的函式,原始碼第19行
return 0;
}
long __stdcall CrashInfocallback(_EXCEPTION_POINTERS *pexcp)
{
//建立 Dump 檔案
HANDLE hDumpFile = ::CreateFile(
L"MEMORY.DMP",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if( hDumpFile != INVALID_HANDLE_VALUE)
{
//Dump資訊
MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
dumpInfo.ExceptionPointers = pexcp;
dumpInfo.ThreadId = GetCurrentThreadId();
dumpInfo.ClientPointers = TRUE;
//寫入Dump檔案內容
::MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hDumpFile,
MiniDumpNormal,
&dumpInfo,
NULL,
NULL
);
}
return 0;
}
三、要點
- PE檔案中包含了對應的pdb檔案的校驗碼和路徑,二者必須和pdb檔案保持一致,即:PE檔案和pdb檔案必須同時生成,pdb檔案必須在PE檔案中記錄的路徑下。
- pdb檔案中記錄了原始碼的位置,若該位置下有原始碼,則定位時不僅可以定位到行號而且還能顯示對應的原始碼,反之只能顯示行號。通常情況下不方便提供原始碼,故pdb檔案必須在所屬的PE檔案下。
四、定位dll檔案中崩潰位置行號步驟
1、修改工程1的pdb檔案生成目錄,如下所示。
專案 -> 工程名 + 屬性,按照下圖修改
將“生成程式資料庫檔案”改為上圖所示,意思是dll對應的pdb檔案的生成路徑為C盤PDB檔案下,名字為工程名.pdb,同時該路徑會被記錄在對應的PE檔案中(重要!!!)。
2、將生成的dll檔案copy到exe所在的目錄下,如下所示:
雙擊exe,因為程式崩潰自動生成了“MEMORY.DMP”檔案,如下圖所示:
3、開啟WinDbg軟體,操作步驟如下:
(1)File -> Image File Path 下圖所示的框:
選中“Browse…”按鈕,選擇TEST1.exe,如下圖所示:
(2)File -> Open Crash Dump… 選擇剛才生成的"MEMORY.DMP"檔案。
(3)之後軟體會彈出命令列視窗,如下圖所示:
在下面命令列那裡輸入“!analyze -v”,WinDbg會自動根據資訊分析出崩潰的程式碼行數,部分結果如下:
WRITE_ADDRESS: 00000008
FOLLOWUP_IP:
ErrorDLL!XError::ErrorFun+6 [d:\errordll\errordll\xerror.cpp @ 16]
70591036 c740080a000000 mov dword ptr [eax+8],0Ah
MOD_LIST: <ANALYSIS/>
FAULTING_THREAD: 00001dac
BUGCHECK_STR: APPLICATION_FAULT_NULL_CLASS_PTR_DEREFERENCE_INVALID_POINTER_WRITE_WRONG_SYMBOLS
PRIMARY_PROBLEM_CLASS: NULL_CLASS_PTR_DEREFERENCE
DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE
LAST_CONTROL_TRANSFER: from 01201054 to 70591036
STACK_TEXT:
0038fab8 01201054 00000000 4546f4ea 01203018 ErrorDLL!XError::ErrorFun+0x6 [d:\errordll\errordll\xerror.cpp @ 16]
WARNING: Stack unwind information not available. Following frames may be wrong.
0038fae0 01201268 00000001 00601ba8 00604150 TEST1+0x1054
0038fb24 74a2336a 7efde000 0038fb70 77039902 TEST1+0x1268
0038fb30 77039902 7efde000 7733d33e 00000000 kernel32!BaseThreadInitThunk+0x12
0038fb70 770398d5 01201389 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0038fb88 00000000 01201389 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x36
STACK_COMMAND: ~0s; .ecxr ; kb
FAULTING_SOURCE_CODE:
12: }
13:
14: void XError::ErrorFun(int *p)
15: {
> 16: p[2] = 10;
17: }
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: errordll!XError::ErrorFun+6
FOLLOWUP_NAME: MachineOwner
IMAGE_NAME: ErrorDLL.dll
BUCKET_ID: WRONG_SYMBOLS
FAILURE_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE_c0000005_ErrorDLL.dll!XError::ErrorFun
WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/TEST1_exe/0_0_0_0/5a5c1877/ErrorDLL_dll/0_0_0_0/5a5d4b1a/c0000005/00001036.htm?Retriage=1
WRITE_ADDRESS: 00000008
寫入空指標,違規訪問。
---------------------------------------------------------------
XError::ErrorFun+0x6 [d:\errordll\errordll\xerror.cpp @ 16]
dll原始碼中第16行異常。
---------------------------------------------------------------
STACK_COMMAND: ~0s; .ecxr ; kb
FAULTING_SOURCE_CODE:
12: }
13:
14: void XError::ErrorFun(int *p)
15: {
> 16: p[2] = 10;
17: }
WinDbg定位到了dll原始碼位置。
任務達成!
五、注意事項
- exe、pdb和dmp檔案保持版本一致。
- 在dll工程設定的 pdb生成目錄下存在對應的pdb檔案。
- 原始碼存在於原來的位置,路徑沒有改動。
六、分析
1、若原始碼位置改動,我這裡把路徑下的工程名改為“ErrorDLL00”,WinDbg的部分分析結果如下:
WRITE_ADDRESS: 00000008
FOLLOWUP_IP:
ErrorDLL!XError::ErrorFun+6 [d:\errordll\errordll\xerror.cpp @ 16]
70591036 c740080a000000 mov dword ptr [eax+8],0Ah
MOD_LIST: <ANALYSIS/>
FAULTING_THREAD: 00001dac
BUGCHECK_STR: APPLICATION_FAULT_NULL_CLASS_PTR_DEREFERENCE_INVALID_POINTER_WRITE_WRONG_SYMBOLS
PRIMARY_PROBLEM_CLASS: NULL_CLASS_PTR_DEREFERENCE
DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE
LAST_CONTROL_TRANSFER: from 01201054 to 70591036
STACK_TEXT:
0038fab8 01201054 00000000 4546f4ea 01203018 ErrorDLL!XError::ErrorFun+0x6 [d:\errordll\errordll\xerror.cpp @ 16]
WARNING: Stack unwind information not available. Following frames may be wrong.
0038fae0 01201268 00000001 00601ba8 00604150 TEST1+0x1054
0038fb24 74a2336a 7efde000 0038fb70 77039902 TEST1+0x1268
0038fb30 77039902 7efde000 7733d33e 00000000 kernel32!BaseThreadInitThunk+0x12
0038fb70 770398d5 01201389 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0038fb88 00000000 01201389 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x36
STACK_COMMAND: ~0s; .ecxr ; kb
FAULTING_SOURCE_CODE:
No source found for 'd:\errordll\errordll\xerror.cpp'
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: errordll!XError::ErrorFun+6
FOLLOWUP_NAME: MachineOwner
IMAGE_NAME: ErrorDLL.dll
BUCKET_ID: WRONG_SYMBOLS
FAILURE_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE_c0000005_ErrorDLL.dll!XError::ErrorFun
WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/TEST1_exe/0_0_0_0/5a5c1877/ErrorDLL_dll/0_0_0_0/5a5d4b1a/c0000005/00001036.htm?Retriage=1
大家可以發現,雖然WinDbg仍然可以分析出原始碼異常行號,但是不能再顯示出對應的原始碼。
在原始碼對應位置顯示的內容如下:
FAULTING_SOURCE_CODE:
No source found for 'd:\errordll\errordll\xerror.cpp'
大家可以發現,WinDbg不能在該路徑下發現原始碼檔案,故無法顯示對應的異常原始碼。那麼這個原始碼路徑哪來的呢?之前的文章介紹過,這個原始碼路徑就是儲存在ErrorDLL.dll指定的ErrorDLL.pdb中。
2、若原始碼位置沒有改動,我將ErrorDLL工程中pdb檔案生成目錄下的pdb檔案刪除,部分結果如下:
WRITE_ADDRESS: 00000008
FOLLOWUP_IP:
ErrorDLL!XError::ErrorFun+6
70591036 c740080a000000 mov dword ptr [eax+8],0Ah
MOD_LIST: <ANALYSIS/>
FAULTING_THREAD: 00001dac
BUGCHECK_STR: APPLICATION_FAULT_NULL_CLASS_PTR_DEREFERENCE_INVALID_POINTER_WRITE_WRONG_SYMBOLS
PRIMARY_PROBLEM_CLASS: NULL_CLASS_PTR_DEREFERENCE
DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE
LAST_CONTROL_TRANSFER: from 01201054 to 70591036
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
0038fab8 01201054 00000000 4546f4ea 01203018 ErrorDLL!XError::ErrorFun+0x6
0038fae0 01201268 00000001 00601ba8 00604150 TEST1+0x1054
0038fb24 74a2336a 7efde000 0038fb70 77039902 TEST1+0x1268
0038fb30 77039902 7efde000 7733d33e 00000000 kernel32!BaseThreadInitThunk+0x12
0038fb70 770398d5 01201389 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0038fb88 00000000 01201389 7efde000 00000000 ntdll!RtlInitializeExceptionChain+0x36
STACK_COMMAND: ~0s; .ecxr ; kb
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: errordll!XError::ErrorFun+6
FOLLOWUP_NAME: MachineOwner
IMAGE_NAME: ErrorDLL.dll
BUCKET_ID: WRONG_SYMBOLS
FAILURE_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE_c0000005_ErrorDLL.dll!XError::ErrorFun
WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/TEST1_exe/0_0_0_0/5a5c1877/ErrorDLL_dll/0_0_0_0/5a5d4b1a/c0000005/00001036.htm?Retriage=1
Followup: MachineOwner
大家可以發現,如果pdb檔案不存在的話,WinDbg就無法分析出原始碼位置了。
七、總結
- PE檔案中會記錄對應的pdb檔案路徑,pdb檔案中會記錄原始碼位置,若三者路徑都是正確的,即:都存在,WinDbg不僅可以定位到行號,還可以顯示原始碼。
- 若沒有原始碼,則只能定位到行號,不能定位到原始碼!
- 若PE檔案中記錄的對應的pdb檔案路徑下沒有pdb檔案,則WinDbg就連行號也無法定位了,而且結果也是值得商榷了。
八、原始碼
相關文章
- Windows下Qt使用dump定位崩潰位置(1)WindowsQT
- 如何使用Ida Pro和Core Dump檔案定位崩潰位置(Linux下無除錯符號的程序專享)Linux除錯符號
- 不生成core檔案的記憶體越界快速定位方法/記憶體越界定位/地址崩潰定位方法記憶體
- DLL檔案中Form的使用 (轉)ORM
- dmp檔案的做成
- PDB資料檔案的線上位置以及檔名更改
- 4.3.2.2 關於CDB Root和PDB$SEED檔案的名稱和位置
- VS 開啟程式碼檔案時,在解決方案中自動定位到對應檔案位置
- 使用 google_breakpad 分析 Electron 崩潰日誌檔案Go
- oracle匯出dmp檔案的2種方法Oracle
- oracle匯入dmp檔案的2種方法Oracle
- PDB檔案的用途
- 檔案系統(七):檔案系統崩潰一致性、方法、原理與侷限
- 配置歸檔位置和檔案格式
- oracle匯入dmp檔案Oracle
- iOS友盟崩潰地址解析 通過dSYM檔案分析定位線上 APP crash問題iOSAPP
- win10怎麼刪除dll檔案_win10dll檔案刪除的方法Win10
- java中呼叫dll檔案的步驟Java
- plsql Oracle匯入dmp檔案SQLOracle
- 圖形化還原崩潰地址 iOS的crash檔案分析iOS
- win10系統dll檔案一鍵修復 缺少dll檔案修復方法Win10
- SAP GUI PDB檔案的作用GUI
- 在ASP檔案中呼叫DLL (轉)
- .dll,.lib,.def 和 .exp檔案
- oci.dll 檔案正在被使用
- hosts檔案位置
- Oracle 12C 中CDB和PDB的引數檔案管理Oracle
- store下載檔案儲存位置
- VS2005(vs2008,vs2010)使用map檔案查詢程式崩潰原因
- 批處理檔案(bat檔案)註冊dll批量註冊dllBAT
- 使用DLL檔案中封裝的視窗 (轉)封裝
- 從Export DMP檔案看匯出字符集(下)Export
- 請教windows下引數檔案的位置Windows
- 實用解析dmp檔案內容
- 讓SQL Server呼叫DLL檔案的方法詳解SQLServer
- [Shell] Input null到檔案中的兩個方法Null
- SOLIDWORKS培訓教程 | SW崩潰後如何恢復檔案?Solid
- html檔案中包含其他檔案的方法大全HTML