cc682/NetRoc
http://netroc682.spaces.live.com/
调试器操作
本节包含以下主题:
启动调试器
调试器命令窗口
WinDbg图形界面
调试器配置
调试器操作(常规)
调试器操作(用户模式)
调试器操作(内核模式)
调试器扩展
远程调试
启动调试器
启动了CDB,KD或者WinDbg之后,有几种办法可以选择调试目标。
KD和CDB都和目标一起启动,当会话结束时,调试器也会退出。
另一方面,WinDbg可以在未选择目标的情况下启动。可以从命令提示符启动,或者从开始菜单打开Debugging Tools for Windows 并选择WinDbg 。也可以不用退出WinDbg就停止WinDbg调试会话。如果未指定目标就打开WinDbg或者停止WinDbg的会话,它会进入静止模式(dormant mode)。在这个模式下,可以选择调试目标并开始一个新的会话。
本节描述了下面一些方法用于启动调试会话。每种方法都包括启动新调试器或者在静止的WinDbg中选择目标。
附加到运行中的进程(用户模式)
创建一个新进程(用户模式)
非侵入式调试(用户模式)(Noninvasive Debugging)
附加到目标机(内核模式)
附加到虚拟机(内核模式)
通过内核调试器控制用户模式调试器
打开崩溃转储(Crash Dump)
也可以按如下方法开始调试会话:
- 连接到调试服务器来加入远程调试会话。关于这种方法的更多信息,查看激活调试客户端。
- 当用户模式进程出错时,可以自动打开调试器。这种方法的更多信息,查看启用即时调试。
- 可以通过加载命名的工作空间(workspace)来恢复以前的调试会话。关于该方法的更多信息,查看使用工作空间。
附加到运行中的进程(用户模式)
如果用户模式应用程序已经在运行了,调试器可以附加到这个进程并调试它。通常需要用操作系统指派的称为进程ID(PID)的十进制数字来指定这个程序。
也可以通过包含文件扩展名在内的完整名字来指定进程。但是,如果两个进程有相同的名字时,必须使用进程ID。 (关于如何找到进程ID和进程名,查看查找进程ID)。
下节描述了几种附加到进程的方法。
CDB命令提示符
在CDB命令提示符附加到运行中的进程,以如下语法使用-p选项和进程ID。
cdb -p ProcessID
或者使用下面的语法通过进程名附加。
cdb -pn ProcessName
还有一些其它有用的命令行选项。例如,可以使用-psn选项来指定要调试的进程所包含的服务名。关于命令行语法的更多信息,查看CDB命令行选项。
WinDbg 命令提示符
通过WinDbg命令提示符附加到运行中的进程,按如下语法指定-p选项和进程ID。
windbg -p ProcessID
或者按下面的语法通过进程名附加。
windbg -pn ProcessName
还有一些其它有用的命令行选项。例如,可以使用-psn选项来指定要调试的进程所包含的服务名。关于命令行语法的更多信息,查看WinDbg 命令行选项。
WinDbg 菜单
当WinDbg在静止模式时,可以通过在File菜单中选择Attach to a Process 或者按F6来附加到运行中的进程。
Attach to Process 对话框出现时,选择包含想调试的进程ID和名字的一行,(也可以在Process ID 文本框中输入进程ID。)然后点击OK。
调试器命令窗口
如果调试器已经打开,可以在调试器命令窗口使用.attach (附加到进程)命令来附加到运行中的进程。
如果CDB是静止的或者已经在调试一个或多个进程,也可以使用.attach命令。如果WinDbg是静止的,则不能使用该命令。
多个目标进程总是一起执行的,除非它们的一些现成被冻结或暂停。
如果.attach 命令成功,调试器会在下一次执行命令的时候附加到指定进程。如果在一行中使用了这个命令多次,则每一条.attach命令都需要执行一次其他命令。
非侵入式调试
如果想调试运行中的程序,并且只对它的执行造成最小的影响,可以非侵入式(noninvasively)调试该进程。
开始调试会话
关于如何开始调试会话的更多信息,查看调试器配置, 符号, 调试器操作(常规)和 调试器操作(用户模式)。
调试器创建的进程行为和通常条件下不同。更多关于这些种类进程的信息,查看被创建进程的行为。
在Microsoft Windows XP和之后的Windows系统中,如果调试器停止相应或者冻结了,可以将一个新的调试器附加到目标进程上。关于如何在这种情况下附加调试器的更多信息,查看重新附加目标进程。
创建一个新进程(用户模式)
调试器可以启动用户模式程序并调试它。如同在命令提示符或者Microsoft Windows系统的运行对话框启动一样,使用名字来指定程序。
调试器也可以自动附加到子进程(child processes) (目标进程创建的另一个进程)。
本主题的下一小节描述了开始新进程的几种方法。
CDB 命令提示符
在CDB命令提示符下启动用户模式程序,需要按如下形式在CDB命令的最后插入对应用程序的命令行。
cdb [-o] ProgramName [Arguments]
-o 选项使得调试器附加到子进程。还有一些其它有用的命令行选项。关于命令行语法的更多信息,查看CDB命令行选项。
WinDbg 命令提示符
在WinDbg命令提示符下启动用户模式程序,需要按如下形式在WinDbg命令的最后插入对应用程序的命令行。
windbg [-o] ProgramName [Arguments]
-o 选项使得调试器附加到子进程。还有一些其它有用的命令行选项。关于命令行语法的更多信息,查看 WinDbg命令行选项。
WinDbg 菜单
当WinDbg在静止模式时,可以在File菜单中点击Open Executable或者按下CTRL+E来启动新进程。
当Open Executable 对话框出现时,在File name文本框里输入可执行文件的完整路径或者使用Look in列表框来选择路径和文件。 (如果在运行对话框或命令提示符窗口中创建进程,Windows会在命令路径下搜索可执行文件,但是Open Executable 对话框需要精确的路径。)
如果想为用户模式程序使用任何命令行参数,可以在Arguments 文本框中输入。如果要修改掉默认的运行目录,在Start directory 中输入。如果希望WinDbg附加到子进程,选上Debug child processes also 选择框。
选择完成后,点击Open。
调试器命令窗口
如果调试器已经激活,可以通过调试器命令窗口中输入.create (创建进程)命令来创建新进程。
如果CDB在静止状态或者已经在调试一个或多个进程,可以使用.create 命令。不能在WinDbg静止时使用。
多个目标进程总是一起执行的,除非它们的一些现成被冻结或暂停。
如果. create命令成功,调试器会在下一次执行命令的时候创建指定进程。如果在一行中使用了这个命令多次,则每一条.create命令都需要执行一次其他命令。
可以在.create之前先使用.createdir (设置被创建进程目录)命令来设置程序的启动目录。可以用.createdir –I命令或-noinh 命令行选项来控制目标程序是否继承调试器的句柄。
在Windows XP和之后版本的Windows系统中,可以使用.childdbg (调试子进程)命令来启用或禁用对子进程的调试。
开始调试会话
关于如何开始调试会话的更多信息,查看调试器配置, 符号, 调试器操作(常规)和 调试器操作(用户模式)。
在Microsoft Windows XP和之后的Windows系统中,如果调试器停止相应或者冻结了,可以将一个新的调试器附加到目标进程上。关于如何在这种情况下附加调试器的更多信息,查看重新附加目标进程。
非侵入式调试(用户模式)
如果用户模式应用程序正在运行,调试器可以非侵入式的调试它。在非侵入式调试下,调试动作会少一些。但是,可以将调试器对目标程序的影响降到最低。
在非侵入式调试下,调试器实际上并没有附加到目标程序。调试器暂停目标的所有线程并访问它的内存、注册表和其他信息。但是,调试器不能控制目标,所以类似g (运行) 这样的命令都不能工作。
如果在非侵入式调试时试图执行不允许的命令,会收到这样的错误信息: "The debugger is not attached, so process execution cannot be monitored."
结束调试会话时,调试器释放目标程序,并且目标程序继续运行。可以使用q (退出), .detach (取消进程附加)或者WinDbg的 Debug | Detach Debuggee 或 Debug | Stop Debugging 命令来关闭会话。 (如果通过关闭调试器窗口,或者使用WinDbg的File菜单的Exit命令,目标进程一般会停止响应。)
如果当目标程序运行在Microsoft NT或Windows 2000下,并且希望结束会话时不结束它,非侵入式调试是很有用的。(这些系统上如果调试器附加到了目标就不能再取消附加。) 非侵入式调试在当目标程序停止相应并且不能打开附加时需要的中断线程时也很有用。
选择要调试的进程
可以通过进程ID(PID)或进程名来指定目标程序。
如果用名字指定程序,则会要使用进程包含扩展名在内的的完整名字。如果两个进程有相同的名字,则必须使用进程ID。
关于如何找到进程ID和进程名,查看查找进程ID。
下小节描述了进行非侵入式调试的几种方法。
CDB 命令提示符
使用CDB命令提示符对运行中进程进行非侵入式调试,用如下语法使用-pv 、-p 选项和进程ID。
cdb -pv -p ProcessID
或者按照如下语法用进程名指定。
cdb -pv -pn ProcessName
还有一些其它有用的命令行选项。关于命令行语法的更多信息,查看CDB命令行选项。
WinDbg 命令提示符
使用WinDbg命令提示符对运行中进程进行非侵入式调试,用如下语法使用-pv 、-p 选项和进程ID。
windbg -pv -p ProcessID
或者按照如下语法用进程名指定。
windbg -pv -pn ProcessName
还有一些其它有用的命令行选项。关于命令行语法的更多信息,查看WinDbg命令行选项。
WinDbg 菜单
当WinDbg在静止模式时,可以点击File菜单的Attach to a Process 或者按F6来对运行中进程进行非侵入式调试。
Attach to Process 对话框出现时,选中Noninvasive 选择框。然后选中包含目标进程ID和名字的一行。(也可以在Process ID文本框自己输入进程ID)。最后,点击OK。
调试器命令窗口
如果调试器已经激活,可以使用调试器命令窗口输入.attach -v (附加到进程) 命令进行非侵入式调试。
可以在调试器已经在对一个或多个进程进行侵入式调试的情况下使用.attach 命令。也可以在CDB静止的时候使用,但是不能在WinDbg静止时使用。
如果.attach -v 命令成功,调试器会在自己执行下一条命令时开始调试指定进程。因为非侵入式调试不允许被调试进程执行,所以一次只能对一个进程进行非侵入式调试。这也意味着.attach -v 命令可能使得已存在的其他侵入式调试会话受到限制。
开始调试会话
关于如何开始调试会话的更多信息,查看调试器配置, 符号, 调试器操作(常规)和 调试器操作(用户模式)。
附加到目标机(内核模式)
在使用KD或者WinDbg开始内核调试之前,必须指定如何连接到目标机。
下面小节描述了附加到目标机的一些方法。
KD命令提示符
使用下面的命令之一来通过KD命令提示符开始内核调试会话。
kd [-y SymbolPath] -k com:port=ComPort,baud=BaudRate
kd [-y SymbolPath] -k 1394:channel=1394Channel[,symlink=1394Protocol]
kd [-y SymbolPath] -k usb2:targetname=String
kd [-y SymbolPath] -k com:modem
kd [-y SymbolPath] -kl
kd [-y SymbolPath]
如果不包含-k命令行选项,连接选项由特定的环境变量决定。关于内核调试连接选项和他们使用上的限制的更多信息,查看选择内核调试设置。关于其他选项的信息,查看KD命令行选项。
在会话开始之后还能通过CTRL+A修改内核调试连接的波特率。
WinDbg命令提示符
使用下面的命令来通过WinDbg命令提示符开始内核调试会话。
windbg [-y SymbolPath] -k com:port=ComPort,baud=BaudRate
windbg [-y SymbolPath] -k 1394:channel=1394Channel[,symlink=1394Protocol]
windbg [-y SymbolPath] -k usb2:targetname=String
windbg [-y SymbolPath] -k com:modem
windbg [-y SymbolPath] -kl
windbg [-y SymbolPath] -k
如果不包含-k命令行选项,关于内核调试连接选项和他们使用上的限制的更多信息,查看选择内核调试设置。关于其他选项的信息,查看 WinDbg命令行选项。
在调试会话开始之后,还可以通过点击Debug | Kernel Connection | Cycle Baud Rate 命令或者按下CTRL+ALT+A来修改波特率。
WinDbg 菜单
当WinDbg在静止模式时,可以通过点击File菜单的Kernel Debug或者按下CTRL+K来开始内核调试会话。
当Kernel Debugging 对话框出现时,点击COM 、1394或Local选项卡。每个选项卡都指定了不同的连接方式。关于这个对话框的更多信息,查看File | Kernel Debug。
如果让Kernel Debugging 对话框中的内容都为空,则由特定的环境变量来设置连接。关于这些设置的更多信息,查看选择内核调试设置。
开始会话
在主控机一端的调试器启动并等待连接之后,启动目标机。如果目标机的Boot.ini文件中启用了调试器(在编辑Boot.ini文件中描述),目标机的调试器会在启动早期就自动连接上来。
如果目标机停止响应,可能是因为较早之前的内核调试动作造成的等待,或者使用了-b 命令行选项,调试器立即中断了目标机。
否则,目标及会继续运行,直到调试器的中断。
关于之后的步骤的更多信息,查看调试器配置, 符号, 调试器操作(常规)和调试器操作(内核模式)。
1394 配置
如果是在启用1394调试连接之后第一次启动内核调试器,一个驱动程序将会安装到主控机上。必须在进行这次调试会话时以管理员登陆目标机。关于该驱动的更多信息,查看安装1394虚拟驱动。
还必须为1394电缆内核调试配置目标机。关于配置的更多信息,查看禁用1394控制器。
附加到虚拟机(内核模式)
KD和WinDbg可以对虚拟机进行内核调试。虚拟机可以运行在调试器同一台物理机器上,或者在连接到相同网络的另一台机器上。
在开始调试之前,需要在虚拟机上创建一条命名管道。调试器通过该管道进行连接。关于如何创建管道,查看所使用的虚拟机文档。
注意 如果使用VMWare的功能来重起虚拟机(例如,重起按钮),需要退出WinDbg并重新打开WinDbg来继续调试。
在进行虚拟机调试时,VMWare通常会占用100%的CPU资源。
开启调试器
如果虚拟机和调试器运行于同一台物理计算机,使用下面的命令之一来开始调试会话。
kd [-y SymbolPath] -k com:pipe,port=\\.\pipe\PipeName[,resets=0][,reconnect]
windbg [-y SymbolPath] -k com:pipe,port=\\.\pipe\PipeName[,resets=0][,reconnect]
如果虚拟机和调试器运行在不同的计算机上,需要使用下面的命令之一来启动会话。
kd [-y SymbolPath] -k com:pipe,port=\\VMHost\pipe\PipeName[,resets=0][,reconnect]
windbg [-y SymbolPath] -k com:pipe,port=\\VMHost\pipe\PipeName[,resets=0][,reconnect]
命令包含以下一些参数:
VMHost
指定运行虚拟机的机器名字。虚拟机文档中通常以virtual machine host 来引用这台计算机。如果虚拟机和内核调试器在同一台主机,则VMHost为一个点号(.)。
PipeName
指定虚拟机创建的命名管道名。
resets=0
指定当主控机和目标机重新同步时,发送给目标机的重置包个数,这个数字没有限制。对于Microsoft Virtual PC和其他丢弃管道中多余数据的虚拟机,使用resets=0 参数。对于VMware 或其他不丢弃管道的多余数据的虚拟机,不要这样使用。
reconnect
指定调试器当管道读/写错误时,自动断开并重连。另外,如果调试器在启动时没有找到指定的管道名,reconnect 参数使得调试器一直等待名为PipeName 的管道出现。对Virtual PC和其他在重起虚拟机时销毁并重建管道的虚拟机使用reconnect 。对于VMWare和其他在重起计算机时保留管道的虚拟机不要使用该参数。
关于其他命令行选项,查看KD命令行选项或者WinDbg命令行选项。
开始会话
在主控机一端的调试器启动并等待连接之后,启动目标机。如果目标机的Boot.ini文件中启用了调试器(在编辑Boot.ini文件中描述),目标机的调试器会在启动早期就自动连接上来。
如果目标机停止响应,可能是因为较早之前的内核调试动作造成的等待,或者使用了-b 命令行选项,调试器立即中断了目标机。
否则,目标及会继续运行,直到调试器的中断。
关于之后的步骤的更多信息,查看调试器配置, 符号, 调试器操作(常规)和调试器操作(内核模式)。
通过内核调试器控制用户模式调试器
可以将用户模式调试器的输入输出重定向到内核调试器。这使得内核调试器可以控制目标机上的特定用户模式调试会话。 (在这种情况下可以使用KD或者WinDbg来作为内核调试器。)
可以使用CDB或NTSD作为用户模式调试器。NTSD 由于只对处理器和被调试程序运行的操作系统造成很小的负担,所以是相当强大的用户模式调试器。事实上,当NTSD在内核调试器控制下启动时,不会创建NTSD的窗口。通过NTSD,可以在引导过程的早期和关闭过程的末期通过串口进行用户模式调试。
通过内核调试器控制用户模式调试器对于调试系统进程非常有用。关于该技术的示例,查看通过NTSD调试CSRSS和 通过NTSD调试WinLogon。
也可以使用该技术来为非交互式服务设置即时调试器以调试停止错误(确切的说是,崩溃)。在Windows Vista和Windows Server 2008上,服务运行在会话0(session 0)中。交互式用户不能访问会话0,所以可以使用本地即时调试器来进行交互式的调试。要使用及时调试器交互式的调试服务,将调试器输出重定向到内核模式是非常有用的。
但是,如果符号存放在远程服务器时,对于非交互式服务的即时调试可能会失败,因为当内核调试器在等待输入时很难维持对符号的连贯访问。在这种等待中,系统可能产生妨碍符号服务器验证的始终误差。这种情况下,使用如下命令来设定即时调试器。
<debugger> -iaec -server npipe:pipe=dbg%x -ddefer -noio
当某个事件引发即时调试时,上述的命令用即时调试器的进程ID(PID)来替代%x 以生成唯一服务器名字,并且中断到内核调试器要求输入。这时,可以使用.sleep (暂停调试器)命令来从内核模式调试器中断中启用系统足够长时间以连接到新创建的服务器。通过使用!process 内核调试器扩展命令,可以找到用户模式调试器道德PID,并打开到明确定义的服务器名字(dbg<PID>)的连接。当用户模式调试器从.sleep命令被唤醒时,它会检测到远程连接,并从该连接获取输入,而不是在此中断到内核。这时,就可以通过新连接的远程调试器来交互式的调试系统服务并稳定访问符号。
如果调试用户模式应用程序并且必须使用一些内核模式调试的功能来分析问题时,可能仍然希望从内核调试器控制用户模式调试器。
注意 在这里描述中,目标程序指被调试的用户模式应用程序,目标机指包含目标程序和CDB、NTSD进程的计算机,主控机指运行内核调试器的计算机。
启动调试会话
要使用该技术,必须如下操作(按任一顺序):
-
在主控机上启动WinDbg或KD,和想调试目标机时类似,但是不要实际中断目标机。
kd [-y SymbolPath] [-k ConnectionOptions]
这一步的更多信息,查看附加到目标机(内核模式)。
-
在目标机上启动CDB或NTSD,并使用-d,命令行选项。可以按如下语法附加到运行中的进程。
ntsd -d -p PID
或者按如下语法启动新进程调试。
ntsd -d ApplicationName
关于这一步的更多信息,查看附加到运行中的进程(用户模式)或 创建新进程(用户模式)。
如果使用CDB,CDB关联到的命令提示符窗口在调试进行时保持锁定并不可用。如果使用NTSD,不会有另外的窗口创建出来,但是目标机上会有NTSD的进程ID。
如果想通过内核调试器运行用户模式调试器,并且将它作为调试服务器,必须用-ddefer 命令行替代-d。使用-ddefer时,用户模式调试器从调试客户端获得输入。如果没有这样的输入可用,调试器从内核调试器获得输入。关于调试客户端和调试服务器的更多信息,查看通过调试器进行的远程调试。
切换模式
当从内核调试器控制用户模式调试器时,会遇到四种可能的模式:
用户模式调试
目标机和目标程序都冻结。在内核调试器的调试器命令窗口中会出现用户模式提示符。在WinDbg中,会在窗口下部显示Input>。可以在这里输入命令来分析目标程序的状态或者运行、单步执行,如同在用户模式调试时一样。 符号文件、扩展DLL和其他调试器访问的文件将在目标机上访问,而不是主控机。
目标程序执行
目标机运行,并且目标程序也在执行,调试器在等待状态。这和通常情况下让目标运行的状态一样。
睡眠模式
目标计算机在运行,但是目标程序和调试器被冻结。当想在目标机上作一些事情但是又不想改变调试会话的状态时,这种模式非常有用。
内核模式调试
目标机和目标程序都被冻结。内核调试器的调试器命令窗口出现内核模式调试提示符。这种模式是典型的内核调试状态。
在用户模式下启动的调试会话,下面的一些操作和事件会造成模式切换:
- 从用户模式调试状态切换到目标程序运行状态,使用g (Go) 命令。
- 使用单步、跟踪或其它临时执行命令,临时从用户模式调试状态切换为运行目标程序,然后又返回到用户模式调试。关于这些命令的列表,查看控制目标。
- 使用.sleep (暂停调试器)命令从用户模式调试切换到睡眠模式。该命令可以指定时间,当到达这个时间时,系统返回到用户模式调试状态。
- 使用.breakin (中断到内核调试器)命令从用户模式调试切换到内核模式调试。注意,如果调用的进程没有管理员权限时,.breakin 会因为拒绝访问的错误失败。这种情况下,应该使用一个短暂的.sleep命令切换到KD并按下CTRL+C。
- 可以在特定环境下从目标程序执行状态切换到用户模式调试状态。如果目标机运行Microsoft Windows XP或之后地Windows版本,可以使用!bpid 扩展命令。如果使用CDB(不是NTSD),可以在目标机激活CDB窗口并按下CTRL+C。
- 如果目标程序遇到断点、异常、其它控制事件或者结束,系统从目标程序执行状态切换到用户模式调试状态。需要预先计划好这样的事件,尤其在使用NTSD时。关于这些事件的详细信息,查看使用断点和 控制异常和事件。
- 从目标程序执行状态切换到内核模式调试状态,在KD窗口按下CTRL+C或者在WinDbg窗口中按下CTRL+BREAK或者点击Debug菜单中的Break按钮,或者在目标机键盘上按下SYSRQ或ALT+SYSRQ键。(如果内核调试器是KD,并且在内核调试器和用户模式调试器通信时按下了CTRL+C,用户模式调试器可能截获到按下的CTRL+C。)
- 如果调试器遇到内核错误,或者使用了breakin.exe工具,系统从目标程序执行状态切换到内核模式调试状态。
- 从睡眠模式切换到用户模式调试状态,可以等待睡眠时间结束、使用-wake 命令行选项在目标机启动一个新的CDB进程、或者在目标机上另一个CDB或NTSD中使用.wake (唤醒调试器) 命令。
- 要切换出内核模式调试,使用g (运行) 命令。该命令返回到用户模式调试或目标程序执行状态(最近一次的状态)。
打开崩溃Dump
调试器可以读取和分析由用户模式程序或者系统崩溃时生成的崩溃转储文件(crash dump file)。
关于如何使用KD、WinDbg或KAnalyze打开和分析内核模式崩溃dump文件的更多信息,查看分析内核模式Dump文件。
关于使用CDB或WinDbg打开和分析用户模式崩溃dump文件的更多信息,查看分析用户模式Dump文件。
关于Dump文件如何创建以及它的各种不同类型的说明,查看崩溃dump文件。