本文主要就windows下dump的分析做一个总结。
一、前置准备
WinDbg程序下载,注意使用32位或者64位,一般网站都有哈,找不到的可以评论区留言。
接下里这个配置非常关键:
1)、确定机器位数
a、 如果dump是64位的,可以选择打开32位的任务管理器,生成32位的dump。
在C:\Windows\SysWOW64目录下找到taskmgr.exe双击打开(不要关闭之前已经打开过的任务管理器),这个时候打开的任务管理器就是32位的了。辨认方式很简单:看taskmgr.exe后面有没有 *32标记,有,那就是32位,没有就是64位。对于win8及以上的操作系统,还可以进行“选择列”操作新增“平台”项,更直观的看到运行的应用程序是32位的还是64位。
b、或者使用windbg将64位dump转为32位再分析,命令如下: .load wow64exts !sw
2)、设置必要的环境信息
打开WinDbg工具,我们首先需要配置Symbol path,Source path以及Image path
a、Symbol path
这是pdb文件路径,包括当前dump调试对应的工程pdb文件,以及系统api对应的pdb文件。需要配置为:
SRV*D:\mysymbol*http://msdl.microsoft.com/download/symbols
其中D:\mysymbol为下载系统pdb文件存放在本机的路径。
同时需要加载map文件所在的路径,程序用到的所有的库所在的路径。(map和pdb文件的生成请参考对应的开发工具。特别注意:程序库、pdb、map、程序源文件都要保持是是dump完全一致的程序生成的,否则解析后会不准。)
在view-commond中输入 .reload命令,加载pdb符号
vc6.0产生map方法如下:需要勾选设置中的产生MAP文件勾选框
更详细的可参考:map文件生成
b、Source path
这是代码路径,此代码需要和pdb文件版本保持一致。
c、Image path
Exe程序路径,一般用于死循环时,在WinDbg中继续调试
二、开始解析
如果第一步配置无误,直接选择File->Open Crash Dump 后输入 !analyze -v,等待解析就可以看到异常的位置和对应的源码位置。
如果说必要的某个库没有导入成功,可以查看位置是否正确,重新执行第一步的配置符号信息。
如果没有解析到对应的代码行数,则需要我们自己去计算地址了,这个后续再更新。本次先贴一下常用的一些命令
内存越界及非法访问:
!analyze -v:自动分析出异常的详细信息
~0s:切换到异常线程
.ecxr :定位当前异常的上下文信息
kb:显示栈回溯信息
.frame 0:将当前堆栈的局部上下文切换到指定栈帧
d命令和dv命令:分析变量值
内存泄漏:
gflags.exe –i XXX.exe +ust:为可能存在内存泄漏的进程启用用户堆栈跟踪
!heap –s:查看当前进行所有堆的内存分配情况,选择堆内存最大一个堆继续分析
!heap -stat –h xxx:查看堆xxx上各个大小的内存块分分布情况
!heap –flt s xx:查看堆上所有大小为xx的内存块信息,随便选几个内存块进行分析
!heap -p –a xxx:查看指定地址的调用堆栈信息
lsa xxx:进入指定模块的代码
死锁:
分析等待链:分析程序是否处于死锁状态
!locks:查看所有线程占用的锁信息,包含拥有锁的线程,以及有多少个线程在等待这把锁
~*kv:查看所有线程的堆栈信息
!cs xxx:查看锁的具体信息
Dump文件无堆栈
!analyze -v:自动分析出异常的详细信息
~*kv:查看所有线程的堆栈
~56s:切换到崩溃线程,假设为56号线程
kb:显示当前线程的栈回溯信息,同时显示栈上的前三个参数
dd xxx:按四字节读取地址
.exr xxx:查看异常类型
.cxr xxx:解析改地址的上下文内容
kb:查看实际的异常的调用堆栈
.frame 1:将当前上下文切到指针栈帧再结合dv命令分析
句柄泄漏
句柄泄漏的分析和其他问题分析不一样,它是在程序运行中进行分析的,也就是不会生成dump文件,而是将该进程attach到windbg中 attach:将该进程attach到windbg中
!htrace –enable:开启句柄栈回溯跟踪,该命令同时默认产生第一次句柄信息的快照
!htrace –snapshot:查看初始的句柄信息快照
F5:让程序继续运行,当出现句柄泄露时,可以通过break中断进程
!htrace –diff:查看没有进行释放操作的句柄栈回溯信息
lsa xxx:进入指定模块的代码
总之在解析dump文件时除了运用这些命令外,还得边结合现象、业务逻辑、代码综合分析。