windbg调试基础

摘要:
加载调试目标后,将更改并保存工作区。它不改变windg的基本工作空间,只改变与调试目标相对应的工作空间;然而,只有当windg没有加载任何调试目标、更改和保存时,基本工作区才会受到影响。客户端软件自己的符号表文件是在构建程序的过程中生成的;操作系统dll的符号表文件可以根据需要通过设置windag自动从Microsoft符号服务器下载。

#工作空间 [Workspace]

工作空间被用来描述和存储一个调试项目的属性、参数以及调试器设置等信息,其功能类似于集成开发环境的项目文件。

具体包括:调试会话状态(断点、打开的源文件、用户定义的别名等)、调试器设置(符号文件路径、源文件路径、可执行映像文件路径等)和窗口布局状态

0. 基础工作空间 [base workspace]

未载入任何的调试文件时使用默认的启动环境。存放位置:HKEY_CURRENT_USER\Software\Microsoft\Windbg\WorkspacesDefault二进制值。

1. User、Kernel、Dump、Explicit工作空间

存放在HKEY_CURRENT_USER\Software\Microsoft\Windbg\Workspaces的各子键中(如下图)

子键UserKernelDump用来保存用户态调试、内核态调试、调试转储文件时,使用【Save Workspace】方式时默认的保存路径。

子键Explicit则用来记录使用【Save Workspace as】方式保存的命名工作空间。

对于【Attach to a Process】的方式,会使用User下的Default二进制值作为其工作空间,之后对工作空间所作的修改也会写到该字段中。

windbg调试基础第1张

注:有时会发现没有某个子键,这是因为windbg还没使用过该调试方式。

2. 其他说明

(1) windbg还提供另外一种保存方式【Save WorkSpace to File】,作用跟上面两种的方式差不多,

     只不过把工作空间以文件的形式保存到磁盘里,那么用户就可以通过U盘或其它方式把工作空间的环境移植到其它机器上使用。

(2) 调试目标最后的工作空间为:基础工作空间其对应工作空间求并所得的环境。

(3) 用windbg打开目标可执行文件【Open Executable】,若有默认的工作空间文件(在子键User下),会自动打开其对应默认的的工作空间文件。

     要使用子键Explicit下目标文件的工作空间,必须先提前【Open WorkSpace】,然后再打开目标可执行文件。

(4) 在载入调试目标后改变了工作空间并保存,并不改变windbg的基础工作空间,只改变调试目标对应的工作空间;

     而只有在windbg还没载入任何调试目标时改变并保存才会影响基础工作空间。

#符号 [Symbol]

调试者接触的二进制数据以及汇编代码,如果没有符号表文件的帮助,就无法知道这些数据代表什么变量、函数。

符号(symbol) :函数和变量的别名,编译器通过符号修饰(Name Decoration)和 函数签名(Function Signature)来实现全局唯一性。

函数符号含有返回值,函数名,函数参数等函数所有信息;变量符号含有类型和名称信息。

通过不同的编译选项,编译器可以生成两种截然不同的信息集合:私有符号(private symbol)公有符号(public symbol)

私有符号(private symbol)包含完整的调试信息,编译选项:/Zi或/ZI。

windbg调试基础第2张

公共函数和变量:在多个的编译单元(源代码文件)中可见的函数和变量。

私有函数和变量:用于描述除公共函数和变量以外的所有函数和变量,包括静态函数、静态和局部变量、函数参数)。

因此,为了能更方便读懂二进制数据和汇编语言,需要获取符号表文件,在windbg下使用的符号表文件一般是.PDB文件。  

客户端软件存在于exe/dll中,这些二进制文件会调用操作系统的dll,这两部分二进制文件的符号表文件都需要获取。

客户端软件自己的符号表文件在构建程序的过程中产生;而操作系统dll的符号表文件可以通过设置windbg,根据需要自动从微软符号服务器上下载。

#pdb(program Database )

0. pdb中包含的内容

符号表

函数和变量符号到地址的映射表(map文件实际就是一个文本格式的符号表)。

源文件和代码行信息

二进制指令到代码源文件代码行的映射表。

类型信息

用于存储每一个函数和变量的类型信息。对于变量或函数参数,类型信息能够告诉调试器是整型还是字符串类型,或是用户自定义类型。

对于函数,类型信息记载了参数的个数、调用转换和返回值的类型。

FPO(frame pointer omission, 帧指针省略)

对于做了FPO优化的函数,FPO信息保存了一些数据来帮助调试器确定函数堆栈帧的大小,

帮助调试器查找函数的参数和本地变量,甚至在帧指针无效时也能工作。

如果没有FPO信息,调试器无法正确显示被优化的程序的调用堆栈。

编辑和继续执行信息

用于帮助Visual Studio在调试时实现编辑和继续执行的功能

在过去的十年中,微软使用了几种不同的格式(COFF、CodeView和应用的最广泛的PDB格式)来存放调试信息。

格式

是否有文档

存储

公共函数和变量

私有函数和变量

源文件和代码行信息

类型信息

FPO信息

编辑和继续执行信息

COFF

微软可移植可执行和通用对象文件格式规范

可执行文件中

+

-

+

-

+

-

CodeView

部分

Microsoft Symbol and Type Information

可执行文件中

或.DBG文件中

+

+

+

+

+

-

Program Database

微软没有提供程序数据库格式的文档,只提供特殊的编程接口DbgHelp 和DIA来访问它。
目前有两个版本,第一版(PDB2.0)为VC6.0所用,第二版(PDB 7.0)被VS采用。
PDB 7.0不能向上兼容,也就是说:VC6.0不能读取PDB 7.0格式。

.PDB文件中

+

+

+

+

+

+

1. 在vc6下配置生成PDB文件

vc6的Debug配置,会在编译时生成私有符号pdb文件;Release可通过如下配置来达到这一目的:

(1) 选择Project->Setting菜单,打开工程设置对话框

(2) 在“Setting For:” 中选择 “Win32 Release”(只设置Release版本即可,因为Debug版本默认生成PDB文件)

(3) 选择标签页 “C/C++” ,在 “Debug info” 中选择 “Line Numbers Only”(如果选择Program Database则包含更多的符号信息)

(4) 选择标签页 “Link” ,勾选 “Generate debug info”

(5) 在标签页 “Link” 中,选择 “Category->Customize”,在这里填写PDB文件的生成路径

论是Debug还是Release配置,VC6.0的Link选项需要将/pdbtype:sept改为/pdbtype:con, 否则生成的pdb文件中将不包含如自定义结构体,类等信息

更多关于vc6和vs的pdb编译和链接选项信息,请参考:Windows程序调试系列: 使用VC++生成调试信息

2. 为vs下Release配置生成PDB文件

(1) 配置C/C++ >General>Debug Information Format 为 “Program Database(/Zi)”

(2) 配置C/C++ >Optimization>Optimization 为”Disabld(/Od)”

(3) 配置Linker>Debugging>Generate Debug Info 为”Yes/(DEBUG)”

3.在windbg下使用PDB文件

启动windbg后,选择 【Symbol File Path】,弹出 “Symbol Search Path” 对话框,输入存放PDB文件的路径。可以输入多个路径,路径之间使用分号进行分隔。

如果此时正在调试程序,则对话框中的 “reload” 选择框是可以选择的,勾选后点击“确定”。

4.使用Windows符号表服务器

为了方便调试,需要获取Windows系统DLL的符号表文件。微软公司提供了可以通过Internet访问的符号表服务器。

经过设置,在调试过程中,windbg调试器会从符号表服务器自动下载调试所需的PDB文件,非常方便。

设置方法: 在 【Symbol Search Path】 对话框中加入下面的路径:srv*D:\SystemSymbols*http://msdl.microsoft.com/download/symbols

其中: D:\SystemSymbols为存放符号的下载目录

windbg调试基础第3张

windbg调试基础第4张

注148C58F3D11e000为对应版本dbghelp.dll的PE头中记录的时间日期戳和映像大小的组合(字节数)

windbg调试基础第5张

timestamp与日期时间的在线转换工具:http://tool.chinaz.com/Tools/unixtime.aspx

注2:6B19F261EE434AF59623D1791CE5A7D72为对应版本dbghelp.pdb的guid

另外,也可以使用windbg提供的symchk.exe工具提前下载某个dll及某个目录下所有dll的pdb文件到本地

"C:\Program Files\Debugging Tools for Windows (x86)\symchk.exe" c:\windows\system32\user32.dll /s SRV*c:\symbols\*http://msdl.microsoft.com/download/symbols  //下载user32.dll的pdb到c:\symbols目录中
"C:\Program Files\Debugging Tools for Windows (x86)\symchk.exe" c:\windows\system32\ /s SRV*c:\symbols\*http://msdl.microsoft.com/download/symbols //下载system32下所有dll的pdb到c:\symbols目录中
"C:\Program Files\Debugging Tools for Windows (x86)\symchk.exe" /r c:\windows\system32\ /s SRV*c:\symbols\*http://msdl.microsoft.com/download/symbols  //递归子目录下载system32下所有dll的pdb到c:\symbols目录中

5. 设置_NT_SYMBOL_PATH环境变量

设置系统环境变量“_NT_SYMBOL_PATH”,Visual Studio、windbg、SysinternalsSuite工具集的ProcessExplorer、ProcessMonitor等都会将该环境变量下的路径添加到自己的Symbol File Path中

windbg调试基础第6张

6.建立自己的符号表服务器

通过为产品建立自己的符号表服务器,就不需要关心复杂的版本问题。在调试过程中,windbg可以根据二进制文件(exe/dll)的哈希值,在符号表服务器上自动查找正确版本的PDB。

(1)建立一个共享文件夹,比如 “ \\server\symbols” ,然后将所有的PDB文件上传到此处

(2)使用下面的命令上传符号表文件

symstore add /r /f D:\MyOutput\chess.exe /s \\server\symbols /t "chess" /v "exe" /c "version build"

symstore add /r /f D:\MyOutput\chess.pdb /s \\server\symbols /t "chess" /v "pdb" /c "version build"

symstore add /r /f D:\MyOutput\chess.map /s \\server\symbols /t "chess" /v "map" /c "version build"

symstore 是windbg附带的一个exe文件,存放于windbg安装目录下。需包含2个文件:symstore.exe、symsrv.dll

上述命令完成的功能是:将D:\MyOutput目录下的chess.exe、chess.pdb、chess.map上传到\\server\symbols目录中。

产品的名称是"chess",版本信息是"exe"、"pdb"、"map",备注说明是"version build"。

(3)在windbg的 【Symbol Search Path】对话框中添加新的路径(路径之间使用分号[;]分隔)\\server\symbols(关联一个本地缓存目录)

srv*D:\SystemSymbols*http://msdl.microsoft.com/download/symbols;srv*D:\ServerSymbols*\\server\symbols;f:\symbols

7. 查找函数符号名  -- 列出含CreateThread字样的符号名

"D:\Program Files (x86)\windbg\dbh.exe" -s:srv*D:\Symbols\ms*http://msdl.microsoft.com/Download/Symbols -d C:\Windows\SysWOW64\kernel32.dll enum *CreateThread*

windbg调试基础第7张

#使用windbg

0. Attach方式

启动windbg,使用菜单【Attach to a Process】,可以选择注入到现在正在运行的某个进程中。

注入到进程中后,进程被暂停执行,windbg处于可输入命令状态,但此时当前线程为windbg产生的线程。

按g继续运行进程时,windbg会随即销毁该线程。

windbg调试基础第8张

如果要观察主线程堆栈,需要切换到主线程(0号线程)(在windbg命令窗口输入这个命令,然后回车):

~0s 

当程序出现CPU占用100%的情况时,通常可以使用这种方式进行注入,然后切换到占用CPU的线程,

同时根据需要使用单步跟踪、设置断点等手段,来判断是何处的代码导致CPU100%问题。

1. Open Executable方式

使用【Open Executable】方式,可以通过windbg启动被调试程序。在这种方式下,被调试程序从启动时刻起就在调试器的监控之下。

对于一些在程序启动过程中产生的异常,可以使用这种方式进行调试。

2. Just in time Debugger 方式 (JIT)

当进程产生结构化异常时,如果进程不作处理,也没有调试器在监控这个进程,那么windows就会调用默认的调试器来调试发生异常的进程。

通过把windbg设置为Just in time Debugger,可以在任意进程发生异常时自动调用windbg来进行调试。

在注册表编辑器中修改下面的注册表项:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug

HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug  // 注:64位系统上的32位程序使用该注册表项

Debugger键值修改为下面的取值 "D:\Tools\windbg.exe " -p %ld -e %ld

注1:将例中windbg.exe的路径替换为本机windbg绝对路径即可

注2:一般该值为:"C:\Windows\system32\vsjitdebugger.exe" -p %ld -e %ld

3. Dump文件

为了分析程序发生异常的原因,还可以借助Dump文件。

当异常发生时,把进程当前的信息保存到一个Dump文件中,再把该Dump文件发送给分析者,由分析者通过windbg进行分析。

Dump分类:

windbg调试基础第9张

内核dump:(蓝屏后,由系统生成)

1. 完全内存转储。这个文件比较大,和物理内存相当,包含了程序崩溃前系统及用户模式下的所有信息。
2. 核心内存转储。这个文件大小约物理内存的三分之一,主要包含崩溃前系统内核的所有信息。一般为了分析内核错误,就选用这种文件。
3. 小内存转储(MiniDump)。保存内存前64KB的基本空间数据,主要包含crash进程及crash线程内核上下文信息,crash线程内核模式堆栈,加载的驱动和模块等信息。

windbg调试基础第10张

如果没有禁用“Windows Error Reporting Service”服务,重启后会弹出如下对话框来显示一些蓝屏相关的信息:

windbg调试基础第11张

问题签名:
  问题事件名称:	BlueScreen
  OS 版本:	6.1.7601.2.1.0.256.48
  区域设置 ID:	2052

有关该问题的其他信息:
  BCCode:	1000007e
  BCP1:	FFFFFFFFC0000005
  BCP2:	FFFFF80004CCC0E4
  BCP3:	FFFFF88004993668
  BCP4:	FFFFF88004992EC0
  OS Version:	6_1_7601
  Service Pack:	1_0
  Product:	256_1

有助于描述该问题的文件:
  C:\Windows\Minidump\060717-10280-01.dmp
  C:\Users\nicochen\AppData\Local\Temp\WER-41964-0.sysdata.xml

联机阅读隐私声明:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0804

如果无法获取联机隐私声明,请脱机阅读我们的隐私声明:
  C:\Windows\system32\zh-CN\erofflps.txt

事件查看器中也记录了那次致命错误

windbg调试基础第12张

不同信息量的minidump:

    (1)标准的minidump。包含了相对比较少的信息,适合在做在线分析:系统信息、加载的模块(DLL)信息、进程信息和线程信息。
        .dump /m c:\stardardMini.dmp(注:不指定/m和/f,/m为缺省选项

    (2) full dump。在内核模式下,生成完全内存转储;用户模式下,最好不使用(/ma和/mf是更好的选择,生成出的dump信息也更丰富一些)
        .dump /f c:\fullMini.dmp

    (3)带有尽量多选项的minidump。包括完整的内存内容、句柄、未加载的模块,等等。文件很大(本机和局域网环境适用)~
        .dump /ma c:\bigMini.dmp(注:/ma等价于/mfFhut;/m的子参数包括:a,A,f,F,h,u,t,i,p,w,d,c,r,R ).dump命令详细用法

下面列出六种生成Dump文件的方法:

(1)在产品代码中加入自动生成Dump文件功能

使用下面的函数,可以生成一个Dump文件:

BOOL MiniDumpWriteDump (
HANDLE hProcess,
DWORD ProcessId,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);

这个函数定义在dbghelp.dll中,windbg安装目录中带有这个dll,同时在sdk子目录中提供了.h和.lib文件。
在进程捕捉结构化异常的地方,使用这个API生成一个Dump文件。

(2) 使用AdPlus生成Dump文件

windbg附带了一个AdPlus的脚本,可以用于监控进程运行情况,并且可以在发生异常时把进程信息写入到Dump文件中。
如果产品没有自动生成Dump文件的功能,可以通过使用这个工具来弥补缺陷。

通过如下命令来使用AdPlus:

cscript D:\tools\windbg\adplus.vbs -crash -pn DebugTest.exe -o D:\CrashDumps

上述命令的意思是:监控当前运行的DebugTest.exe,如果发生了结构化异常,则生成一个Dump文件到D:\CrashDumps目录中。
关于AdPlus更详细的介绍请参阅:http://support.microsoft.com/kb/286350/zh-cn

(3) 使用windbg生成Dump文件

windbg可以通过命令生成mini-Dump文件:

.dump /mfh D:\CrashDumps\mydumpfile.dmp

(4) win7任务管理器 - 进程标签页 - 创建转储文件

(5) 使用vs2010以上版本生成  在调试状态下[菜单]:调试 - 将转储另存为

(6) 第三方系统工具  如:最新版本的Process Explorer、proccump.exe命令行工具等

注意:

win32程序在64位操作系统上,需要生成dump时,应该生成32位的dump,否则windbg在获取call stack时可能出错,一些sos、psscor2等扩展无法读取dump中的数据,一些命令在获取dump中的信息也会受限。
对于32位dump,应该用x86版的windbg分析(无论是在32位还是64位操作系统上);64位dump,应该用在64位操作系统上使用x64版的windbg进行分析。

分析Dump文件

使用菜单【Open Crash Dump】打开Dump文件,然后打开堆栈观察窗口,此时看到的堆栈可能不是异常发生时的堆栈。

通过如下命令切换到异常发生时的堆栈:

.ecxr

为了分析异常,可以通过下面的语句来获取分析信息,帮助定位问题:

!analyze -v

#参考

http://www.debuginfo.com/resources.html

http://www.debuginfo.com/articles/debuginfomatch.html

http://www.debuginfo.com/articles/gendebuginfo.html

DbgHelp Functions: http://msdn.microsoft.com/en-us/library/ms679291(VS.85).aspx

利用VS2005进行dump文件调试

免责声明:文章转载自《windbg调试基础》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SQL SERVER的DTS功能yml 文件中使用环境变量下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux SVN 操作详解(转)

1、将文件checkout到本地目录 svn checkoutpath(path是服务器上的目录)例如:svn checkout svn://192.168.1.1/pro/domain简写:svn co 2、往版本库中添加新的文件 svnaddfile例如:svnaddtest.php(添加test.php)svnadd*.php(添加当前目录下所...

shell脚本调试技术_转

转自:http://itlab.idcquan.com/linux/SHELL/727128.html 参考:https://linux.cn/article-8045-1.html 本文全面系统地介绍了shell脚本调试技术,包括使用echo, tee, trap等命令输出关键信息,跟踪变量的值,在脚本中植入调试钩子,使用“-n”选项进行shell脚本的...

前端框架Vue自学之Vue CLI(五)

终极目标:掌握和使用Vue(全家桶:Core+Vue-router+Vuex) 本博客目的:记录Vue学习的进度和心得(Vue CLI) 内容:学习和使用Vue CLI2 和 Vue CLI3。如果了解webpack如何一步步配置的,建议可以先看我的前一个博客:前端框架Vue自学之webpack(四)。 正文: Vue CLI 一、Vue CLI 1、前言...

C# fckeditor浏览服务器和上传目录不一致,看不到上传过的文件

fckeditor在上传标签页面,传过文件后,在浏览服务器那里,看不到之前上传的文件,通过浏览服务器页面上传文件,保存的目录也和上传标签页面上传的不是同一个文件夹。 修改方法如下: 打开fckeditoreditorfilemanagerconnectorsaspx目录下的config.ascx,将SetConfig()方法下面的 TypeConfig...

domino控制台命令

Broadcast message 向该服务器的用户广播消息 Broadcast message usernames 向该服务器的某一用户广播消息 Dbcache Flush 关闭当前在数据库高速缓存中打开的所有数据库。使用此命令可以在高速缓存中维护数据库,例如:备份或恢复数据库。 Drop username 关闭一个或多个服务器会话。如果...

Vue 开发规范目录及说明

Vue 开发规范目录及说明 Vue 开发规范目录及说明 命名规范 普通变量命名规范 常量 组件命名规范 views 下的文件命名 结构化规范 目录文件夹及子文件规范 vue 文件基本结构 多个特性的元素规范 元素特性的顺序 组件选项顺序 为组件样式设置作用域 注释规范 务必添加注释列表 单行注释 多行注释 模块 指令规范 Props 规...