我想我不需要强调在调试时拥有有效的PDB文件有多重要。通常,PDB文件是由调试器静默加载的,并且您很高兴在modules窗口中看到解析的所有符号。不幸的是,您还可能遇到调试器找不到匹配符号的情况。其原因可能与断开的互联网连接或更复杂的签名不匹配一样微不足道。在本文中,我将向您展示如何在调试之前检查符号文件,以及如何从中提取源文件信息。由于有不同的方法(和工具)来操作符号文件,我将介绍我所知道的那些。

下载给定PE文件的PDB文件

由于PDB文件格式是微软的秘密,所以我介绍的所有工具都只是API的包装器。要处理PDB文件,我们首先需要获取它们。让我们列出能帮助我们的工具。

symchk.exe

符号检查器(Symchk.exe)是一个应用程序,它将可执行文件与符号文件进行比较,以验证匹配的符号是否可用。Symchk也可以用于填充符号缓存。它可以从PE文件(exe,dll)、转储文件和进程中读取符号信息。它还支持递归目录搜索和批处理文件。

我们将从加载kernel32.dll库的符号开始:

c:\Windows\System32>echo %_NT_SYMBOL_PATH%
 
c:\Windows\System32>symchk /v /os kernel32.dll
[SYMCHK] Searching for symbols to c:\Windows\System32\kernel32.dll in path SRV*C:\Symbols\MSS*http://referencesource.microsoft.com/symbols;SRV*C:\Symbols\MSS*http://msdl.microsoft.com/download/symbols
DBGHELP: Symbol Search Path: SRV*C:\Symbols\MSS*http://referencesource.microsoft.com/symbols;SRV*C:\Symbols\MSS*http://msdl.microsoft.com/download/symbols
[SYMCHK] Using search path "SRV*C:\Symbols\MSS*http://referencesource.microsoft.com/symbols;SRV*C:\Symbols\MSS*http://msdl.microsoft.com/download/symbols"
DBGHELP: No header for c:\Windows\System32\kernel32.dll.  Searching for image on disk
DBGHELP: c:\Windows\System32\kernel32.dll - OK
SYMSRV:  C:\Symbols\MSS\kernel32.pdb\9B30FD7CD6B44975BF34B43B6EF668212\kernel32.pdb not found
SYMSRV:  kernel32.pdb from http://msdl.microsoft.com/download/symbols: 704453 bytes - copied
DBGHELP: kernel32 - public symbols
         C:\Symbols\MSS\kernel32.pdb\9B30FD7CD6B44975BF34B43B6EF668212\kernel32.pdb
[SYMCHK] MODULE64 Info ----------------------
[SYMCHK] Struct size: 1680 bytes
[SYMCHK] Base: 0x0000000078D20000
[SYMCHK] Image size: 1175552 bytes
[SYMCHK] Date: 0x4e21213b
[SYMCHK] Checksum: 0x0012386d
[SYMCHK] NumSyms: 0
[SYMCHK] SymType: SymPDB
[SYMCHK] ModName: kernel32
[SYMCHK] ImageName: c:\Windows\System32\kernel32.dll
[SYMCHK] LoadedImage: c:\Windows\System32\kernel32.dll
[SYMCHK] PDB: "C:\Symbols\MSS\kernel32.pdb\9B30FD7CD6B44975BF34B43B6EF668212\kernel32.pdb"
[SYMCHK] CV: RSDS
[SYMCHK] CV DWORD: 0x53445352
[SYMCHK] CV Data:  kernel32.pdb
[SYMCHK] PDB Sig:  0
[SYMCHK] PDB7 Sig: {9B30FD7C-D6B4-4975-BF34-B43B6EF66821}
[SYMCHK] Age: 2
[SYMCHK] PDB Matched:  TRUE
[SYMCHK] DBG Matched:  TRUE
[SYMCHK] Line nubmers: FALSE
[SYMCHK] Global syms:  FALSE
[SYMCHK] Type Info:    FALSE
[SYMCHK] ------------------------------------
SymbolCheckVersion  0x00000002
Result              0x00030001
DbgFilename
DbgTimeDateStamp    0x4e21213b
DbgSizeOfImage      0x0011f000
DbgChecksum         0x0012386d
PdbFilename         C:\Symbols\MSS\kernel32.pdb\9B30FD7CD6B44975BF34B43B6EF668212\kernel32.pdb
PdbSignature        {9B30FD7C-D6B4-4975-BF34-B43B6EF66821}
PdbDbiAge           0x00000002
[SYMCHK] [ 0x00000000 - 0x00030001 ] Checked "c:\Windows\System32\kernel32.dll"
 
SYMCHK: FAILED files = 0
SYMCHK: PASSED + IGNORED files = 1

正如您在详细模式(/v开关)中看到的,您收到了很多关于symchk正在做什么的信息。我们甚至可以读取它使用的符号API(dbghelp消息)。/os开关通知symchk打印输出消息中符号文件的完整路径。运行此命令后,kernel32.pdb文件应该在符号存储中。如果您想索引整个System32目录,您需要使用/r开关,它通知symchk递归地遍历提供的目录并下载找到的所有文件的符号,eg. symchk /r /v c:\windows\system32\*.dll

让我们尝试加载notepad.exe进程的符号:

c:\temp\symtest>tasklist /FI "IMAGENAME eq notepad.exe"
 
Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
notepad.exe                   2264 Console                    1      6 036 K
 
c:\temp\symtest>symchk /ip 2264 /s SRV*.*http://msdl.microsoft.com/download/symbols
 
SYMCHK: FAILED files = 0
SYMCHK: PASSED + IGNORED files = 26

使用/ip开关,我们可以只提供进程ID,symchk将为进程中加载的所有模块下载符号文件。在这个例子中,我们还使用了/s开关,它为symchk提供它应该使用的符号路径(如果设置了,则覆盖symchk的_NT_SYMBOL_PATH)。在我们的例子中,我们将符号文件从Microsoft公共服务器下载到当前目录。运行此命令后,此目录的列表如下所示:

c:\temp\symtest>tree .
Folder PATH listing
Volume serial number is 00000002 C622:C13F
C:\TEMP\SYMTEST
├───advapi32.pdb
│   └───6AEFDCFF7F2A429B8532CD2BFDDF85D12
├───CLBCatQ.pdb
│   └───60B9D310C472440BA13F66BFF0FC39E32
├───comctl32.pdb
│   └───943BA638A2CD4D88A1C7E7418EAF796C1
├───comdlg32.pdb
│   └───631B57376F8549FDB2E7A8AB3D2D1FDF2
├───cryptbase.pdb
│   └───F03E074BB9E74C9F9BBFB0E42EF3A0AB2
├───dwmapi.pdb
│   └───8683ED0C3DBE4053883EC22FD9B4F2102
├───gdi32.pdb
│   └───FB9403C3B1304DA192C4D0E3485E25ED2
├───imm32.pdb
│   └───98F27BA5AEE541ECBEE00CD03AD50FEE2
├───kernel32.pdb
│   └───9B30FD7CD6B44975BF34B43B6EF668212
├───kernelbase.pdb
│   └───61044362232B410AA600843CEBFD11612
...

另一个有趣的开关是(/id),它使您能够调试转储文件。symchk.exe的另一个伟大功能是称为清单文件的东西。清单文件包含有关必须下载的所有符号的信息。然后,可以使用/om开关运行symchk,该开关将生成清单文件,而无需下载任何符号。然后,可以将清单文件复制到具有Internet连接的任何计算机上,并使用/im开关下载符号文件。下面的代码片段显示了一个使用示例:

c:\temp\symtest>symchk /om notepad-symbols.man /ip 2264
 
SYMCHK: FAILED files = 0
SYMCHK: PASSED + IGNORED files = 26
 
c:\temp\symtest>type notepad-symbols.man
notepad.pdb,36CFD5F9888C4483B522B9DB242D84782,1
notepad.exe,4a5bc9b335000,1
ntdll.pdb,6192BFDB9F04442995FFCB0BE95172E12,1
ntdll.dll,4ce7c8f91a9000,1
kernel32.pdb,9B30FD7CD6B44975BF34B43B6EF668212,1
kernel32.dll,4e21213b11f000,1
kernelbase.pdb,61044362232B410AA600843CEBFD11612,1
KernelBase.dll,4e21213c6c000,1
...
c:\temp\symtest>symchk /im notepad-symbols.man /s SRV*.*http://msdl.microsoft.com/download/symbols
 
SYMCHK: FAILED files = 0
SYMCHK: PASSED + IGNORED files = 52

dbh.exe

这个工具是DbgHelp.dll库的包装器,它揭示了几乎所有的功能。我们将只看一个使用示例,因此如果您想更深入地了解Windows帮助的调试工具。当以模块名作为参数运行dbh.exe时,它将自动下载符号文件。因此,只要调用dbh c:\ windows\system32\kernel32.dll info,您就可以下载符号文件(使用了_NT_SYMBOL_PATH环境变量),并打印有关该文件及其PE文件(kernel32.dll)的信息:

c:\temp>dbh c:\windows\system32\kernel32.dll info
 
    SizeOfStruct : 0x690
     BaseOfImage : 0x1677721664x
       ImageSize : 0x1000000
   TimeDateStamp : 0x4e21213b
        CheckSum : 0x12386d
         NumSyms : 0x0
         SymType : SymPdb
      ModuleName : kernel32
       ImageName : c:\windows\system32\kernel32.dll
 LoadedImageName : c:\windows\system32\kernel32.dll
   LoadedPdbName : C:\Symbols\MSS\kernel32.pdb\9B30FD7CD6B44975BF34B43B6EF668212\kernel32.pdb
           CVSig : 0x53445352
          CVData : kernel32.pdb
          PdbSig : 0x0
        PdbSig70 : 0x9b30fd7c, 0xd6b4, 0x4975, 0xbf, 0x34, 0xb4, 0x3b, 0x6e, 0xf6, 0x68, 0x21
          PdbAge : 0x2
    PdbUnmatched : false
    DbgUnmatched : false
     LineNumbers : false
   GlobalSymbols : false
        TypeInfo : false
   SourceIndexed : false
   PublicSymbols : true
     MachineType : X64

如果您想查看有关加载的PDB文件的详细信息,请使用-n开关。要更改默认符号路径(或覆盖符号路径设置),请使用-s:开关。

dumpbin.exe

您可能会惊讶于这个工具出现在这里,但是您是否注意到它的/PDBPATH[:VERBOSE]开关?在kernel32.dll库中发出dumpbin/pdbpath:verbose将导致从公共符号存储下载PDB文件:

c:\temp\symtest>dumpbin /pdbpath:verbose c:\windows\system32\kernel32.dll
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.
 
Dump of file c:\windows\system32\kernel32.dll
 
File Type: DLL
  PDB file 'c:\windows\system32\kernel32.pdb' checked.  (File not found)
  PDB file 'c:\temp\symtest\kernel32.pdb' checked.  (File not found)
  PDB file found at 'C:\Symbols\MSS\kernel32.pdb\9B30FD7CD6B44975BF34B43B6EF668212\kernel32.pdb'
 
  Summary
 
        2000 .data
        A000 .pdata
       6E000 .rdata
        8000 .reloc
        1000 .rsrc
       9B000 .text

从源服务器下载源代码

srctool.exe

这个工具非常有趣,因为它允许您检查PDB文件中索引的源文件,并最终提取它们。使用-r开关,您可以检查PDB文件中哪些源代码路径是硬编码的

c:\temp>srctool -r ConsoleApplication1.pdb
D:\lab\symbols-lab\symbols\ConsoleApplication1\Program.cs
D:\lab\symbols-lab\symbols\ConsoleApplication1\AdvertQuickView.cs

没有任何开关,SRCooT将检查PDB文件中的源服务器流(如果存在)和将执行以提取源文件的打印命令,例如:

c:\temp>srctool ConsoleApplication1.pdb
[D:\lab\symbols-lab\symbols\ConsoleApplication1\Program.cs] cmd: cmd /c svn.exe cat "svn://localhost/test2/Program.cs@1" --non-interactive --username admin --password admin > "
[D:\lab\symbols-lab\symbols\ConsoleApplication1\AdvertQuickView.cs] cmd: cmd /c svn.exe cat "svn://localhost/test2/AdvertQuickView.cs@1" --non-interactive --username admin --password admin > "
 
ConsoleApplication1.pdb: 2 source files are indexed

要运行命令并提取源文件,只需在上面的调用中添加-x开关。此外,还可以使用-d开关指定要将源文件提取到的目录(默认情况下是当前目录)。

pdbstr

如果希望更好地控制源服务器流,可以检查pdbstr命令。借助它,您可以读取和更新PDB文件中的源服务器信息。源服务器流实际上是一个带有预定义节的文本块(可以在这里找到更多信息)。您可以通过发布以下内容来转储其内容:

c:\temp>pdbstr -r -p:ConsoleApplication1.pdb -s:srcsrv > stream.txt

stream.txt文件应包含如下内容:

SRCSRV: ini ------------------------------------------------
VERSION=1
INDEXVERSION=2
VERCTRL=Subversion
DATETIME=Thu Nov 17 13:31:46 2011
SRCSRV: variables ------------------------------------------
SVNUSER=admin
SVNPASS=admin
SVN_EXTRACT_TARGET=%targ%\%fnbksl%(%var3%)\%var4%\%fnfile%(%var1%)
SVN_EXTRACT_CMD=cmd /c svn.exe cat "%var2%%var3%@%var4%" --non-interactive --username %svnuser% --password %svnpass% > "
%svn_extract_target%"
SRCSRVTRG=%SVN_extract_target%
SRCSRVCMD=%SVN_extract_cmd%
SRCSRV: source files ---------------------------------------
D:\lab\symbols-lab\symbols\ConsoleApplication1\Program.cs*svn://localhost/*test2/Program.cs*1
D:\lab\symbols-lab\symbols\ConsoleApplication1\AdvertQuickView.cs*svn://localhost/*test2/AdvertQuickView.cs*1
SRCSRV: end ------------------------------------------------
然后,可以应用所需的更改并将新的源流定义保存回PDB文件:
c:\temp>pdbstr -w -p:ConsoleApplication1.pdb -s:srcsrv -i:stream.txt

Pdbstr不会为您提取源代码文件,而是从源流内容中提取,您可以很容易地在哪里找到它们。这将结束我们的PDB工具列表-我希望您会发现它很有用。

PDB files out of the debugger的更多相关文章

  1. PDB Files: What Every Developer Must Know

    Reference:  http://www.wintellect.com/blogs/jrobbins/pdb-files-what-every-developer-must-know Most d ...

  2. PDB文件:每个开发人员都必须知道的 PDB Files

    PDB文件:每个开发人员都必须知道的   PDB Files: What Every Developer Must Knowhttp://www.wintellect.com/CS/blogs/jro ...

  3. Do PDB Files Affect Performance?

    After a detour into Historical Debugging, it's time to come back to return to answering questions ab ...

  4. Why is Visual Studio 2015 not able to find or open PDB files?

    first change parameters, Tools->Options->Debugging->Symbols->Microsoft Symbol Server, ye ...

  5. vs2010调试程序出现“Cannot find or open the PDB file”

    项目中源程序编写好以后, (一个简单的小程序) #include int main(void) { int age; int day; age = 24; printf("tom is %d ...

  6. PDB文件:每个开发人员都必须知道的

    PDB Files: What Every Developer Must Knowhttp://www.wintellect.com/CS/blogs/jrobbins/archive/2009/05 ...

  7. C# dmp debug, can't load pdb file

    1.  Project->Properties->Build->Advance, Debug Info : Full/pdb-only . set to [none] will no ...

  8. pdb文件 PDB文件:每个开发人员都必须知道的 .NET PDB文件到底是什么?

    pdb文件包含了编译后程序指向源代码的位置信息,用于调试的时候定位到源代码,主要是用来方便调试的. 在程序发布为release模式时,建议将 pdb文件删除, 同时,对外发布的时候,也把 pdb删除, ...

  9. pdb文件及引发的思考

    最初只想知道线上iis里需要不需要pdb文件,了解部分之后对于.net底层产生了浓厚的兴趣,看了一点点资料 资料来源: https://www.cnblogs.com/itech/archive/20 ...

随机推荐

  1. Spring boot使用influxDB总结

    项目中需要存放大量设备日志,且需要对其进行简单的数据分析,信息提取工作. 结合众多考量因素,项目决定使用时序数据库中的领头羊InfluxDB. 引入依赖 项目中使用influxdb-java,在pom ...

  2. 如何用代码设置机器人初始坐标实现 2D Pose Estimate功能

    前言:ROS机器人有时候会遇到极端的情况:比如地面打滑严重,IMU精度差,导致积累误差严重,或是amcl匹配错误,导致机器人定位失败, 这时候如何矫正机器人位置变得非常重要,我的思路是利用相机或是在地 ...

  3. LeetCode 561:数组拆分 I Array Partition I

    文章全部来自公众号:爱写bug 算法是一个程序的灵魂. Given an array of 2n integers, your task is to group these integers into ...

  4. session的工作原理与session用法

    一直在使用session存储数据,一直没有好好总结一下session的使用方式以及其工作原理,今天在这里做一下梳理. 这里的介绍主要是基于php语言,其他的语言操作可能会有差别,但基本的原理不变. 1 ...

  5. 每个php程序员都应该知道的15个最佳PHP库

    PHP是一种功能强大的web站点脚本语言,通过PHP,web网站开发者可以更容易地创建动态的引人入胜的web页面.开发人员可以使用PHP代码与一些网站模板和框架来提升功能和特性.然而,编写PHP代码是 ...

  6. Pandas操作excel

    读取excel:Pandas库read_excel()参数详解 pandas.read_excel(io,sheet_name = 0,header = 0,names = None,index_co ...

  7. 设置a标签,实现点击跳转页面的两种效果

    设置a标签,实现点击跳转页面 这个问题,主要是设置a标签的属性target,下面对target属性进行描述: 跳转在同一个窗口 1,target="_self",  它使得目标文档 ...

  8. 获取Url地址中参数的3种方法【华为云技术分享】

    获取Url的代码如下:window.location.href; 方法一:原生js(假设已经获得了Url地址) var url = 'https://gitbook.cn/gitchat/geekbo ...

  9. golang --- fmt.printf I/O 函数格式化说明

    说明 fmt 包实现了格式化 I/O 函数,类似于 C 的 printf 和 scanf格式“占位符”衍生自 C,但比 C 更简单 常用格式化输出 fmt.Printf("start at ...

  10. Go的流程控制

    流程控制 Go语言支持最基本的三种程序运行结构:顺序结构.选择结构.循环结构. 顺序结构:程序按顺序执行,不发生跳转. 选择结构:依据是否满足条件,有选择的执行相应功能. 循环结构:依据条件是否满足, ...