第第第第30章章章章 WinDBG 用法用法用法用法详解详解详解详解
WinDBG 是个非常强大的调试器,它设计了极其丰富的功能来支持各种调试任务,包括用户
态调试、内核态调试、调试转储文件、远程调试等等。WinDBG 具有非常大的灵活性和可扩展性,
用来满足各种各样的调试需求,比如用户可以自由定义调试事件的处理方式,编写调试扩展模块
来定制和补充 WinDBG 的调试功能。
尽管 WinDBG 是个典型的窗口程序,但是它的大多数调试功能还是以手工输入命令的方式来
工作的。目前版本的 WinDBG 共提供了 20 多条标准命令,140 多条元命令(Meta-commands),
和难以计数的大量扩展命令。学习和灵活使用这些命令是学习 WinDBG 的关键,也是难点。
上一章我们从设计的角度分析了 WinDBG,本章将从使用(用户)的角度介绍 WinDBG。我
们先介绍工作空间的概念和用法(第 1 节),然后介绍命令的分类和不同种类的命令提示符(第 2
节)。第 3 节介绍不同的调试模式,也就是如何与不同特征的调试目标建立调试会话。第 4 节介绍
上下文的概念和在调试时应该如何切换和控制上下文。第 5 节介绍调试事件和如何定制调试事件
的处理方式。从第 6 节到第 9 节我们将分别介绍如何在 WinDBG 中完成典型的调试操作,比如控
制调试目标(第 6 节)、设置断点(第 7 节)、观察栈(第 8 节)以及如何观察和修改数据(第 9
节)。
30.1 工作空间
工作空间
工作空间
工作空间
WinDBG 使用工作空间(Workspace)来描述和存储一个调试项目的属性、参数、以及调试器
设置等信息。其功能类似于集成开发环境的项目文件。
30.1.1 分类分类分类分类
WinDBG 定义了两种工作空间,一种称为缺省的工作空间(Default Workspace),另一种称为
命名的工作空间(Named Workspace)。当没有明确使用某个命名的工作空间时,WinDBG 总是使
用缺省的工作空间,因此缺省的工作空间也叫隐含的(implicit)工作空间,命名的工作空间也叫
显式的(explicit)工作空间。
WinDBG 安装时就预先创建了一系列缺省的工作空间,分别是:
基础工作空间(base workspace),当调试会话尚未建立,WinDBG 处于模糊状态时,它
会使用基础工作空间。
缺省的内核态工作空间(default kernel-mode workspace),当在 WinDBG 中开始内核调试,
但是尚未与调试目标建立起联系时,WinDBG 会缺省使用这个工作空间。
缺省的远程调试工作空间(remote default workspace),当通过调试服务器(DbgSrv 或
KdSrv)进行远程调试时,WinDBG 会缺省使用这个工作空间。
特定处理器的工作空间(processor-specific workspace),在进行内核调试时,当 WinDBG
与调试目标建立起联系,并知道对方的处理器类型后,WinDBG 会缺省使用其对应处理
器类型的工作空间。典型的处理器类型有 x86、AMD64、Itanium 等。
缺省的用户态工作空间(default user-mode workspace),当 WinDBG 正在附加到一个用
户态进程的过程中时,它会使用这个工作空间。
1
相对于可执行文件的缺省工作空间,当在用户态调试时,一旦 WinDBG 知道了调试目标
的可执行文件名后(对于附加到已经运行的进程,是附加到进程后,对于调试新运行的
程序,那么是选定程序文件后),它就会使用这个可执行文件所对应的工作空间,如果这
个工作空间已经存在,那么它就用存在的,如果不存在,那么就创建一个新的。
相对于转储文件(dump file)的工作空间,在分析转储文件时,WinDBG 会为每个转储
文件建立和维护一个工作空间。
在通过 WinDBG 文件菜单的 Save workspace as…命令调出的 Save Workspace As 对话框的标题
中包含了 WinDBG 当前所使用工作空间的名字。当 WinDBG 切换到一个新的工作空间或者退出
前通常也会提示是否要保存工作空间,提示对话框(图 30-8)的标题中包含了工作空间的名字。
图 30-1 切换或者关闭调试会话时 WinDBG 提示是否要保存工作空间
将当前工作空间另存为一个特定的名字,那么便创建了一个命名的工作空间。
30.1.2 内容内容内容内容
工作空间保存了如下几类信息:
调试会话状态:包括断点,打开的源文件,用户定义的别名(alias)等。
调试器设置:包括符号文件路径,可执行映像文件路径,源文件路径,用 l+/l-命令设置
的源文件选项,日志文件设置,通过启动内核调试对话框设置内核调试连接设置,最近
一次打开文件对话框所使用的路径,和输出设置等。
WinDBG 图形界面信息:包括 WinDBG 窗口的标题,是否自动打开反汇编窗口,缺省字
体,WInDBG 窗口在桌面的位置,打开的 WinDBG 子窗口,每个打开窗口的详细信息,
包括位置,浮动状态等,命令窗口的设置,是否显示状态条和工具条,寄存器窗口的定
制信息,源文件窗口的光标位置,变量观察窗口的变量信息等等。
除了以上信息外,命名的工作空间还可以保存调试会话的状态,对于调试转储文件和调试新
创建进程的情况,打开对应的工作空间,WinDBG 可以自动重新开始调试会话。
30.1.3 存储存储存储存储
WinDBG 缺省使用注册表来保存工作空间设置。其路径为:
HKEY_CURRENT_USER\Software\Microsoft\Windbg\Workspaces
在这个键下通常有四个子健 User、Kernel、Dump 和 Explicit(参见图 30-1),前三个子
键分别用来保存用户态调试、内核态调试、调试转储文件时使用的缺省工作空间,Explicit 用来
保存命名的工作空间。
2
图 30-1 注册表中保存 WinDBG 工作空间的子键
在以上四个子键下的每个键值对应于一个工作空间,键值名是工作空间的名称,键值值就是
这个工作空间的二进制数据。
WinDBG 支持使用文件来保存工作空间。使用 File 菜单的 Save Workspace to File 功能就能将
当前的工作空间保存为一个.WEW 文件。这个文件是二进制的,其格式与注册表中的数据是一样
的。
30.1.4 应用应用应用应用
启动 WinDBG 时可以通过-W 开关指定要使用的工作空间名称,也可以通过 File 菜单来打开
一个工作空间以显式的加载这个工作空间的设置。
值得说明的是,工作空间中的除了图形界面以外的大多数设置都是以累积方式被应用的。
WinDBG 启动时,它便应用缺省的基础设置,而后加载新的工作空间时,WinDBG 只是加载这个
新工作空间中的特别内容。
30.1.5 删除删除删除删除
通过 WinDBG 的 File 菜单的 Delete Workspaces 可以删除工作空间。另一种更快速的方法就是
使用注册表编辑器(regedit)直接删除注册表中上文所述位置的键值。如果要删掉全部,那么就
把 Workspaces 键全部删除。可以不用担心缺省的工作空间删掉会影响 WinDBG 运行,下次使用
时它会自动为缺省工作空间创建新的键值。
30.1.6 主题主题主题主题
WinDBG 程序目录中的 Themes 子目录中包含了四种经过定制的工作空间设置(主要是窗口
布局),称为主题(Theme)。每个主题配备了一个.reg 文件和一个.WEW 文件。将.reg 文件导入到
注册表或者使用 WinDBG 打开.WEW 文件(Open Workspace in File)便可以应用对应的主题。读
者可以以这些主题为基础,经过调整,然后保存为自己所喜欢的设置。
30.2 命令命令命令命令概览概览概览概览
WinDBG 主要是以命令方式工作的,本节我们将概括性的介绍 WinDBG 的三类命令分类:
WinDBG 共支持三类命令:标准命令、元命令和扩展命令。
,然后介绍不同形式的命令行提示符。
3
30.2.1 标准标准标准标准命令命令命令命令
标准命令通常是一两个字符(version 除外)或者符号,用来提供适用于各种调试目标的最基
本调试功能。标准命令是不分大小写的。以下是根据功能归纳的当前版本 WinDBG 所支持的所有
标准命令:
控制调试目标执行,包括恢复运行的 g 命令、跟踪的 t 命令(trace into)和 p 命令(step
over);
观察和修改寄存器的 r 命令;
观察、编辑和搜索内存数据的 d 命令、e 命令和 s 命令;
观察栈的 k 命令;
设置和维护断点的 BP(软件断点)、BA(硬件断点)、BL(列出所有断点)和 BC/BD/BE
(清除、禁止和重新启用断点)命令;
显示和控制线程的~命令;
显示进程的|命令;
显示表达式的?命令和显示 C++表达式的??命令;
用于汇编的 a 命令和用于反汇编的 u 命令;
显示段选择子的 dg 命令;
执行命令文件的$命令;
设置调试事件处理方式的 sx 命令;
显示调试器和调试目标版本的 version 命令;
检查符号的 x 命令,搜索符号的 ln 命令,和显示模块列表的 lm 命令;
结束调试会话的 q 命令。
值得说明的是上面某些单字符的命令代表了一系列以这个字符开始的双字符命令,比如 d 命
令后面通常带上第二个字符来指定数据的显示长度,比如 db(按字节显示)、dd(按双字显示)
等。
在命令行输入一个问号(?)可以显示出一个标准命令的列表和简单介绍。
30.2.2 元命令元命令元命令元命令
元命令(Meta-Command)用来提供标准命令没有提供的调试功能,与标准命令一样,元命
令也是内建在调试器引擎或者 WinDBG 程序文件中的。
所有元命令都以一个点(.)开始,所以元命令也被称为点命令(Dot Command)。
按照功能,可以把元命令分成如下几类:
显示或者设置调试会话或者调试器选项,比如用于符号选项的.symopt,用于符号路径
的.sympath 和.symfix,用于源程序文件的.srcpath、.srcnoise 和.srcfix,用于扩展命令模块
路径的.extpath,用于匹配扩展命令的.extmatch,用于可执行文件的.exepath,设置反汇编
选项的.asm,控制表达式评估器的.expr 命令,等等。
控制调试会话或者调试目标,如重新开始调试会话的.restart,放弃用户态调试目标(进
程)的.abandon,创建新进程的.create 命令和附加到存在进程的.attach 命令,打开转储文
件的.opendump,分离调试目标的.detach,用于杀掉进程的.kill 命令,等等。
管理扩展命令模块,包括加载模块的.load 命令,卸载用的.unload 命令和.unloadall 命令,
显示已经加载模块的.chain 命令等。
管理调试器日志文件,如.logfile(显示信息)、.logopen(打开)、.logappend(追加)、.logclose
4
(关闭)。
远程调试,如用于启动 remote.exe 服务的.remote 命令,启动引擎服务器的.server,列出
可用服务器的.servers 命令,用于向远程服务器发送文件的.send_file,用于结束远程进程
服务器的.endpsrv,用于结束引擎服务器的.endsrv 命令,等等。
控制调试器,如让调试器睡眠一段时间的.sleep 命令,唤醒处于睡眠状态的调试器的.wake
命令,启动另一个调试器来调试当前调试器的.dbgdbg 命令,等等。
编写命令程序,包括一系列类似 C 语言关键字的命令,
如.if、.else、.elsif、.foreach、.do、.while、.continue、.catch、.break、.continue、.leave
、.printf、.block 等。我们将在第 10 节介绍命令程序的编写方法。
显示或者转储调试目标数据,如产生转储文件的.dump 命令,将原始内存数据写到文件
的.writemem 命令,显示调试会话时间的.time 命令,显示线程时间的.ttime 命令,显示任
务列表的.tlist(task list)命令,以不同格式显示数据的.fromats 命令,等等。
输入.help 可以列出所有元命令和每个命令的简单说明。
30.2.3 扩展命令
扩展命令
扩展命令扩展命令
扩展命令(Extension Command)用于扩展某一方面的调试功能。与标准命令和元命令是内建
在 WinDBG 程序文件中不同,扩展命令是实现在动态加载的扩展模块(DLL)文件中的。
通过 WinDBG 的 SDK,用户可以编写自己的扩展模块和扩展命令。WinDBG 程序包中包含
了常用的扩展命令模块。并存放在以下几个子目录中:
NT4CHK – 用于 Windows NT 4.0 Checked 版本的扩展模块。
NT4FRE – 用于 Windows NT 4.0 Free 版本的扩展模块。
W2KCHK – 用于 Windows 2000 Checked 版本的扩展模块。
W2KFRE –用于 Windows 2000 Free 版本的扩展模块。
WINXP - 用于 Windows XP 或者更高版本的 Windows 的扩展模块。
WINEXT – 适用所有 Windows 版本的扩展模块。
表 30-1 列出了 WINEXT 和 WINXP 木立中的的扩展些模块的名称和简单描述。
表 30-1 WinDBG 工具包中的扩展命令模块
扩展模块
描述
路径
WINEXT 适用于各种调试目标的常用扩展命令。
WINEXT 内核态调试时的常用扩展命令。
WINEXT 用户态调试时的常用扩展命令。
WINEXT 用于监视和记录 API 调用(Windows API Logging Extensions)。
WINEXT 用于调试托管代码和.Net 程序。
WINEXT 用于调试内核流(Kernel Stream)。
WINEXT 调试使用 WDF(Windows Driver Foundation)编写的驱动程序。
用于 ACPI 调试,追踪调用 ASL 程序的过程,显示 ACPI 对象。
关 于 堆 ( !heap )、 进 程 / 线 程 结 构 ( !teb/!peb )、 安 全 信 息
(!token、!sid、!acl)、和应用程序验证(!avrf)等的扩展命令。
包含了大量用于内核调试的扩展命令。
用于调试文件系统的过滤驱动程序(FsFilter)。
用于调试 AIC78xx 小端口(miniport)驱动程序。
用于调试网络有关驱动程序。
WINXP
WINXP
WINXP
WINXP
WINXP
WINXP
ext.dll
kext.dll
uext.dll
logexts.dll
sos.dll
ks.dll
wdfkd.dll
acpikd.dll
exts.dll
kdexts.dll
fltkd.dll
minipkd.dll
ndiskd.dll
5
ntsdexts.dll
rpcexts.dll
scsikd.dll
traceprt.dll
vdmexts.dll
WINXP
WINXP
WINXP
WINXP
WINXP
wow64exts.dll
WINXP
wmitrace.dll
实现了!handle、!locks、!dp、!dreg(显示注册表)等命令。
用于 RPC 调试。
用于调试 SCSI 有关的驱动程序。
用于格式化 ETW 信息。
调试运行在 VDM 中的 DOS 程序和 WOW 程序。
调试运行在 64 位 Windows 系统中的 32 位程序。
显示 WMI 追踪有关的数据结构、缓冲区和日志文件。
WINXP
DDK 中* 用于调试使用 UMDF 编写的用户态驱动程序。
WudfExt.dll
*目前的 WinDBG 工具包尚未包含这个扩展模块。
执行扩展命令时,应该以叹号(!)开始,叹号在英文中被称为 bang,因此扩展命令也被称
为 Bang Command。
执行扩展命令的完整格式是:
![扩展模块名].<扩展命令名> [参数]
其中扩展模块名可以省略,如果省略,WinDBG 会自动在已经加载的扩展模块中搜索这个命
令的实现。
因为扩展命令是实现在动态加载扩展模块中的,所以执行时需要加载对应的扩展模块。当调
试目标被激活时,WinDBG 会根据调试目标的类型和当前的工作空间,自动加载某些扩展模块。
此外,也可以使用以下方法来加载扩展模块:
使用.load 命令加上扩展模块的完整路径来加载它。
使用.loadby 命令加上扩展模块的名称,WinDBG 会自动到当前配置中定义的扩展模块所
有路径中搜索匹配的模块。
当使用“!扩展模块名.扩展命令名”的方式执行扩展命令时,WinDBG 会自动搜索和加
载指定的模块。
使用.chain 命令可以列出当前加载的所有扩展模块。使用.unload 和.unloadall 命令可以卸载指
定的或者全部扩展模块。
30.3 用户界面
用户界面
用户界面
用户界面
本节我们将介绍 WinDBG 的基本用户界面特别是命令窗口的用法,包括命令提示符的含义,
和输入命令的一些基本常识。
30.3.1 窗口概览
窗口概览
窗口概览窗口概览
WinDBG 是个典型的 Windows 窗口程序(图 30-1),最外层是框架窗口,框架窗口的用户区
上边是菜单和工具条,下边是状态条,中部可以自由摆放不确定数量的工作窗口。
6
图 30-1 WinDBG 的基本用户界面
图 30-1 中打开了四个常用的子窗口,分别是反汇编窗口、内存窗口、命令窗口和寄存器窗口,
其中内存窗口与反汇编窗口共享一个区域,目前没有完全显示出来。通过 View 菜单或者热键还
可以打开其它窗口。表 30-1 列出了目前版本的 WinDBG 的所提供能所有类型的工作窗口的名称、
热键、和用途。
表 30-1 WinDBG 的工作窗口
名称
热键
Command
Watch
Locals
Registers
Memory
Call Stack
Disassembly
Scratch Pad
Processes and Threads
Alt+1
Alt+2
Alt+3
Alt+4
Alt+5
Alt+6
Alt+7
Alt+8
Alt+9
Command Browser
Alt+N
用途
输入命令、显示命令结果和调试信息输出
观察指定全局变量、局部变量和寄存器的信息
自动显示当前函数的所有局部变量
观察和修改寄存器的值
观察和修改内存数据
栈中记录的函数调用序列
反汇编
白板,可以用来做调试笔记等
显示所有调试目标的列表,包括进程和线程等
执行和浏览命令
图 30-2 显示了图 30-1 中的各个 WinDBG 窗口的窗口属性(句柄、标题、窗口类)以及它们
的相互关系。
图 30-2 WinDBG 窗口的亲子关系
7
从图中可以看到,最顶层是窗口类 WinDbgFrameClass 的一个实例,它有三个子窗口,分别
是工具条、状态条和一个 DockClass 类型的子窗口 Dock0。Dock0 又有 5 个子窗口,即我们打开
的 5 个工作窗口。
WinDBG 支持两种方式来摆放工作窗口,一种是浮动方式(floating),另一种是码放(dock)。
对于浮动方式,WinDBG 提供了自动水平平铺、垂直平铺和级联(Cascade)功能。
对于码放方式,所有工作窗口填充在图 30-2 中的 DockClass 窗口中。用户可以使用鼠标来调
整子窗口的大小和位置。图 30-1 所示的情况使用的是码放方式。
可以把窗口布局保存到工作空间中,这样下次再打开这个工作空间时,WinDBG 会自动打开
上次使用的子窗口并恢复到保存时的状态。
命令窗口和命令提示符
30.3.2 命令窗口
和命令提示符
命令窗口命令窗口
和命令提示符
和命令提示符
命令窗口是 WinDBG 最主要的人机接口。它主要由上下两个部分组成:上部的信息显示区和
下面的命令条。命令条又分为左右两个部分:左边是命令提示符,右边是命令编辑框。
信息显示区是 WinDBG 输出各种调试信息的主要场所,包括命令的执行结果、调试事件、错
误信息等。
WinDBG 的命令提示符由一系列文字和大于号两部分组成。因为大于号是固定不变的,所以
我们接下来只讨论文字部分。
根据调试目标的类型和调试会话状态的不同,命令提示符的内容也会不同。下面我们分别做
详细讨论。
首先,如果调试器处于繁忙状态,那么命令提示符的内容是*BUSY*。繁忙状态通常有三种
情况:调试目标处于运行状态,(内核调试时)尚未与调试目标建立起连接,调试器正在加载符号
或者处理上一个命令。
图 30-2
图 30-3
第二,如果目前没有任何调试目标,那么命令提示符是 No Target。
8