上一篇向大家介绍了如何在程序“死”的时候转储Dump文件以及如何进行一些其他的处理(请戳蓝色字体:《程序又“死”了,但是还好我转储了dump!》)。那么,今天笔者将继续向大家详细介绍如何使用Windbg对dump文件进行调试分析。
-- 准备工作 --
Windbg是一款功能十分强大的调试工具,它设计了极其丰富的功能来支持各种调试任务,包括用户态调试、内核态调试、调试转储文件、远程调试等等。
● STEP 1:打开Windbg,在file中选择open crash Dump来打开所需要调试的Dump文件。
● STEP 2:在file菜单中分别设置好Symbol file path 和 Source file path。
其中Symbol file path是程序编译时所生成的pdb文件,VS下编译时可以通过勾选编译选项来生成,Delphi下编译时暂时还未找到生成的方法,若各位读者有知道的,欢迎告知;Source file path则是对应的代码路径。
● STEP 3:设置完这些之后,就可以在command窗口中使用Windbg的命令行来进行各种调试分析了。
* 这里需要注意的是:
①如果有pdb文件的话,尽可能的保证pdb文件和产生Dump文件的程序版本是匹配的。
②尽可能地保证所用来分析的源代码和程序版本是匹配的。
如果上述有不匹配的情况,很有可能导致分析时所得到的结果不是正确的,或者是在通过地址偏移定位出现异常代码的行数时导致定位不准确。
如果Dump文件是64位的,在分析时,需要根据被转储文件的位数来判断是否转为32位的,转换的命令如下:
.load wow64exts
!sw
这两个命令可以将64位的Dump转为32位的
再次输入!sw则可将转为32位的Dump再次转为64的
目前版本的Windbg共提供了20多条标准命令,140多条元命令和难以计数的大量扩展命令。
在这里只介绍一下比较常用的命令,其他的可以参考《Windbg用法详解》或者网上搜索
◤ !analyze –v 自动分析 kv 查看堆栈dt 查看结构 ◢
此时利用我们的Dump生成工具来对其进行转储生成Dump文件,可以在命令行中进行调用,如下所示:
分别输入参数:程序名称,PID,窗口标题等,这里PID使用了缺省值。
生成Dump文件之后,将pdb文件和map文件拷贝至Dump文件的同目录下(也可以放在其他路径,这里只是为了方便演示):
如果电脑上装有VS的话,此时可以直接双击Dump文件进行打开,之前做VS下开发的时候,调试Dump基本上是这么进行调试的。如下图:
通过本地调试,可以很容易的定位到导致程序出现无响应的代码行-while死循环,也可以在堆栈列表中对程序的上下文进行加载分析等。
当然,这里最主要还是介绍如何使用Windbg进行Dump的分析,下面将演示Windbg的分析:
使用Windbg打开Dump文件并设置好符号文件路径(sysmbol path)和代码路径(source path),然后界面如下图所示:
在command窗口的命令行中输入:
!analyze –v (自动分析命令)↓↓
可以看到,通过这个命令,可以自动的分析出出错的代码段,很明显,是这里的死循环导致程序出现了无响应。
接下来将演示一下没有pdb文件时对Dump的分析。这里使用Delphi编译了一个程序,同样也是设置一个死循环导致程序出现无响应。
相同的步骤这里就跳过了,在command窗口中同样输入:!analyze –v
在自动分析的结果中,我们只能看到一些基本的堆栈信息,以及相互间的上下文调用。不过从这里我们可以看出,程序是卡在我们所写的代码里,在stocktrade!DoIpoVoteTrade+0x28f4这里出的问题。
由于是在现有的机构客户端的框架下,所以可以大致的判断出是在stocktrade的模块下的代码出了问题。DoIpoVoteTrade是这个模块的导出函数,然后在这个函数的基础上有又0x28f4大小的地址偏移。
根据这个地址偏移,可以计算出出问题的代码的动态地址,如下图所示:
使用? stocktrade!DoIpoVoteTrade+0x28f4可以得到其动态偏移地址为205cea24,这个地址是产生Dump时的动态地址,当我们再次debug的时候,其动态地址则会发生变化。
所以这里我们主要要获取到stocktrade和DoIpoVoteTrade之间的偏移量,DoIpoVoteTrade和出错代码之间的偏移量。
通过14.png可以计算出stocktrade和DoIpoVoteTrade之间的偏移量为:0006c130
DoIpoVoteTrade和出错代码之间的偏移量为:0x28f4
获取到这两个偏移量之后,通过:stocktrade模块的基地址 + 0006c130 + 0x28f4则可以计算出debug时候的偏移地址。
同样可以将stocktrade!DoIpoVoteTrade+0x28f4输入到汇编窗口中观察这块内存地址的汇编信息,以便和接下来我们debug时候cpu界面看到的汇编信息进行对比,验证所计算出的地址偏移是否准确。如下图所示:
当获取到动态偏移地址的偏移量之后,接下来我们需要打开出错的的这个模块的代码,然后进行debug调试。
通过Modules界面可以找到stocktrade模块的基地址:1EAB0000,加上之前得到的偏移量0006c130和0x28f4,可以得到偏移地址:1EB1EA24。
设置断点之后,打开CPU调试界面(ctrl + alt + c),如下图所示:
然后在右键菜单中选择Goto Address:
跳转到我们通过Windbg所分析出的偏移地址。不过我个人的电脑不知是怎么回事,跳转的时候总是不能正确的跳转过去,原因还在调查中。跳转后,可以看到如下界面:
结合我们在Windbg的汇编窗口看到的信息和本界面进行对比,确定所计算的地址是正确的。通过显示的代码信息,可以判断出是出现了死循环。同时可以在这里打个断点,然后F8进行调试:
可以看到程序也是在一直循环的,所以结合代码,可以判断出程序是在uFrmIpoTrade的715行出现了异常导致无响应的。
当然,以上介绍的这些都是很简单的例子,结合代码可以很容易的分析出问题所在。但是实际工作中,所遇到的异常问题,可能原因比较复杂,涉及到多线程以及更多的模块等等。
这个就需要慢慢去积累经验,逐步地去分析了,但是基本的步骤应该是和上面所演示的例子是差不多的,希望能够对各位有所帮助。
本文转载自恒生技术之眼,如需转载请至恒生技术之眼官网申请授权。
作者: 刘大强
原文链接: http://rdc.hundsun.com/portal/article/dump2-610.html?from=CSDN