• windbg调试基础


    #工作空间 [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还没使用过该调试方式。

    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下使用的符号表文件一般是.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为存放符号的下载目录

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

    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中

    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

    0. Attach方式

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

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

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

    如果要观察主线程堆栈,需要切换到主线程(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分类:

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

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

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

    问题签名:
      问题事件名称:	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

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

    不同信息量的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文件调试

  • 相关阅读:
    归并、希尔排序
    堆排序
    [模板] 最小树形图/朱刘算法
    [模板] 常系数线性递推
    [模板] Kruskal算法 && 克鲁斯卡尔重构树
    [模板] 斯特林数,性质以及求法
    这几天想干什么
    奇怪的 Markdown / LaTeX 笔记
    [模板] 各种莫队
    [模板] 2-SAT 问题
  • 原文地址:https://www.cnblogs.com/kekec/p/2755924.html
Copyright © 2020-2023  润新知