Windows 2000对调试技术的支持( 四 )


安装符号文件
重新启动后 , 你就有了一个 Windows 2000 系统的快照( snapshot ) , 包括一个有问题的 Kernel-mode Driver (读取空指针时被捕获) 。观察此快照文件和察看实际系统内存是一样的 。当然 , 这个快照文件和动物死尸一样 --- 不再对外界刺激有所反应 , 但是你现在不需要担心这些 。接下来你需要安装内核调试器需要的符号文件( symbol files ) , 当你分析崩溃文件时 , 你就会用到了 。
MSDN 用户可以在 Windows 2000 Customer Suuport – Diagnostic Tools 光盘上找到这些符号文件 。插入光盘 , 用 IE 打开光盘上的 DBG.HTM 文件 , 你会看到很多安装选项 。如果你运行的是 free build 的 Windows 2000 , 你最好安装 retail symbols。对于 checked build 版 , 可以选择安装 debug symbols。安装程序会从 SYMBOLS.CAB 中复制一些 .dbg 和 .pdb 文件到系统符号文件目录中 。默认的系统符号文件目录为: %SystemRoot%Symbols。%SystemRoot% 环境变量代表 Windows 2000 的安装目录 。
在起动时 , Windows 2000 内核调试器会尝试通过环境变量 _NT_SYMBOL_PATH 指示的路径来寻找符号文件 , 所以最好正确的定义该变量 。
译注:
现在可以通过 Symchk.exe 工具来检查和下载最新的符号文件 , 该工具随 Debugging Tools for Windows 软件包安装 。
微软的文档中对于 _NT_SYMBOL_PATH 应该指向哪里的说明有些模糊不清 。在 DDK 的内核调试一节里提到必须包含符号子目录 , 即 C:WINNTSymbols 或等价目录 。而在 SDK 关于 dbghelp.dll 库的文档中 , 有关符号路径的描述又稍微有些区别:
“该库需要使用符号搜索路径来定位 .dll 、 .exe 或 .sys 对应的调试符号( .dbg 文件) 。它会在路径后添加 dll 、 exe 或 sys。例如 , .dll 符号文件位于: C:WINNTSymbolsdll , .exe 文件的路径则为: C:WINNTSymbolsexe ”
。。。。。。
“如果你设置了 _NT_SYMBOL_PATH 环境变量 , 符号管理器按照如下顺序搜索符号文件:
1. 应用程序的当前工作目录
2. _NT_SYMBOL_PATH 指示的目录
3. _NT_ALT_SYMBOL_PATH 指示的目录
4. SYSTMEROOT 指示的目录

这样看来把 _NT_SYMBOL_PATH 设定为 C:WINNT 似乎要好于 C:WINNTSymbols , 为了确定哪种说法是正确的 。我试验了这两种方法 , 很高兴它们都能正常的工作 。
配置内核调试器
构建调试环境的最后一步就是安装和配置内核调试器 。如果你已经安装了 Windows 2000 DDK , 那你可以在 NTDDKbin 目录中找到调试器 。内核调试器的可执行文件名为 i386kd.exe。另一种方法是从 Windows 2000 Customer Support---Diagnostic Tools 光盘中安装 。
为了使用前面我们得到的崩溃转储文件 , 你需要使用 i368kd 的 –Z 选项 。示例如下:
i386kd –z C:WINNTMEMORY.DMF
成功打开我们的 crash dump 后 , 你会看到类似图 1-7 所示的东东 , kd> 提示符会出现 , 这表示内核调试器已经准备接受命令了 。在开始之前 , 请检查符号搜索路径是否正确 。列出的启动信息 , 表示调试器已经加载了三个扩展 DLL。i386kd.exe 一个强大的特性就是其扩展机制 , 这允许第三方采用独立的 DLL 来扩展其基本功能 。对于这些扩展的命令 , 要在其前面加上!号以区分内建的命令 。
如图 1-7 所示 , 我输入了一个内建命令: u becc3000 , u 的含义是“反编译( unassembel )” , becc3000 是开始反编译的 16 进制地址 。默认情况下 , 均采用 16 进制 , 但你也可也通过命令来改变此默认值 。命令为: n 10 , 此后默认所有数字都是 10 进制表示 。你可以使用 0x 前缀来表示这是一个 16 进制数 。地址 becc3000 就是 w2k_kill.sys 引起系统崩溃的地方 。请使用你在蓝屏时看到的地址 。如果一切正确的话 , 你会看到 mov eax, [00000000] 指令 , 如上图所示 。如果没有看到的话 , 你可能没有使用正确的崩溃转储文件 。mov eax, [00000000] 指令表示从虚拟地址(也可称作线性地址) 0x00000000 读取一个 32 位的数值到 CPU 寄存器 EAX 中 , 这明显是列表 1-1 中 *(NTSTATUS*)0) 表达式的实现 , 等同于读取空指针的操作 。没有针对此类错误的异常处理例程 , 因此 , 系统在蓝屏上会显示 KMODE_EXCEPTION_NOT_HANDLED , 如图 1-3 所示 。如果你想知道有关此错误信息更多的东西请参考《 The NT Insider 》( Open Systems Resources 1999b ) 。

推荐阅读