Windbg调试⼯具使⽤详解,⼲货满满!
⽬录
1、Windbg简介
Windbg是微软提供的Windows平台下强⼤的⽤户态和内核态调试利器,给我们分析Windows上软件的异常提供了极⼤的便利和有⼒的⽀持,⽐原始的直接查看代码分析异常的效率要来的⾼的多。Windbg在某些⽅⾯甚⾄要⽐微软的Visual Studio还要强⼤,作为Windows平台的开发⼈员,必须要会使⽤该⼯具分析问题。
Windbg的主界⾯如上所⽰。Windbg可以静态分析dump⽂件,也可以对⽬标进程进⾏动态调试。Windbg可以直接启动进程,也可以附加到正在运⾏的⽬标进程上,可以查看进程运⾏时变量内存中的数据。Windbg在排查内存访问违例、死循环、死锁、搞CPU占⽤、异常崩溃等⽅⾯,有着独到的优势。
其实,Windbg⼊门的门槛较低,只需掌握⼀些常⽤的Windbg命令即可。另外,有时需要深⼊研究问题时,可能还要使⽤到IDA反汇编⼯具,去查看⼆进制⽂件中的汇编代码的上下⽂,查看汇编代码才能最直观地看出软件崩溃的最直接的原因。所以,除了掌握Windbg之外,我们还需要学会使⽤IDA反汇编⼯具,本⽂主要讲解windbg的使⽤。
2、Windbg版本
⾄于Windbg的版本,有⽆需安装的6.0绿⾊版本,也有需要安装的最新的10.0的版本,这⾥推荐⼤家使⽤10.0及以上的版本。
10.0新版本相对6.0版本,要智能很多,要查看相关内容,不⽤再输⼊各种复杂命令,只要点击超链接查看即可。在6.0版本中,很多命令是需要⼿动输⼊的。
另外,6.0版本不能加载VS2017编译⽣成的pdb⽂件(6.0版本的Windbg是⽆法识别VS2017编译出来的pdb⽂件的),所以要处理VS2017的程序问题,是需要使⽤10.0版本的Windbg的。
新版本的Windbg已经内置到Windows SDK的安装包中,这个安装包可以到微软的官⽅⽹站上下载,
安装时只需要勾选安装Windbg 即可。对于Win10系统,也可以到系统⾃带的应⽤商店中去免费下载安装。
3、PDB⽂件说明
PDB - Program Databse File,程序数据库⽂件,存放了⼆进制⽂件中所有函数及变量的符号,要查看完整的函数调⽤信息和变量信息,都需要使⽤pdb⽂件。Windbg和IDA都需要使⽤pdb⽂件。
Windbg使⽤时需要配置pdb⽂件路径,IDA使⽤时只需将pdb⽂件放置在⽬标⼆进制的同级⽬录中, IDA会从⽬标⼆进制⽂件所在的⽬录中搜索对应的pdb⽂件,去⾃动加载。
另外,加载pdb⽂件时会严格校验pdb⽂件的时间戳,必须要和⼆进制⽂件完全⼀致。即使是同样的代码,在不同时间编译⽣成的pdb ⽂件,也是不能交叉使⽤的。
需要注意的是,pdb⽂件的名称必须和⼯程的名称⼀致,否则也是⽆法加载的,⽐如⼯程名称为codec_hw.vcxproj,⽣成的pdb⽂件的名称默认应为codec_hw.pdb,但在执⾏⽂件拷贝时将⽂件名称改成codec.pdb,这种情况下Windbg也是⽆法加载的。必须⼿动将⽂件名改成⼯程名后,才能正常加载。
4、Windbg中pdb符号⽂件路径配置
在Windbg中配置pdb符号库路径时,⼀般设置如下格式的pdb⽂件路径:
C:\Users\Administrator\Desktop\tlpdb;srv* f:\mss061*msdl.microsoft/download/symbols
这么个⼀长串路径主要由下⾯三个部分构成:
5、在Windbg中配置pdb⽂件路径和源代码路径
我们需要将函数调⽤堆栈中涉及到的模块的pdb⽂件添加到Windbg中,具体的添加pdb⽂件(路径)的⽅法是,在Windbg菜单栏中点击File --> Symbol File Path,打开如下的窗⼝,将pdb⽂件所在的路径设置进来即可:
这样我们在windbg打印出来的函数调⽤堆栈中就能看到具体的函数名及变量信息了。
我们不⽤通过函数调⽤堆栈中显⽰的代码⾏号到源代码⽂件中对应的代码⾏,我们可以将项⽬源代码的根路径设置到Windbg中,在菜单栏中点击File --> Source File Path,将项⽬源代码的路径拷贝进来即可:
这样我们在点击调⽤堆栈中的序号链接时,Windbg的源代码视图就会⾃动跳到对应的代码⾏上,这样看起来很⽅便,特别是我们在查看多个堆栈帧时。
6、常⽤的Windbg命令
1).ecxr
⽤来切换到异常发⽣时的上下⽂,主要⽤在分析静态dump⽂件的时候。当我们使⽤.reload命令去强制加载库的pdb⽂件后,需要执
⾏.ecxr命令,重新切换到异常上下⽂。
2)kn/kv/kp
⽤来查看当前线程的函数调⽤堆栈。如果要查看当前进程的所有线程的函数调⽤堆栈,可以使⽤~*kn命令。
3)lm
⽤来查看库的信息,⽐如库的路径、时间戳、库的加载地址等。⼀般使⽤模糊匹配的模式,⽐如:lm vm codec*。
4).reload
⽤来加载pdb⽂件,⼀般⽤来强制加载某个pdb⽂件,⽐如:.reload  /f  kdcodec.dll。注意这个命令中的名称要使⽤完整的⽂件名称。
5)!analyze -v
输出当前异常的详细分析信息。
6)g
在中断模式下,跳过中断,继续运⾏,主要⽤于实时调试的场景。
7)bp/bl/bc
添加、查看、删除断点,主要⽤于实时调试的场景。
8)~ns
切换到n号线程中,在GUI应⽤程序中,UI线程为0号线程,是GUI程序的主线程。
9).dump
创建⼀个⽤户模式或内核模式的转储⽂件,⽐如.dump /ma C:\1125.dmp。
10)r
显⽰当前线程所有寄存器的值。
11).cls
清除当前屏幕显⽰。
安装版本的Windbg(⾮绿⾊版)会⾃带帮助⽂档,可以到帮助⽂档中查看命令的详细说明:
7、Windbg静态分析dump⽂件
我们在代码中添加了异常捕获的模块,⼀旦软件发⽣异常崩溃,我们的异常捕获模块⼀般都能捕获到,然后⾃动将当时的异常信息保存到dump存储⽂件中,事后可以将dump⽂件取来分析。使⽤Wind
bg静态分析dump⽂件,有以下⼏点重要的说明。
1)切换到异常上下⽂
Windbg打开dump⽂件后,输⼊.ecxr命令切换到异常上下⽂,此时可以看到异常发⽣时的寄存器中的值,以及发⽣异常的汇编指令。可以看到汇编指令所属的模块及该指令代码段的地址。
2)查看函数调⽤堆栈
紧接着,输⼊kn/kv/kp命令,查看异常发⽣时的函数调⽤堆栈,通过函数调⽤堆栈,我们就能⼤概地看出是什么操作引起的异常。要在函数调⽤堆栈中看到具体的函数名及函数中的⾏号,我们需要将对应模块的pdb⽂件加载Windbg中来。需要看哪个模块,就将该模块的pdb⽂件加载进来。
3)加载pdb符号库
pdb文件阅读器安卓我们先使⽤类似于lm vm directui*命令,查看directui.dll库⽣成的时间戳,这样就能确定该库的编译时间,然后到0.99服务器上到对应的版本路径,来对应的pdb⽂件,然后将pdb路径设置到windbg中。注意添加路径时,记得勾选reload选项,这样windbg就会⾃动去加载所需要的pdb⽂件。但有时⾃动加载不进来,就需要我们使⽤命令去强制加载了。
使⽤类似于.reload /f directui.dll命令,其中/f参数表⽰强制加载,注意命令中的⽂件名必须是带后缀的完整⽂件名。如果还是加载失败,我们可以使⽤!sym noisy命令打开pdb符号库加载详情,看显⽰的详情中为啥会加载失败。
pdb符号库加载失败,可能是pdb⽂件的时间戳对不上,也有可能是因为pdb⽂件名和⼯程名不⼀致引起的。
另外,有时没加载pdb时看到的堆栈可能都是⽆效的⼆进制地址信息,加载pdb后才能看到完整的模块信息和函数调⽤信息,这个情况我们也遇到过不少次。
4)结合函数调⽤堆栈进⾏具体分析
pdb符号库加载成功后,重新输⼊.ecxr切换到异常上下⽂,再次输⼊kn命令,此时打印出来的函数调⽤堆栈中就能看到具体的函数名和代码的具体⾏号了。将函数调⽤堆栈和C++源代码结合起来,逐步排查出代码中存在的问题。
5)全dump⽂件和简要dump⽂件
有些时候我们可能需要查看函数调⽤堆栈中某个函数中变量的值,我们可以点击函数调⽤堆栈中的帧序号,就能看到该函数中局部变量以及当前函数所在类的this指针在内存中的值。
但因为我们异常捕获库⾃动保存的dump⽂件中只包含了部分概要信息的,可能看不到变量的值或者只能看到部分变量的值,只有全dump⽂件才能看到完整的内存信息。
⼀般我们通过.dump命令导出的dump⽂件就是全dump⽂件,⽂件中包含了完整的异常信息和内存数据信息,这种全dump⽂件⼀般⽐较⼤,⼤概有好⼏百M。
另外,在Windows任务管理器中通过进程的右键菜单导出的转储⽂件也是⽐较完整的全dump⽂件,⽂件也⽐较⼤。
6)64位上下⽂需要转化为32位上下⽂
有时dump⽂件可能是从64系统的资源管理器中导出的转储⽂件,windbg打开后看到的函数调⽤堆栈很奇怪,完全和我们的业务代码对应不上,此时可能Windbg调试⼯具的使⽤是64位的异常上下⽂:
⽽我们的程序是32位的,所以需要
⽤.effmach X86命令转换成32位的上下⽂,例如转换后的函数调⽤堆栈如下:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。