Dump 文件分析很大程度上就是分析蓝屏产生的原因。这种系统级的错误算是Windows提示错误中比较严重的一种(更严重的还有启动黑屏等硬件或软件兼容性错误等等)。说它是比较严重,是因为毕竟Windows还提供了dump文件给用户分析,至少能比较容易的找到错误的原因。一般蓝屏要么是内核程序中的异常或违规,要么是数据结构的损坏,也有boot或shutdown的时候内核出错。有时候蓝屏是一闪而过,紧接着是系统重启;有时候是蓝屏等待。总之蓝屏的时候都提示了一些停止代码和错误信息,不过这些提示是不全面的,最多知道哪个模块出错(比如驱动)。想了解进一步的信息,或者通过搜索引擎,最好的方式当然是dump文件分析。当然,如果有更进一步研究的欲望,内核调试是更好的方法,不过这需要某些软件支持和调试技巧。
类型
Dump文件有三种:完整内存转储,内核内存转储,小内存转储。System Properties中的高级选项中可以看到这些设置。
完整内存转储太大,一般是物理内存大小或多一些,包括了用户进程页面,这种方式不实用,2GB的物理内存转储出来至少要2GB的磁盘空间(还有文件头信息)。内核转储一般是200MB大小(物理内存小于4GB),它只是包含了所有属于内核模式的物理内存。小内存转储一般是64KB(64位上是 128KB),这两种方式是更常用的。
小内存转储在\Windows\Minidump下生成了一个叫Mini日期+序列号.dmp的文件,这个珍贵的资源就是系统Crash时刻的状态,只不过小内存转储只记录的有限的信息,而且在你分析时,如果windbg没有设置符号服务器的路径(关于符号服务器,请参考Windbg内核调试之二: 常用命令),那么你的当前系统必须和发生蓝屏的系统的Ntoskrnl.exe版本相同,否则就有找不到符号的问题产生。
启动windbg,用Open Crash Dump打开dump文件,或者直接拖动文件到windbg中,windbg显示如下信息:
Mini Kernel Dump File: Only registers and stack trace are available
Symbol search path is: SRV*d:/temp/*http://msdl.microsoft.com/download/symbols
Executable search path is:
Windows Vista Kernel Version 6000 (Service Pack 1) UP Free x86 compatible
Kernel base = 0x80400000 PsLoadedModuleList = 0x8046e8f0
Debug session time: Thu May 28 16:12:29.031 2009 (GMT+8)
System Uptime: not available
Loading Kernel Symbols...............................................................
Loading unloaded module list.....................................................................
Loading UserSymbols
******************************************************************************** ** Bugcheck Analysis ** ********************************************************************************
Use !analyze -v to get detailed debugging information.
BugCheck 7F, {0, 0, 0, 0}
大致上提示了Crash系统的版本,加载符号的过程,如果找不到符号文件,还会提示Unable to load image。如下错误就是找不到ntoskrnl.exe的符号文件:
Unable to load image \SystemRoot\system32\ntoskrnl.exe, Win32 error 0n2
*** WARNING: Unable to verify timestamp for ntoskrnl.exe
*** ERROR: Module load completed but symbols could not be loaded for ntoskrnl.exe
命令
通过lm命令查看模块列表。另外,如果出现Unable to load image,说明没有找到这个文件,这个时候需要查看是否加载了正确的符号文件。设置符号服务器路径(.symfix命令)是很有必要的,因为调试机器和Crash机器的环境很可能不一致。
运行命令kb,显示调用栈的信息。如果有正确的符号设置,可以看到调用的函数名。如果你在调试自己驱动程序的蓝屏问题,请确保设置正确该驱动程序的符号路径,不然就会出现Stack unwind information not available的问题。加入正确的符号文件(pdb)后,可以用命令!reload重新加载符号文件。
通过!thread和!process,可以显示当前进程和线程。或者通过dt nt!_KTHREAD 地址和dt nt!_EPROCESS地址来查看线程和进程结构。
Windbg提供了自动分析dump文件的机制。通过命令!analyze –v,windbg可以自动做分析,显示如下信息:
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.
Arguments:
Arg1: e1147008, memory referenced
Arg2: 0000001c, IRQL
Arg3: 00000000, value 0 = read operation, 1 = write operation
Arg4: fbe93403, address which referenced memory
Debugging Details:
------------------
READ_ADDRESS: e1147008 Paged pool
CURRENT_IRQL: 1c
FAULTING_IP:
myfault+403
fbe93403 8b06 mov eax,dword ptr [esi]
DEFAULT_BUCKET_ID: DRIVER_FAULT
BUGCHECK_STR: 0xD1
PROCESS_NAME: NotMyfault.exe
TRAP_FRAME: f9357b80 --(trap fffffffff9357b80)
ErrCode = 00000000
eax=00000000 ebx=8111f330 ecx=000000d1 edx=0000001c esi=e1147008 edi=00000000
eip=fbe93403 esp=f9357bf4 ebp=f9357c58 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246
myfault+0x403:
fbe93403 8b06 mov eax,dword ptr [esi] ds:0023:e1147008=????????
Resetting default scope
LAST_CONTROL_TRANSFER: from 804f880d to 80527da8
STACK_TEXT:
f9357734 804f880d 00000003 f9357a90 00000000 nt!RtlpBreakWithStatusInstruction
f9357780 804f93fa 00000003 e1147008 fbe93403 nt!KiBugCheckDebugBreak+0x19
f9357b60 80540853 0000000a e1147008 0000001c nt!KeBugCheck2+0x574
f9357b60 fbe93403 0000000a e1147008 0000001c nt!KiTrap0E+0x233
WARNING: Stack unwind information not available. Following frames may be wrong.
f9357c58 805759d1 ffb5c3b0 8111f318 811d9130 myfault+0x403
f9357d00 8056e33c 00000090 00000000 00000000 nt!IopXxxControlFile+0x5e7
f9357d34 8053d808 00000090 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
f9357d34 7c92eb94 00000090 00000000 00000000 nt!KiFastCallEntry+0xf8
0012f9f0 7c92d8ef 7c801671 00000090 00000000 ntdll!KiFastSystemCallRet
0012f9f4 7c801671 00000090 00000000 00000000 ntdll!ZwDeviceIoControlFile+0xc
0012fa54 004018c2 00000090 83360018 00000000 0x7c801671
STACK_COMMAND: kb
FOLLOWUP_IP:
myfault+403
fbe93403 8b06 mov eax,dword ptr [esi]
SYMBOL_STACK_INDEX: 4
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: myfault
IMAGE_NAME: myfault.sys
DEBUG_FLR_IMAGE_TIMESTAMP: 43774e1d
SYMBOL_NAME: myfault+403
FAILURE_BUCKET_ID: 0xD1_myfault+403
BUCKET_ID: 0xD1_myfault+403
Followup: MachineOwner
一般是按照如下:停止码解释,陷阱帧寄存器信息,蓝屏属性(有些除零错误就在这里显示),栈调用,错误指令位置(FOLLOWUP_IP),出错源代码和汇编代码行,错误代码行,出错模块信息(包括负责人等信息),来组织自动分析信息。
通过r命令,可以显示Crash时刻寄存器的状态和最后的命令状态。
通过d命令,可以显示当前内存的地址。在定位了错误代码行了之后,就可以进一步进行内核调试和系统调试了。