在上一次折腾的过程中遇到了一个小问题 —— 在使用 IDA 查看反汇编的时候,居然搜索不到相关的函数,在 windbg 中使用 x 命令也搜不到,即使加载了符号文件也搜不到。最后发现是 /debug:fastlink 选项导致的。
IDA
windbg
x
/debug:fastlink
使用 IDA 打开 vs2017 编译出来的程序,查看反汇编代码,但是没有看到相关函数。
vs2017
最开始以为是 IDA 加载符号文件的问题,就想着在 windbg 中使用 x 命令看一下,没想到也查看不了。
感觉有些离谱,之前一直好好的,而且这个示例程序非常简单。于是,使用 vs2013 编译同样的代码,然后在 IDA 中查看反汇编的函数,一切正常。又试了试 vs2019,也一切正常。下图是使用 IDA 查看 vs2019 生成的程序的情况。
vs2013
vs2019
根据多年的经验,应该是 pdb 出问题了。难道是 vs2017 在生成 pdb 的过程中有 bug?不管是不是 bug,先看看 pdb 的内容,看看到底在哪里失败了。
pdb
bug
在 github 上搜索 pdb,发现了几个有用的仓库。我列在这里,感兴趣的小伙伴儿可以点进去查看。
github
因为 PDBRipper 不用编译即可使用,所以我决定先使用它查看 vs2017 生成的 pdb 文件。发现什么都没有。这是什么情况?赶紧试试 vs2013 和 vs2019 生成的 pdb 文件,发现可以正确的列出很多符号。
PDBRipper
至此,我更加怀疑是 vs2017 的问题。具体是什么问题呢?到底问题出在哪里呢?还是要跟踪一下解析过程才能知道。
既然有现成的工具和代码,就不用自己研究 pdb 文件格式,再根据格式写解析程序了。我没有跟踪 PDBRipper,而是直接调试的 raw_pdb。
raw_pdb
使用 vs2019 打开 raw_pdb\build\RawPDB.sln,编译。编译成功后,修改解决方案启动工程并设置好调试参数,加载有问题的 pdb 文件进行调试。简单跟踪几步后,发现在下图中的位置报错返回了。
raw_pdb\build\RawPDB.sln
从提示看,不能正确解析 PDB 是因为生成 PDB 的时候使用了名为 /DEBUG:FASTLINK 的选项。
PDB
/DEBUG:FASTLINK
至此得到了一个非常重要的线索 —— /DEBUG:FASTLINK。赶紧 google 一下。
google
很快就搜到了以下两个非常有用的网址:
ab8K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4N6A6L8X3c8T1k6#2)9J5k6i4S2&6P5W2)9J5c8Y4N6A6L8X3c8T1k6#2)9J5c8X3q4J5N6r3W2U0L8r3g2Q4x3V1j5J5x3o6c8Q4x3X3c8y4f1#2k6o6i4K6u0V1e0r3W2F1K9$3g2J5i4K6u0V1e0%4m8@1K9h3!0F1i4K6u0V1i4K6u0V1i4K6u0V1c8$3g2F1k6i4u0S2N6r3g2Q4x3X3c8p5k6h3u0#2k6#2)9J5k6p5W2F1k6X3)9`.
ef7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6T1L8r3!0Y4M7#2)9J5k6h3#2A6j5%4u0G2M7$3!0X3N6q4)9J5k6h3y4G2L8g2)9J5c8X3y4H3M7r3u0D9L8$3N6Q4x3V1k6X3j5i4y4@1k6i4u0Q4x3X3c8U0i4K6u0V1j5Y4g2A6L8r3c8Q4x3X3c8U0P5h3y4D9k6g2)9J5k6r3W2F1i4K6u0V1N6Y4y4Q4x3X3b7I4y4g2)9J5k6s2N6A6N6r3S2Q4x3X3c8V1k6h3u0#2k6$3k6S2M7%4c8D9K9h3&6C8i4K6u0r3
d69K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6D9K9i4y4@1M7#2)9J5k6h3I4D9N6X3#2Q4x3X3g2G2M7X3N6Q4x3V1k6H3K9i4m8W2M7X3#2S2K9h3I4Q4x3V1k6D9L8s2k6E0i4K6u0V1k6r3g2$3i4K6u0r3x3U0l9I4y4#2)9J5k6p5A6#2L8X3g2Q4x3V1j5I4x3e0x3&6x3o6y4Q4x3X3g2Z5N6r3#2D9
根据以上文章,可以得到如下结论:
为了提高链接速度,从 vs2015 开始引入了 /DEBUG:fastlink 选项。
vs2015
/DEBUG:fastlink
使用 /DEBUG:fastlink 编译选项生成的 PDB 是 partitial pdb,这种 pdb 缺少私有符号信息,但是可以提高链接速度。
partitial pdb
从Visual Studio 15 (也就是 vs2017)开始,/Debug:fastlink 将成为默认选项。/DEBUG 选项等同于 /DEBUG:fastlink 。
Visual Studio 15
/Debug:fastlink
/DEBUG
可以通过 Linker -> Debugging -> Generate Debug Info 来设置使用 /DEBUG:fastlink 或者 /DEBUG:FULL。
Linker -> Debugging -> Generate Debug Info
/DEBUG:FULL
友情提示: 如果有小伙伴儿不清楚 vs 各个版本名称与版本号的对应关系,可以参考下图。
vs
看完以上几篇文章基本明白了原因。
赶紧在 vs2017 中修改对应的设置为 /DEBUG:FULL,然后在 windbg 中使用 x 命令查看,果然出现了期待已久的函数。
当然,肯定也得用 mspdbcmf.exe 转换成 full pdb 试试,结果也是很 ok 的。
mspdbcmf.exe
full pdb
ok
经过验证,使用 vs2019 新建工程后,Generate Debug Info 的默认选项是 /DEBUG。但是使用默认选项生成的程序在调试的时候,并不存在不能查看符号的问题。看来,vs2019 又把 /DEBUG 选项处理成 /DEBUG:FULL 了。
Generate Debug Info
在调查这个问题的时候还搜到一些相关的网址,感兴趣的小伙伴儿可以看一下。
下面这篇文章是译文,讲的是 /DEBUG:fastlink 在缩短链接时间上的好处。
306K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2@1L8%4m8G2L8h3g2D9i4K6u0W2j5$3!0E0i4K6u0r3j5i4u0U0K9r3W2$3k6i4y4Q4x3V1j5K6x3U0t1I4i4K6u0W2K9s2c8E0L8l9`.`.
下面这篇是国外网友遇到的不能使用 DIA SDK 读取使用 /DEBUG:fastlink 选项编译生成的 Partitial PDB 的问题。
DIA SDK
Partitial PDB
a82K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0U0L8$3#2E0N6h3&6A6N6s2W2Q4x3X3g2$3K9i4y4#2j5h3I4K6N6s2g2V1K9h3!0Q4x3X3g2U0L8$3#2Q4x3V1k6@1i4K6u0r3k6r3W2S2i4K6u0V1M7$3c8C8i4K6u0V1M7%4c8A6L8r3I4Q4x3X3c8V1L8$3g2K6L8Y4c8Q4x3X3c8K6N6i4m8H3L8%4u0@1i4K6u0V1k6r3g2T1N6h3N6X3j5i4y4@1L8r3W2F1K9#2)9J5c8U0b7$3x3K6p5`.
下面这篇是国外网友遇到的,在使用 vtune 分析使用 /DEBUG:fastlink 选项编译的程序,加载符号文件导致的卡死问题。
vtune
f3aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0L8$3#2E0N6h3&6A6N6s2W2Q4x3X3g2A6L8Y4c8W2L8q4)9J5k6h3y4G2L8g2)9J5c8Y4b7#2i4K6u0r3b7h3&6S2L8s2W2*7k6i4u0K6i4K6u0r3g2h3&6S2j5X3I4W2i4K6u0V1N6r3!0Q4x3X3c8D9L8$3q4V1i4K6u0V1M7r3c8T1i4K6u0V1k6X3W2D9k6i4y4Q4x3X3c8S2k6Y4c8W2M7W2)9J5k6s2m8J5L8$3k6A6L8r3W2F1k6#2)9J5k6s2g2K6K9h3&6Y4i4K6u0V1g2W2x3J5x3o6p5&6i4K6u0r3L8g2)9J5k6s2m8Q4x3V1j5I4x3e0j5#2y4o6b7#2
可以使用很多工具查看 pdb 的内容,比如 PDBRipper。
使用 /DEBUG:fastlink 可以降低链接所需要的时间。
[培训]科锐逆向工程师培训第53期2025年7月8日开班!