VS2010下使用dmp文件和pdb文件定位到dll中崩溃位置的方法
2018-01-15 17:42
2201 查看
2018-01-15 创建人:Ruo_Xiao 邮箱:xclsoftware@163.com
一、基础链接
http://blog.csdn.net/itworld123/article/details/79041500http://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就连行号也无法定位了,而且结果也是值得商榷了。
八、源码
http://download.csdn.net/download/itworld123/10207344相关文章推荐
- VS2010下使用dmp文件和pdb文件定位程序异常代码行号的注意事项
- vs2010下使用dmp文件和pdb文件调试时dump、exe和pdb三个文件要保持版本一致的原因
- vs2010 利用DMP文件、pdb文件查找release下的异常行号的方法
- 使用MAP文件快速定位程序崩溃代码行
- 使用MAP文件快速定位程序崩溃代码行
- MS-VC 使用MAP文件快速定位程序崩溃代码行
- vc调试:使用MAP文件快速定位程序崩溃代码行-zz
- DMP文件的生成和使用(转),由于须要取得用户出现问题的信息,所以须要取得demp信息,可以通过本方法获取。
- 使用MAP文件定位程序崩溃代码行
- linux下whereis命令使用详解---linux定位文件位置命令
- Regsvr32注册DLL文件命令的使用方法详细说明
- VS2010环境下用ANSI C创建DLL和使用方法
- 使用MAP文件快速定位程序崩溃代码行
- 使用MAP文件快速定位程序崩溃代码行
- vc调试:使用MAP文件快速定位程序崩溃代码行
- 使用MAP文件快速定位程序崩溃代码行
- 使用windbg分析dmp文件定位程序bug
- MS-VC 使用MAP文件快速定位程序崩溃代码行[转]
- 使用VS2008创建一个DLL文件的方法
- 使用MAP文件快速定位程序崩溃代码行(转)