我想我不需要强调在调试时拥有有效的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. 微信企业号SDK

    1. 微信企业号SDK class class_wxqiye { var $corpid = CorpID; var $corpsecret = CorpSecret; var $agentid = ...

  2. python运维开发常用模块(一)psutil

    1.模块简介 psutil是一个跨平台库(http://code.google.com/p/psutil/),能够轻 松实现获取系统运行的进程和系统利用率(包括CPU.内存.磁盘.网 络等)信息.它主 ...

  3. 执行"rm -rf /"之后世界安静了吗

    对于Unix/Linux程序员来说,"rm -rf /"一直被认为是一个极度危险的操作,因为直接把根目录给删除了,整个操作系统也就崩溃了.但实际上会是这样的吗?呵呵,请看图: 啊哈 ...

  4. python调用MySQL数据库

    在Python中访问mysql数据库中的数据需要三步骤: 1,建立连接 2,操作数据库 3,连接关闭

  5. 大型情感剧集Selenium:6_selenium中的免密登陆与cookie操作【华为云技术分享】

    网站登录 现在各大平台在反爬虫功能上,可谓花样繁多.总结下来按照破解成功率排名,最高的是滑动解锁.其次是验证码数字.之后是一次点击对应的汉字,最后是想12306之前那种反人类的让你说那些是奶糖吧,哈哈 ...

  6. JavaScript 加减危机——为什么会出现这样的结果?

    在日常工作计算中,我们如履薄冰,但是 JavaScript 总能给我们这样那样的 surprise~ 0.1 + 0.2 = ? 1 - 0.9 = ? 如果小伙伴给出内心的结果: 0.1 + 0.2 ...

  7. EF连接mysql,出现A call to SSPI failed错误,解决办法

    我的使用场景是用EF连接AWS的mysql RDS,会偶发性的出现A call to SSPI failed错误, System.AggregateException: One or more err ...

  8. C# vb .NET读取识别条形码线性条码UPC-A

    UPC-A是比较常见的条形码编码规则类型的一种.如何在C#,vb等.NET平台语言里实现快速准确读取该类型条形码呢?答案是使用SharpBarcode! SharpBarcode是C#快速高效.准确的 ...

  9. iTextSharp生成pdf含模板(一)---制作pdf模板

    参考地址:https://www.cnblogs.com/ibeisha/p/itextsharp-pdf.html 一.使用场景:在线填写一些信息,根据对应的信息生成奖状. 二.解决方案 1.新建w ...

  10. redis集群cluster简单设置

    环境: 这里参考官方使用一台服务器:Centos 7  redis-5.0.4    192.168.10.10 redis集群cluster最少要3个主节点,所以本次需要创建6个实例:3个主节点,3 ...