目录
1 Windbg简介 1
2 Windbg设置条件断点 1
3 事件处理与异常 4
4 调试dll和ocx控件 7
5 进程调试与程序死锁 8
6 结语 12
不要相信任何人
关键词:
软件调试,调试技巧,windbg
摘 要:
Windbg是微软提供的一款免费的软件调试工具,具有强大的功能和扩展性,满足各种各样的调试需求。本文对windbg进行了简单的介绍,对几个我比较关心的主题进行了详细的讲解,并给出了一些调试技巧,配合一些示例。由于软件调试是一个广阔的领域,windg的命令使用与调试技巧也很多,本文也不能一一涉及,文章最后给出了一些参考资源,可以进一步深入研究。
1 Windbg超强台风简介
Windbg是微软开发的一款免费软件调试工具,WinDBG 是个非常强大的调试器,它设计了极其丰富的功能来支持各种调试任务,包括用户态调试、内核态调试、调试转储文件、远程调试等等。WinDBG 具有非常大的灵活性和可扩展性,用来满足各种各样的调试需求,比如用户可以自由定义调试事件的处理方式,编写调试扩展模块来定制和补充WinDBG 的调试功能。此外windbg通过SOS.dll支持可以调试应用程序,使得windbg成为windows下软件调试的首选。
WinDbg主要适用于以下这些场合:
1. 商业软件的Debug(缺乏源码)和客户支持(需要远程调试)
2. 内核驱动的调试,以及对驱动进行逆向工程时进行动态调试
3. 研究Windows本身的内核或者软件
4. 疑难BUG的调试,如死锁、COM调用、资源泄露、堆栈或者堆溢出
5. 以性能优化为目的的调试
6. 对调试目标基本不造成影响的非侵入式调试(windbg特有)
Windbg具备极为强大的功能,可以调试可执行文件(exe),动态链接库(dll)、Activex控件,程序dump文件和在运行进程,涵盖了软件调试的方方面面,windbg的操作命令和使用技巧也很多,这里仅列举我比较关心和常用的几个主题。
2 Windbg设置条件断点
1. 条件断点
在程序调试过程中通常会遇到循环和条件判断,调试的时候往往只关心其中的某种情形和某一时刻的内部状态,如果每次循环都要断下来查看就大大增加了我们的调试工作量,好在windbg为我们提供了条件断点,通过条件断点我们可以设置仅仅在我们期望的条件下中断目标程序的运行。条件断点的设置方法是:
断点指令 + “j(Excecute If-Else) 和 gc (Go from Conditional Breakpoint)”
这里的断点指令支持bp, bu, bm, ba等指令。语法格式如:
0:000> bp Address "j (Condition) 'OptionalCommands'; 'gc' "
0:000> bp Address ".if (Condition) {OptionalCommands} .else {gc}"
这两条是等价的。
2. 利用条件断点自定义log输出
利用条件断点可以进行各种高级断点的设置,可以方便我们程序BUG的查和定位。此外,巧妙使用条件断点和windbg自带的强大辅助调试功能,我们还可以利用windbg来实现
在不破坏源程序的情况下自定义log输出,这在实际应用中,客户部署环境下有重大的意义。这里仅例举一个简单的例子,演示如何在不破坏源程序情况下使用windbg自定义log输出,程序如下:
class MyCls
{
private:
char* str;
public:
void set(char* input){
(1) this->str = input;
}
void output() {
printf(str);
}
};
手机上网很慢int main(int argc, char* argv[]){
MyCls* pcls = new MyCls();
char ch[2];
for (int i=0; i< 10 ;i++)
{
pcls->set(itoa(i,ch,10));
临沂有什么好玩的地方旅游景点 pcls->output();
}
getchar();
f150 return 0;
}
该程序的正常输出为:0123456789。在调试程序过程(debug模式下)中,我们希望在不修改源程序情况下,打印MyCls::set函数的调用参数大于‘4’的参数内容,使用windbg我们怎么能做到呢?
打开windbg,设置好符号路径,加载调试目标,程序中断在入口处,在命令窗口输入:
.logopen c:\test.log
设置log文件输出:C:\test.log,下条件断点:
bp TestDbg2!MyCls::set+0xe "j (wo(poi(ebp+8))>34) '.echo enter set func,arg: ;da poi(ebp+8);gc';'gc'"
该命令的含义是在TestDbg2程序MyCls::set函数入口设置条件中断(这里的+0xe偏移是为了让函数建立入口栈帧),当调用参数input(poi(ebp+8))的首字母大于4(ASCII 0x34)时,输出“enter set func,arg: (调用字符串)”,下条件断点后,输入g让程序继续运行,程序运行结束后,输入:.logclose关闭日志文件。程序调试输出log文件如下:
Opened log file 'c:\test.log'
0:000> bp TestDbg2!MyCls::set+0xe "j (wo(poi(ebp+8))>34) '.echo enter set func,arg: ;da poi(ebp+8);gc';'gc'"
breakpoint 0 redefined
0:000> g
enter set func,arg:
0012ff78 "5"
enter set func,arg:
0012ff78 "6"
enter set func,arg:
0012ff78 "7"
enter set func,arg:
0012ff78 "8"
enter set func,arg:
0012ff78 "9"
eax=00000000 ebx=00000000 ecx=7c800000 edx=7c99b120 esi=7c92de50 edi=00000000
eip=7c92e4f4 esp=0012fe54 ebp=0012ff50 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCallRet:
7c92e4f4 c3 ret
0:000> .logclose
Closing open log file c:\test.log
输出高亮部分为自定义的log输出,加以运用,可以为我们的应用程序调试提供很大的便利。尤其针对客户应用环境,可以在不破坏原程序和应用环境下自定义日志记录,以便日后分析。使用windbg收集程序运行日志还有一个更大的好处,可以借助windbg操作打印,记录程序运行的各种变化量:模块加载与卸载等变化。本文还附我使用windbg调试OSPdemo的一个自定义log输出的例子,里面记录了打开文件对话框,选择上传的文件,对应模块加载的情况,见ospdemo.log。
1
2
1
2
3
3
3 事件处理与异常
程序的运行可能触发各种事件,例如进程和线程的创建与销毁、dll动态链接库的加载与卸载、应用程序产生异常等。调试的各事件及其设置方式可以参加事件处理设置对话框,如图 31所示。
图 31 windbg事件处理设置对话框
异常事件是软件调试中遇到最多的一种事件,也是最复杂的一种。Windbg对异常的处理有两次机会:对于每一轮机会Windows 都会先分发给调试器(如果存在),然后再寻异常处理器(VEH、SEH 等)。因而对于每个异常,调试器都可能收到两次通知,具备两次处理机会,调试器可以根据具体需要来决定它是否处理这个异常。
对异常的处理和事件的处理也可以使用命令行的方式来配置:
sx{e|d|i|n} [-c "Cmd1"] [-c2 "Cmd2"] [-h] {Exception|Event|*}
其中的e|d|i|n 对应于图形界面的Enabled、Disabled、Output 和Ignore,-c 和-c2 分别用来定义第一轮机会和第二轮机会的关联命令,Exception|Event 为对应的异常或者事件。
当因为发生异常而中断到调试器中时,可以使用g 命令恢复调试目标执行,调试器将使用给定的设置来处理该事件或者异常。如果调试人员希望返回与设置不同的状态,那么可以使用GH 或者GN 命令。前者用来返回已经处理(Handled),后者用来返回没有处理(Not Handled)。
这里举一个C++程序中经常容易遇到的一个问题,指针非法调用。源程序如下:
void foo(){
MyCls* pcls; /* MyCls* pcls = new MyCls(); */
(2) pcls->set("abcd");
pcls->output();
delete pcls;
pcls = NULL;
}
int main(int argc, char* argv[]){
int a,b;
过期牛奶的妙用 a = b = 3;
try {
(1) int c = 5/(a-b);
}catch(...)
{
cout << "Divided by 0!"<< endl;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论