缘起
在上一次折腾的过程中遇到了一个小问题 —— 在使用 IDA
查看反汇编的时候,居然搜索不到相关的函数,在 windbg
中使用 x
命令也搜不到,即使加载了符号文件也搜不到。最后发现是 /debug:fastlink
选项导致的。
初遇问题
使用 IDA
打开 vs2017
编译出来的程序,查看反汇编代码,但是没有看到相关函数。
最开始以为是 IDA
加载符号文件的问题,就想着在 windbg
中使用 x
命令看一下,没想到也查看不了。
感觉有些离谱,之前一直好好的,而且这个示例程序非常简单。于是,使用 vs2013
编译同样的代码,然后在 IDA
中查看反汇编的函数,一切正常。又试了试 vs2019
,也一切正常。下图是使用 IDA
查看 vs2019
生成的程序的情况。
根据多年的经验,应该是 pdb
出问题了。难道是 vs2017
在生成 pdb
的过程中有 bug
?不管是不是 bug
,先看看 pdb
的内容,看看到底在哪里失败了。
查看 PDB 内容
在 github
上搜索 pdb
,发现了几个有用的仓库。我列在这里,感兴趣的小伙伴儿可以点进去查看。
- microsoft-pdb 微软官方介绍
pdb
文件格式的仓库。 - PDBRipper 查看
pdb
程序 - raw_pdb 查看
pdb
的c++
库,可以基于此开发自己的工具。 - formatPE 可以查看
PE
文件或者PDB
文件格式的库。
因为 PDBRipper
不用编译即可使用,所以我决定先使用它查看 vs2017
生成的 pdb
文件。发现什么都没有。这是什么情况?赶紧试试 vs2013
和 vs2019
生成的 pdb
文件,发现可以正确的列出很多符号。
至此,我更加怀疑是 vs2017
的问题。具体是什么问题呢?到底问题出在哪里呢?还是要跟踪一下解析过程才能知道。
既然有现成的工具和代码,就不用自己研究 pdb
文件格式,再根据格式写解析程序了。我没有跟踪 PDBRipper
,而是直接调试的 raw_pdb
。
发现关键线索
使用 vs2019
打开 raw_pdb\build\RawPDB.sln
,编译。编译成功后,修改解决方案启动工程并设置好调试参数,加载有问题的 pdb
文件进行调试。简单跟踪几步后,发现在下图中的位置报错返回了。
从提示看,不能正确解析 PDB
是因为生成 PDB
的时候使用了名为 /DEBUG:FASTLINK
的选项。
至此得到了一个非常重要的线索 —— /DEBUG:FASTLINK
。赶紧 google
一下。
搜索
很快就搜到了以下两个非常有用的网址:
http://www.windbg.xyz/windbg/article/204-MSVC-Linker-Option---Generate-Debug-Info
https://devblogs.microsoft.com/cppblog/faster-c-build-cycle-in-vs-15-with-debugfastlink/
https://lists.llvm.org/pipermail/llvm-dev/2017-June/113903.html
根据以上文章,可以得到如下结论:
为了提高链接速度,从
vs2015
开始引入了/DEBUG:fastlink
选项。使用
/DEBUG:fastlink
编译选项生成的PDB
是partitial pdb
,这种pdb
缺少私有符号信息,但是可以提高链接速度。从
Visual Studio 15
(也就是vs2017
)开始,/Debug:fastlink
将成为默认选项。/DEBUG
选项等同于/DEBUG:fastlink
。可以通过
Linker -> Debugging -> Generate Debug Info
来设置使用/DEBUG:fastlink
或者/DEBUG:FULL
。可以通过
vs
安装目录下的VC\bin
子目录下的mspdbcmf.exe
工具从partitial pdb
获得full pdb
。
友情提示: 如果有小伙伴儿不清楚
vs
各个版本名称与版本号的对应关系,可以参考下图。
看完以上几篇文章基本明白了原因。
赶紧在 vs2017
中修改对应的设置为 /DEBUG:FULL
,然后在 windbg
中使用 x
命令查看,果然出现了期待已久的函数。
当然,肯定也得用 mspdbcmf.exe
转换成 full pdb
试试,结果也是很 ok
的。
说明
经过验证,使用 vs2019
新建工程后,Generate Debug Info
的默认选项是 /DEBUG
。但是使用默认选项生成的程序在调试的时候,并不存在不能查看符号的问题。看来,vs2019
又把 /DEBUG
选项处理成 /DEBUG:FULL
了。
其它资源
在调查这个问题的时候还搜到一些相关的网址,感兴趣的小伙伴儿可以看一下。
下面这篇文章是译文,讲的是 /DEBUG:fastlink
在缩短链接时间上的好处。
https://www.topomel.com/archives/3221.html
下面这篇是国外网友遇到的不能使用 DIA SDK
读取使用 /DEBUG:fastlink
选项编译生成的 Partitial PDB
的问题。
https://developercommunity.visualstudio.com/t/dia-sdk-still-doesnt-support-debugfastlink/4631
下面这篇是国外网友遇到的,在使用 vtune
分析使用 /DEBUG:fastlink
选项编译的程序,加载符号文件导致的卡死问题。
总结
可以使用很多工具查看
pdb
的内容,比如PDBRipper
。使用
/DEBUG:fastlink
可以降低链接所需要的时间。使用
/DEBUG:fastlink
生成的是partitial pdb
,这种pdb
中并不包含缺少私有符号,调试的时候会有不能查看符号的问题。可以使用
mspdbcmf.exe
把partitial pdb
转换成full pdb
。