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  查看堆栈
   !runaway  显示所有线程的CPU消耗
   !handle e00 f 显示句柄详细详细
   !cs 00bcd034 临界对象
   !teb查看TEB的结构
   bp 下断点,还有条件断点
  !address 显示整个地址空间和使用摘要的信息
  dd 按字节查看

  dt 查看结构                                                          ◢

-- 实例解析 --

有PDB文件时的分析:由于Delphi编译暂时未找到生成pdb文件的方法,这里以VS下的MFC程序为示例来进行分析。
如下图所示,示例程序MFCApplication1.exe在点击“出现无响应”按钮之后,进入无响应状态:

此时利用我们的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文件怎么办? --

通过以上两个示例可以看出,当有pdb文件的时候,不论使用VS还是Windbg,相对来说分析Dump还是比较简单的,可以直观的看到对应的代码段,然后进行分析。

接下来将演示一下没有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行出现了异常导致无响应的。

当然,以上介绍的这些都是很简单的例子,结合代码可以很容易的分析出问题所在。但是实际工作中,所遇到的异常问题,可能原因比较复杂,涉及到多线程以及更多的模块等等。

这个就需要慢慢去积累经验,逐步地去分析了,但是基本的步骤应该是和上面所演示的例子是差不多的,希望能够对各位有所帮助。

发布了1 篇原创文章 · 获赞 0 · 访问量 2710

猜你喜欢

转载自blog.csdn.net/yjj350418592/article/details/105331991