您的位置:首页 > 编程语言 > C#

快速打造批量DUMP分析工具

2008-12-28 00:41 309 查看
在前些日子的工作中很大一部分时间用在版本稳定性的维护上,对于一个拥有庞大用户数的客户端软件而言,用户机器上软件环境的多样性使开发人员很难预料会发生什么样的情况,这时候应用程序崩溃后的DUMP反馈措施几乎就成了唯一能够快速发现和解决问题的途径。

  应用程序崩溃后,客户端程序通过交互界面征求用户同意在用户机器上收集能够帮助开发人员定位错误的有用信息,包括用户的操作系统版本号、程序启动以来所加载和卸载过的动态库模块名称和校验值、发生错误时刻各个线程的栈数据(当然也包括调用堆栈),也可能包含部分数据段的堆内存数据(堆内存中通常会有几十甚至几百MB的数据段内存,因此通常是不可能返回完整的数据段内存的),这些数据被包含在.DMP文件中,然后随同其他日志或附加文件打包反馈给软件提供者。
  造成应用程序崩溃的原因各不相同,包括软件本身的缺陷、与其它软件冲突(也有很多时候是受隐藏在用户机器上的低质量木马和病毒程序影响)、还有软件本身未预期的复杂的用户软件环境。

  分析 DUMP 所要准备的环境包括与用户环境中匹配的应用程序版本映像文件(exe和dll)、编译该版本时所产生的pdb符号文件以及编译该版本所使用的源代码。通常使用Visual Studio时,我们将符号文件和exe/dll文件放在同一目录下,然后将所要分析的 .dmp 文件也复制过来,双击打开dump文件时就能立即找到匹配的符号,也避免了在需要同时分析多个不同版本的dump文件时通过 Visual Studio中的设置无法区分版本的问题。

  通常刚开始分析DUMP的开发者会习惯于依赖Vistual Studio的环境,但是 Visual Studio 却不适合用于批量分析,虽然它很强大,而且我们可以编写VS IDE插件来完成这一工作,然而它太过庞大,VS IDE 的插件接口也不太适合作批量操作,不符合我们“快速打造”的预期。同时没有考虑使用PlatformSDK中 dbgeng.h 和 dbghelp.h 中的堆栈分析方法也是基于同一个原因,我们需要的是一个比较程序员化却又不太过程序员化的能够很快工作起来的东西,刚开始的时候不需要太完美,但我们希望能够不断改进让它逐渐变得用起来得心应手。

  因此要进行开发,首先需要一个适用于快速应用开发(RAD)的开发工具,考虑到了Python和C#,它们都很容易被使用,虽然最熟悉的工具仍然是C++,但是C++的确不太适合作为快速应用开发的首选,而如果我不希望这个工具永远都只有自己能使用的话,我希望这个分析工具能有个象样的界面,所以最终选择了C#。

  Windbg在调试崩溃现场的时候较 Visual Studio 而言有更多的优势,它小巧,实用,能够看到更多的详细信息,不需要和打开 Visual Studio 调试一样耐心地等待,一旦在运行参数里指定了源文件路径后不需要像VS一样每次都要去手动选择源文件。(Windbg 可以在 http://www.microsoft.com/whdc/DevTools/Debugging/default.mspx 被找到。)虽然使用 Windbg 让人仿佛回到了命令行时代,不过却正是这一点为我们将要定制的分析工具带来了更大的灵活性。

  Debugging Tools 安装包中除了我们常用的 windbg 以外还有一个叫做 cdb 的命令行工具,命令和参数都和windbg一致:-z 指定dump文件路径和名称,-i 指定映像文件路径,-y 指定符号路径,-srcpath 指定源代码路径,路径以分号分隔可以指定多个路径,- logo 指定将调试过程的命令输出到文本文件,-cf 指定一个命令脚本。

借由 cdb 能够执行该脚本并将结果输出的文本文件,就不需要再考虑如何自行 walk through 整个调用堆栈和枚举加载模块和线程,所有这些都可以通过一个脚本配置文件来完成。例如:
 k 100
 lm
 q

"k 100"使 cdb 分析调用堆栈,调用堆栈深度限制为100层call方法,"lm"列举出应用程序崩溃时在用户机器上所加载和卸载的模块信息(名称和在内存中的加载地址,使用lmv可以打印出更详细的版本、路径、校验值等信息),最后一行"q"退出cdb。通过一个类似的批处理过程省略掉自己使用debug API分析dump内容的过程,从而轻易完成了可能会最痛苦的步骤。这时,分析工作就只聚焦在输出结果上,所要完成的也就只剩下不需要太多技术含量的文本解析过程。

某些时候会发生许多崩溃源自同一原因的情况,这个时候通常在调用堆栈里都具备一些相同的特征,因此使分析工具具备某些自动化的特征成了批量处理的关键,例如我在 CrashTracker 中为批量分析添加了一个小小的调用堆栈分析规则,使分析过程变成自动化且可配置,同时结合UI将分析结果可视化,一个规则样本文件如下:
[
 ntdll!KiUserExceptionDispatcher+0xe
 urlmon!CTransaction::GetBindInfo+0x10
 urlmon!CINet::Start+0x5f
]
{ urlmon.dll 所引起的崩溃 }
[ call stack feature ]
{ auto analysis comment }

从而根据脚本输出分析自动为某个崩溃项添加备注,省去手工检查重复项的烦琐工作。如果觉得在命令行里跑 cdb 不够优雅的话可以利用管道API来屏蔽命令行输出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息