如何错过异常第一现场找到异常上下文

介绍

前面的章节都在讲解通过SetUnhandledExceptionFilter 设置程序自动捕获异常dump,这类dump通过.ecxr 命令或者 !analyze -v 就可以找到异常,但是在有些情况下(比如别人的项目),没有自动保存异常dump时应该怎么分析呢?

现象

某个新项目在测试环境出现了异常,弹出了一个异常框,这是windows下比较常见的异常框,是因为程序遇到了异常,但是没有设置用户自定异常处理函数,从而触发了windows默认异常处理函数“弹出一个异常提示框”。
这种情况下:
1、不要关闭对话框。使用windbg attach 到该异常程序
2、通过命令 .dump /ma d:\xx.dmp 保存fulldump
分析方法
通过windbg打开xx.dmp,加载系统符号文件。
输入命令

1
~*er?$t1=((ntdll!_NT_TIB*)@$teb)->StackLimit;r?$t2=((ntdll!_NT_TIB*)@$teb)->StackBase;!teb;dps@$t1@$t2

这个命令是打印所有线程的调用栈,通过查找“KiUserExceptionDispatcher”来找到异常上下文。

注意:因为如上命令会打印很多信息,所以windbg ui界面是无法显示的,好的办法是将输出都保存到日志文件中, windbg->”edit”->”open/close log file”。

1
在输出的log文件中查找"KiUserExceptionDispatcher",如下

1
2
3
4
5
6
7
8
9
10
11
12
044bed64  044ba000
044bed68 00000000
044bed6c 044bf288
044bed70 77a70133 ntdll!KiUserExceptionDispatcher+0xf
044bed74 014bed84
044bed78 [044bedd4]
044bed7c 044bed84
044bed80 044bedd4
044bed84 e06d7363
044bed88 00000001
044bed8c 00000000
044bed90 769cc42d KERNELBASE!RaiseException+0x58

注意其中“[]”的内容,这个地址就是异常上下文地址,最后通过命令
.cxr 044bedd4

kv

就可以找到异常点。