Windbg工作空间
WinDbg使用工作空间来描述和存储调试项目的属性、参数及调试器设置等信息。工作空间与vc中的项目文件很相似。WinDbg定义了两种工作空间,一种为默认工作空间,另一种为命名的工作空间。当没有明确使用某个命名空间时,WinDbg总是使用默认工作空间。
WinDbg在安装后就有预先创建了一些列默认空间。分别为基础工作空间、默认内核工作空间、默认远程调试工作空间、特定处理器工作空间、默认用户态工作空间。它们分别定义了在WinDbg在各种条件下的一些配置、参数设置等。
基础工作空间:当调试会话尚未建立,WinDbg处于闲置状态时,会使用此空间作为默认空间。
默认内核工作空间:当WinDbg开始内核调试,但是尚未与调试目标建立连接时,会使用此空间作为默认空间。
默认远程调试工作空间:当通过调试服务器进行远程调试时,会使用此空间作为默认空间。
默认的用户态工作空间:当使用WinDbg调试一个已运行的进程时,会使用这个空间作为默认工作空间。
当WinDbg打开一个应用程序开始调试时,调试器会 根据可执行文件的路径和文件名为其创建一个默认工作空间,如果已经存在工作空间,就使用已存在的。在WinDbg的文件菜单中可以使用另存为..创建一个命名的工作空间。
WinDbg的工作空间中保存了一下信息:
调试会话状态:包括,断点、打开的源文件、用户自定义别名。
调试器设置:符号文件、可执行文件路径、源文件路径等。
WinDbg图形界面信息:包括WinDbg窗口标题、默认字体、窗口在桌面的位置、打开的子窗口、以及每个子窗口的状态等。
WinDbg默认使用注册表来保存工作空间设置,其路径为:HKEY_CURRENT_USER/Software/Microsoft/WinDBG/Workspaces,在此路径下有四个键:User、Kernel、Dump和Explicit。前三个键分别用来保存用户态调试、内核态调试、调试转储文件时使用的默认空间。Explicit用以存储命名的工作空间。在四个键下的每个键对应于一个工作空间。键值名为工作空间的名称,键值就是这个工作空间的配置数据。
WinDbg支持使用文件来保存工作空间。这可以使用Save workspace to File。使用Delete workSpaces可以删除工作空间。更快的方法是直接删除保存在注册表中的键值。
WinDbg命令
WinDbg的大多数功能是使用命令方式工作的。命令分为三种:标准命令、元命令和扩展命令。
1、标准命令:提供适用于所有调试目标的基本调试功能。标准命令在调试器内部实现,执行时不需要加载任何扩展模块。标准命令第一个字符不区分大小写,后面的字符可能区分大小写。共有130多条命令,分为60多个系列18个子类:
一:控制调试目标执行,包括恢复运行的g系列命令。跟踪执行的t系列命令。单步执行的p系列命令和跟踪监视的wt命令。
二:观察和修改寄存器的r系列命令。
三:读写IO端口命令。
四:观察、修改和搜索内存数据的d系列、e系列和s命令。
五:观察栈的k系列命令。
六:显示进程的|(非l)命令。
七:显示和控制线程的~命令。
八:设置和维护断点的bp(软件断点),ba(硬件断点)和管理断点的bl(列出所有断点),bc,bd,be(清除,禁用和重新启用断点)命令。
九:评估表达式的?命令和评估C++表达式的??命令。
十:用于汇编的a命令和反汇编的u命令。
十一:显示段选择子的dg命令。
十二:执行命令文件的$命令。
十三:设置调试事件处理方式的sx系列命令,启用与禁止静默模式的sq命令,设置内核选项的so命令,设置符号后缀的ss命令。
十四:显示调试器和调试目标版本的version命令。显示调试目标所在系统信息的vertarget命令。
十五:检查符号的x命令。
十六:控制和显示源程序的ls系列命令。
十七:加载调试符号的ld系列命令。搜索相邻符号的ln命令。 显示模块列表的lm命令。
十八:结束调试会话的q命令。
在命令编辑框中输入?,可以显示主要标准命令和每个命令的简单介绍。
2、元命令:元命令用于提供标准命令没有提供的常用调试命令,元命令也是内建在调试器引擎或WinDbg程序文件中。所有元命令都是以.开始,所以元命令也被称为点命令。
按照功能,元命令可以分为一下几类:
一:显示和设置调试器会话和调试器选项,如符号选项.symopt,用于符号号路径的.sympath和.symfix。用于源程序文件的.srcpath、.srcnoise和.srcfix。用于扩展命令模块的路径的.extpath。用于匹配扩展命令的.extmatch。用于可执行文件的.exepath。设置反汇编选项的.asm。控制表达式评估器的.expr命令。
二:控制调试会话或调试目标。如重新开始的.restart命令。放弃用户态调试目标的.abandon。创建新进程的.create命令和附着在存在进程的.attach命令。打开转储文件的.opendump。分离调试目标的.detach。用于杀掉进程的.kill。
三:管理扩展命令模块。如加载模块的.load 命令。卸载模块的.unloead命令和.unloadall命令。显示已加载模块的.chain命令。
四:管理调试器日志文件。如.logfile(显示信息).logopen(打开文件)。.logappend(追加),和.logclose(关闭文件)。
五:远程调试命令。
六:控制调试器。如让调试器睡眠一段时间的.sleep命令。唤醒调试器的.wake命令。启动另一个调试器来调试当前调试器的.dbgdgb命令。
七:编写命令程序。包括一系列类似于C语言关键字的命令。如.if、.else、.elseif、.foreach、.do、.while、.continue、.catch、.break、.leave等。
八:显示或转储调试目标数据。如产生转储文件的.dump命令。将原始数据写到文件的.writemem命令。显示调试会话事件的.time命令。显示线程时间的.ttime命令。显示任务列表的.tlist命令。以不同格式显示数字的.format命令。
输入.help命令可以列出所有元命令和每个元命令的简单说明。
3、扩展命令:扩展命令用于实现针对特定目标的调试功能。与标准命令和元命令内建在Windbg程序文件中不同,扩展命令是是现在动态加载的扩展模块dll中。利用WinDbg的sdk,用户可以自己编写扩展模块和扩展命令。
执行扩展命令时应该以感叹号!开始。!在英语中为bang。因此扩展命令也被称为bang command。
执行扩展命令的完整格式:!nameofExtentModule.nameofExtentCommand 参数。
其中nameofExternModule可以省略。省略后,WinDbg会在已加载的扩展模块中搜索指定的命令。如果此模块没有加载,则将模块加载。
因为扩展命令是在扩展模块中实现的,所以执行时需要加载相应的模块。WinDbg可以根据调试目标的类型和当前的工作空间自动加载命令空间指定的扩展模块。用户也可以调用.load命令手动加载扩展模块。.load后跟模块路径。
除了.load之外,还可以使用.loadby命令加上扩展模块名称和一个已加载的程序模块的名称。这时,WinDbg会在已加载模块所在目录搜索扩展模块。
大多数扩展模块都支持使用help命令来显示这个模块的基本信息和所包含命令。如:!ext.help。
事件处理
Windows的调试模型是事件驱动的。调试目标是调试事件的发生源,调试器负责接收和处理调试事件,调试子系统负责将调试事件发送给调试器并为调试提供服务。简单来说,异常是调试事件的一种。因为有很多中异常,所以异常事件又分为多个子类。而其他调试事件却没有包含子类。
对于每个异常windows系统最多给予两轮处理机会,对于每一轮记录调试子系统都会试图先发给调试器,然后再寻找异常处理器。因此对于每个异常,调试器最多收到两次处理机会。每次处理后都应该向系统返回一个结果,说明它是否处理这个异常。
对于第一轮异常处理机会,调试器通常是返回没有处理异常。然后让调试子系统继续分发,交给程序中的异常处理器来处理。对于第二轮机会如果调试器不处理,那么系统便会终止应用程序执行或启用蓝屏机制停止整个系统。所以对于第二轮异常处理机会,调试器通常返回已经处理,让系统恢复程序执行。这通常会再次导致异常,又重新分发异常,如此循环。值得注意的是,对于断点和调试异常,调试器会在第一轮处理机会就返回已经处理。
Windbg将异常和其他调试事件一起处理,但只有异常事件有两轮处理机会,异常以外的事件只有一次处理机会。
大多数调试器都允许用户来定制处理调试事件的方式。因为异常事件最多有两轮处理机会。而且对于每一轮机会都需要决定如下几个问题:
一:当收到事件通知时是否中断给用户。
二:返回给系统的处理结果。是返回已处理还是没有处理,即所谓的处理状态。
三:第一轮机会是否中断给用户。
四:第二轮机会是否中断给用户。
五:第一轮机会的处理结果。
六:第二轮机会的处理机会。
前两个选项被称为中断选项。后两个被称为继续选项。
为了允许用户设置这些选项,不同调试器提供了不同形式的界面。下图为WinDbg调试器的事件配置 :
右下角的Execution组的四个单选按钮用来配置中断选项,它们的含义如下:
Enable:收到该事件后便中断给用户。对于异常事件,意味着两轮事件都中断给用户。对于其他事件,意味着收到便中断。
Disable:对于异常事件,第二轮机会时中断给用户。第一轮不中断。对于其他事件不中断。
Output:输出消息通知用户。
Ignore:忽略这个事件。
Continue组的两个单选按钮,用于配置返回给系统的异常事件处理状态,只适用于异常,且针对第一轮处理机会。如果选择Handled,那么便返回已经处理异常,否则返回没有处理异常。对于大多数异常,默认返回时没有处理异常。对于第二轮默认返回已经处理。WinDbg即允许配置中断选项也允许配置继续选项。但是vc只允许配置中断选项,不允许设置继续选项。
下图为vc2010调试器配置界面:
上图中,对于 每种异常,提供了两个复选框。分别为thrown(引发)和User-unhandled(用户未处理)。前者的含义是对于第一轮机会是否中断给用户。后者的含义是对于第二轮异常是否中断给用户。从上图也可以看出,我们无法配置继续选项。