日期:2014-05-16  浏览次数:20797 次

Windows 异常处理的研究的总结

原文:

http://www.cnblogs.com/yangchaobj/archive/2013/02/23/2923416.html

http://www.cnblogs.com/yangchaobj/archive/2013/02/23.html

?

最近半年单位的项目集中上线,出了一些 crash 的问题。

程序crash 后,会自动生成一个 dump 文件,这是通过调用系统API?MiniDumpWriteDump 实现的。

?

通过事后对 dump 文件的分析,工程师可以找到出问题的点。

不方便的是,每次打开dump文件后,堆栈总是停在类似?ntdll!KiFastSystemCallRet 的地方,通过这个 callstack 完全找不到任何程序的蛛丝马迹。而是用 .ecxr 则报错,说没有 ContextRecord.?工程师需要执行 windbg 的 s 命令,在堆栈中寻找 ExceptionContext 去恢复现场,对于做过的人稍有些麻烦,对于生手就比较困难了。

*具体搜索思路是:根据ContextRecord 的定义,第一个成员是异常号,比如 0xc0000005,那就在堆栈上搜这个异常号:s -d esp L1000 0xc0000005

如果是 x64平台,用 s -d rsp L1000 0xc0000005

一般会找到2-3个匹配的堆栈地址,再逐个去试,就很容易找到。

还有一个问题,有时候 dump 文件可以生成,有时候程序直接退出,没有任何 dump。

?

基于这些现象,我有了一些问题:

1. 能否不用每次手动寻找 ExceptionContext ,而让 windbg 直接重现现场。

2. 能否保证所有的异常都被捕获并生成 dump (当然是在外围条件都满足的情况下)

由这个 Dump 文件引发了我一系列的研究和学习。现在将成果总结如下。

?

在windbg 定位的时候,需要用到 .cxr 指令,通过查windbg帮助手册,了解到这个指令是 Display Context Record 的缩写。在异常发生时,windows 会将异常发生时的各个寄存器数值、堆栈位置等记录下来,存在一个 ContextRecord 结构里,并把这个结构压入堆栈。.cxr 命令还带一个地址参数,用来指定 ContextRecord 的位置。这个结构对于能否恢复堆栈起着决定性的作用