前言
Windbg简单来说就是一个Windows下对用户态/内核态的程序进行调试,以及对Core Dump文件的分析。对于Crash,资源泄露,死锁等问题的分析,Windbg是一个强有力的利器。
一、下载
微软官网提供的Windbg为windows10版本,win7下不能使用。Win7下使用Windbg需要通过Windows SDK下载,下载链接为//www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b&displaylang=en
- 安装
如果对windows SDK的其他内容不感兴趣,可只勾选Windbg.
安装完成后便可以在Windows开始菜单栏中找到Windbg.
安装可能会失败,如果失败的话可以到控“制面板\程序\程序和功能“中将 Microsoft Visual C++ 2010 Redistributable卸载,即可安装成功。
- 开始使用Windbg
微软官网提供了详细的使用教程,参考链接:https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/getting-started-with-windows-debugging
在使用之前,需要完成以下任务
- 判断哪个设备作为服务系统,那个设备作为客户系统。调试器运行在客户系统,程序运行在服务系统。
- 判断你将要进行用户态调试还是内核态调试。内核态可以拥有极大的权限,可以访问系统的任何部分,许多核心操作系统功能和硬件驱动运行在内核态。用户态拥有很多限制,只能运行在自己的虚拟内存空间,不能直接访问系统。
关于调试内核态,请参考:
关于调试用户态,请参考:Getting Started with WinDbg (User-Mode).
除此之外,还需要做以下事情:
- 配置符号表。为了使用WinDbg提供的所有高级功能,必须加载正确的符号表。可以参考:Symbols for Windows debugging (WinDbg, KD, CDB, NTSD)。Windows 调试中的符号表
- 配置源码。如果你的目标是调试你自己的源代码,你需要配置源码路径。
Windows 调试中的符号表
- 关于符号表
- 符号表和符号文件
当应用程序,库,驱动,或者操作系统被链接,连接器生成exe文件或dll文件的同时还生成许多额外的文件叫做symbol files.符号文件拥有许多数据,这些数据在运行二进制文件时并不需要,但是在debug过程中非常拥有。通常的,这些数据包含以下信息:
- 全局变量
- 局部变量
- 函数名以及他们实体指针的地址
- 帧指针表
- 源代码行数
这些都被成为symbol。例如一个简单的符号文件Myprogram.pdb可能包含上百个符号表。一般来说,软件公司发布两种版本的symbol file,一种是全量symbol file包含全部public symbols和private symbols,另一种简版的文件只包含public symbols。
调试时,必须知道调试器能够获取与调试目标相匹配的symbol files,在线调试和调试crash dump files都需要symbols。
Windows以后缀名pdb保存symbols,vs将所有symbols保存在pdb文件中。
- 为Debugging获取符号表
设置好symbols是一项充满挑战的任务,特别对于内核态调试来说。它经常需要你知道你电脑产品的所有名字和releases,调试器必须能够定位到每一个产品的symbol file。
为了简化困难,symbols files被收集到一个symbol store,可以通过symbol server获取。一个symbol store 是一个symbols files的集合,是一个索引,是一个管理员添加和删除文件的工具。这些文件通过一些独特的参数被索引,例如时间戳或图像大小。Debugging Tools for Windows contains a symbol store creation tool called SymStore. Debugging Tools for Windows contains a symbol server called SymSrv.
微软官网上说的比较委婉,不容易操作。这里直接给出一种简单的设置方法。
- 将windbg安装目录添加到Path环境变量中。如:C:\Program Files\Debugging Tools for Windows (x64)
- 新建一个环境变量_NT_SYMBOL_PATH 值为: SRV*c:\mysymbol* http://msdl.microsoft.com/download/symbols
这句话告诉WinDbg,我的symbol文件保存在c:\mysymbol文件夹里,其实里面什么都没有,甚至这个文件夹不存在,不过没关系,系统找不到的话会创建一个,并在上面的网址中去帮你下载符号文件放在里面。
- 重启计算机
重启计算机后会如果发现C盘多一个mysymbol文件,并且用windbg打开一个exe文件,会看到Symbol search path is: SRV*c:\mysymbol* http://msdl.microsoft.com/download/symbols提示信息,说明配置成功。
注意:进行完此步骤后,如果再次启动VS,VS会读取_NT_SYMBOL_PATH环境变量并且从中下载并读取symbol,这会造成VS启动调试非常缓慢,建议不用Windbg时可以将_NT_SYMBOL_PATH换个名字。
- Debugger如何识别符号表
- 调试中的符号问题
用户态调试入门
调试自己的程序
假设你已经编写如下程序
void MyFunction(long p1, long p2, long p3)
{
long x = p1 + p2 + p3;
long y = 0;
y = x / p2;
}
void main()
{
long a = 2;
long b = 0;
MyFunction(a, b, 5);
}
(1)用Visual studio 2015在x64、debug模式下生成一个Helloworld.exe,同时生成一个Helloworld.pdb。
(2)将Helloworld.pdb拷贝到设置的本地symbol文件夹中(参考:配置符号表)。
(3)用windbg打开Helloworld.exe和Helloworld.cpp。
接着就可以输入调试命令进行输入了,例如:
意思是在HelloWorld的main模块处设置断点
开始运行程序
- 按F11进行单步调试,直到程序运行到y = x / p2将会崩溃,输出错误信息,类似这样:
(3058.3830): Integer divide-by-zero - code c0000094 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
HelloWorld!MyFunction+0x53:
00000001`3f2a16d3 f7bd28010000 idiv eax,dword ptr [rbp+128h] ss:00000000`0014f648=00000000
是说发生了0除错误。
(4)!analyze -v
将会生成一堆对错误的分析。
调试notepad
此部分的先决条件是配置好symbol(参考: 配置符号表)。
- 用windbg打开notepad.exe,通常在C:\Windows\System32,如图:
- 运行.reload,寻找并且加载symbols
- x notepad!WinMain
寻找所有与WinMain匹配的symbols。
- bu notepad!WinMain 设置断点
- bl 显示已经设置的断点信息
- g 运行程序直到断点、崩溃或程序结束
- lm 显示notepad程序已经加载的模块
- k显示当前线程的堆栈轨迹,即函数调用结构表
- g 继续运行
- 按菜单栏的stop按钮停止调试
- bu ntdll!ZwWriteFile 设置新的断点
- bl 显示断点信息
- ~ 查看当前程序的所有线程
- ~0s
以上两个命令可以进入0好进程,并查看堆栈轨迹
- qd退出调试