WinDBG

什么是 WinDBG?
 
WinDbg 是微软开发的免费源码级调试工具。Windbg可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件。由于大部分程序员不需要做Kernel模式调试, 我在这篇文章中不会介绍Kernel模式调试。Kernel模式调试对学习Windows核心极有帮助。如果你对此感兴趣,可以阅读Inside Windows 2000和Windbg所带的帮助文件。
 
这篇文章得主要目的是介绍WINDBG的主要功能以及相关的命令。关于这些命令的详细语法,请参阅帮助文件。对文章中提到的许多命令,WINDBG有相应的菜单选项。
如何得到帮助
 
在命令(Command)窗口中输入.hh 命会调出帮助文件令。
 
.hh keyword
会显示关于keyword的详细命令。
 
启动 Debugger
 
Windbg 可以用于如下三种调试:
 
  1. 远程调试:你可以从机器A上调试在机器B上执行的程序。具体步骤如下:
?  在机器B上启动一个调试窗口(Debug Session)。你可以直接在Windbg下运行一个程序或者将Windbg附加(Attach)到一个进程。
?            在机器B的Windbg命令窗口上启动一个远程调试接口(remote):
.server npipe:pipe=PIPE_NAME
PIPE_NAME 是该接口的名字。
?    在机器A上运行:
windbg –remote npipe:server=SERVER_NAME,pipe=PIPE_NAME
SERVER_NAME 是机器B的名字。
  1. Dump文件调试:如果在你的客户的机器上出现问题,你可能不能使用远程调试来解决问题。你可以要求你的用户将Windbg附加到出现问题的进程上,然后在命令窗口中输入:
.dump /ma File Name
创建一个Dump文件。在得到Dump文件后,使用如下的命令来打开它:
windbg –z DUMP_FILE_NAME
 
  1. 本地进程调试:你可以在Windbg下直接运行一个程序:
Windbg “path to executable” arguments     
    也可以将Windbg附加到一个正在运行的程序:
    Windbg –p “process id”  
Windbg –pn “process name”
    注意有一种非侵入(Noninvasive)模式可以用来检查一个进程的状态并不进程的执行。当然在这种模式下无法控制被调试程序的执行。这种模式也可以用于查看一个已经在Debugger控制下运行的进程。具体命令如下:
    Windbg –pv –p “process id” 
Windbg –pv –pn “process name” 
      
调试多个进程和线程
 
如果你想控制一个进程以及它的子进程的执行,在Windbg的命令行上加上-o选项。Windbg中还有一个新的命令.childdbg 可以用来控制子进程的调试。如果你同时调试几个进程,可以使用 | 命令来显示并切换到不同的进程。
在同一个进程中可能有多个线程。~命令可以用来显示和切换线程。
 
调试前的必备工作
在开始调试前首先要做的工作是设置好符号(Symbols)路径。没有符号,你看到的调用堆栈基本上毫无意义。Microsoft的操作系统符号文件(PDB)是对外公开的。另外请注意在编译你自己的程序选择生成PDB文件的选项。如果设置好符号路径后,调用堆栈看起来还是不对。可以使用lm, !sym noisy, !reload 等命令来验证符号路径是否正确。
 
Windbg 也支持源码级的调试。在开始源码调试前,你需要用.srcpath设置源代码路径。如果你是在生成所执行代码的机器上进行调试,符号文件中的源码路径会指向正确的位置,所以不需要设置源代码路径。如果所执行代码是在另一台机器上生成的,你可以将所用的源码拷贝(保持原有的目录结构)的一个可以访问的文件夹(可以是网络路径)并将源代码路径设为该文件夹的路径。注意如果是远程调试,你需要使用.lsrcpath来设置源码路径。
 
静态命令:
显示调用堆栈 :在连接到一个调试窗口后,首先要知道的就是程序当前的执行情况k* 命令显示当前线程的堆栈。~*kb会显示所有线程的调用堆栈。如果堆栈太长,Windbg只会显示堆栈的一部分。.kframes可以用来设置缺省显示框架数。
 
显示局部变量 :接下来要做通常是用dv显示局部变量的信息。CTRL+ALT+V可以切换到更详细的显示模式。关于dv要注意的是在优化过的代码中dv的输出极有可能是不准确的。这时后你能做的就是阅读汇编代码来发现你感兴趣的值是否存储在寄存器中或堆栈上。有时后当前的框架(Frame)上可能找不到你想知道的数据。如果该数据是作为参数传到当前的方法中的,可以读一读上一个或几个框架的汇编代码,有可能该数据还在堆栈的某个地址上。静态变量是储存在固定地址中的,所以找出静态变量的值较为容易。.Frame(或者在调用堆栈窗口中双击)可以用来切换当前的框架。注意dv命令显示的是当前框架的内容。你也可在watch窗口中观察局部变量的值。
 
显示类和链表 dt可以显示数据结构。比如 dt PEB 会显示操作系统进程结构。在后面跟上一个进程结构的地址会显示该结构的详细信息:dt PEB 7ffdf000
Dl 命令可以显示一些特定的链表结构。
 
显示当前线程的错误值 !gle会显示当前线程的上一个错误值和状态值。!error命令可以解码HRESULT。
 
搜索或修改内存 :使用s 命令来搜索字节,字或双字,QWORD或字符串。使用e命令来修改内存。
 
计算表达式 :?命令可以用来进行计算。关于表达式的格式请参照帮助文档。使用n命令来切换输入数字的进制。
 
显示当前线程,进程和模块信息 !teb 显示当前线程的环境信息。最常见的用途是查看当前线程堆栈的起始地址,然后在堆栈中搜索值。!peb显示当前进程的环境信息,比如执行文件的路径等等。lm显示进程中加载的模块信息。
 
 
显示寄存器的值 r命令可以显示和修改寄存器的值。如果要在表达式中使用寄存器的值,在寄存器名前加@符号(比如@eax)。
 
 
显示最相近的符号 ln Address。如果你有一个C++对象的指针,可以用来ln来查看该对象类型。
 
查找符号 x命令可以用来查找全局变量的地址或过程的地址。x命令支持匹配符号。x kernel32!*显示Kernel32.dll中的所有可见变量,数据结构和过程。
 
 
查看lock:!locks 显示各线程的锁资源使用情况。对调试死锁很有用。
 
查看handle:!handle 显示句柄信息。如果一段代码导致句柄泄漏,你只需要在代码执行前后使用!handle命令并比较两次输出的区别。有一个命令!htrace对调试与句柄有关的Bug非常有用。在开始调试前输入:
!htrace –enable
然后在调试过程中使用!htrace handle_value 来显示所有与该 句柄有关的调用堆栈。
 
显示汇编代码 u
 
程序执行控制命令:
设置代码断点 bp/bu/bm 可以用来设置代码断点。你可以指定断点被跳过的次数。假设一段代码KERNEL32!SetLastError在运行很多次后会出错,你可以设置如下断点:
    bp KERNEL32!SetLastError 0x100.
在出错后使用bl 来显示断点信息(注意粗体显示的值):
0 e 77e7a3b0     004f (0100) 0:*** KERNEL32!SetLastError
重新启动调试(.restart命令)并设置如下的断点:
bp Kernel32!SetLastError 0x100-0x4f
Debugger 会停在出错前最后一次调用该过程的地方。
 
你可以指定断点被激活时Debugger应当执行的命令串。在该命令串中使用J命令可以用来设置条件断点:
bp `mysource.cpp:143` "j (poi(MyVar)”0n20) ''; 'g' "
上面的断点只在MyVar的值大于32时被激活(g命令
 
条件断点的用途极为广泛。你可以指定一个断点只在特殊的情况下被激活,比如传入的参数满足一定的条件,调用者是某个特殊的过程,某个全局变量被设为特殊的值等等。
 
设置内存断点:ba 可以用来设置内存断点。调试过程中一个常见的问题是跟踪某些数据的变化。如下的断点:
ba w4 0x40000000 "kb; g"
可以打印出所有修改0x40000000的调用堆栈。
 
控制程序执行 p, pa,t, ta等命令可以用来控制程序的执行。
 
控制异常和事件处理 :Debugger的缺省设置是跳过首次异常(first chance expcetion),在二次异常(second chance exception)时中断程序的执行。sx命令显示Debugger的设置。sxesxd可以改变Debugger的设置。
    sxe clr
可以控制Debugger在托管异常发生时中断程序的执行。常用的Debugger事件有:
    av    访问异常 
     eh    C++ 异常
    clr   托管异常
    ld    模块加载
-c 选项可以用来指定在事件发生时执行的调试命令。
 
  2004年4月3日 10:12 - (阅读:26844;评论:20)
href="http://blog.joycode.com/gangp/Services/Pingback.aspx" rel="pingback" />
反馈
# 回复: 使用WinDbg调试程序 2004-4-3 11:45 win32c@msn.com
它和VS 的调试有什么区别?
有什么好处?
# 回复: 使用WinDbg调试程序 2004-4-3 13:27 孙展波
如何去掉文章中自动加入的:-)等
# 回复: 使用WinDbg调试程序 2004-4-3 14:59 sam1111
VS的调试一般都是用户模式的调试,而WinDbg可以调试内核模式。
# 回复: 使用WinDbg调试程序 2004-4-3 17:27 彭刚
About the icons, the text should be:
.server npipe:pipe=<PIPE_NAME>
windbg –remote npipe:server=<SERVER_NAME>,pipe=<PIPE_NAME>

I can't modify this on the website now (other information will be lost.) Will change it later.
# 回复: 使用WinDbg调试程序 2004-4-4 13:29 Flier Lu
我也正在写一个用WinDbg跟踪CLR的系列文章,有机会可以互相交流一下 :P

用WinDbg探索CLR世界[1] - 安装与环境配置
http://flier_lu.blogone.net/?id=1270368

用WinDbg探索CLR世界 [2] 线程
http://flier_lu.blogone.net/?id=1370342

# 回复: 使用WinDbg调试程序 2004-4-4 18:59 rivershan
写驱动的时候有用,其它的没什么大用~
# 回复: 使用WinDbg调试程序 2004-4-5 6:38 彭刚
WINDBG更适用于调试系统或复杂的程序。比如死锁,Stack Corruption或Heap Corruption,访问异常,资源泄漏等等。
To Flier Lu: Your blogs are great. Topics are very clearly explained.有机会可以互相交流 :)
# 回复: 使用WinDbg调试程序 2004-4-5 12:50 rivershan
对大多数人来说,VC自带的调试器已经足够了~
# 回复: 使用WinDbg调试程序 2004-4-21 21:41 Flier Lu
VC提供的编译器屏蔽了太多的底层细节,对于工作在应用层的人来说足够了,但是对于希望了解实现细节的人来说,还是 WinDbg/SoftIce 这样的工具比较合适,呵呵

刚刚续写了一篇文章,中间发现对 CLR 的函数下断点很不方便,不知道有什么好的解决办法吗?

用WinDbg探索CLR世界 [3] 跟踪方法的 JIT 过程
http://www.blogcn.com/blog/cool/main.asp?uid=flier_lu&id=1678453

欢迎指正 :D
# 回复: 使用WinDbg调试程序 2004-5-1 12:46 chiv_bj
很好,我最近开始研究这个乐~~~`
# re: 使用WinDbg调试程序 2004-9-21 10:23
代码中间的表情怎么
去掉
# re: 使用WinDbg调试程序 2004-10-14 11:41 steve
collect
# re: 使用WinDbg调试程序 2004-12-6 14:53 rmdir
去掉中间的表情,可以多加一个空格。
# re: 使用WinDbg调试程序 2004-12-6 15:05 rmdir
windebug在远程调试状态下有2点是需要注意的:

1、如果对方是W2K/XP/W2003的系统,要进行远程调试必须要先连接到对方的系统上,如://IP,而系统会要求你输入用户名和密码,你需要使用当前用户正在使用的用户名和密码才能登陆,否则是不能被登陆的。在这一点来说,WINDEBUG没有提示用户也没有获取系统的标准登陆方式,导致无法连接到对方系统,而不知道是怎么回事。
2、如果对方有在启动时MMC后台执行过:net share IPC$ /del或者是:net share ADMIN$ /del,这类似的命令,使用WINDEBUG是无法连接到对方系统中,连提示都没有。

所以作者遗漏的地方,小第帮忙补上。
# re: 使用WinDbg调试程序 2004-12-13 13:28 罗新求
作者,您好!
您能帮助我:提供windows2000系统下,使用2台计算机,使用windbg调试内核驱动程序的资料或您的经验吗?
谢谢!
# re: 使用WinDbg调试程序 2005-2-28 15:20 罗庚华
作者,您好!
我使用2台机器(含有windbg的主机;被安装驱动程序的目标机器)调试内核驱动程序,2台机器能连接;但老显示win32 14 error 内存分配不充足错;且设置不上断点,请给予一些帮助与启示!
谢谢! leg@mobileelife.com 05-02-28
# re: 使用WinDbg调试程序 2005-6-26 6:10 mk
踏上当当的脚印
崩溃转储分析....
# re: 使用WinDbg调试程序 2005-9-20 16:57 空自流
请问你熟不熟悉64位程序用windbg来调试呢?我们在一台OS为windows XP x64的机子上调,但加断点的时候总是提示“code not found,breakpoint not set",怎么回事啊?
# 回复: 使用WinDbg调试程序 2007-2-5 16:54 hjh
No runnable debuggees error in 'p'
# IIS占用CPU百分百问题排查方案 2007-6-3 12:14 蛙蛙池塘
有时候辛辛苦苦写个网站,挂到服务器上一看,CPU给百分百了,这种问题百分之八九十都是因为代码写有问题,而不是因为系统设置的问题,这种问题也比较难排查。但是结合一些工具也可以找到原因的,关于windbg...
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值