最近,接到一个活,要写一个程序,用来批量分析一堆dll和对应的PDB,
其实工作很简单,就是根据一堆偏移,通过PDB文件,找到对应dll里面对应位置的明文符号,
简单的需求,实现起来,通常都很麻烦,
微软的demo中,有一个demo叫做dia,这个demo可以提供类似的功能,
我很高兴地编译了这个项目,但是失败了,加载符号失败,
通过单步调试,越过了若干个小问题(比如msdia120没注册这种),发现出现问题的位置位于 loadDataForExe 这个函数上,
这个函数原型是
virtual HRESULT STDMETHODCALLTYPE loadDataForExe( LPCOLESTR executable, LPCOLESTR searchPath, IUnknown *pCallback) = 0
可以看出,参数1是要解析的可执行文件,参数2是目标dll活着exe,参数3是一个接口,可以为NULL,或者按照微软demo中不用修改。
但是执行之后发现,它给我报错,说路径错误,无法找到目标pdb。
具体错误细节不说了,浪费时间。
说说怎么解决这个问题吧。
解决方式比较简单,
首先确定思路,这个函数不能用,说明它不能自己下载符号了,那么怎么办,
解决办法就是我们下载符号,然后让它直接加载就好了,另一个函数是可以用的 loadDataFromPdb。
确定了思路,那么就要铺平道路,我怎么怎么自己下载符号,
最简单的办法,其实就是使用Windows自己的下载功能,为了尽量少开发,所以可以使用WinDBG内部的功能来自动下载符号。
这样,符号文件有了,加载方式有了,就差如何把符号文件和可执行文件对应起来了,如何对应。
通过分析,我们发现,实际上符号文件落地之后是有个特殊的目录名字的,这个名字很像一个MD5,或者很像一个GUID,
通过分析程序,最终发现,这个目录名字实际上是可执行文件内部记录的一个GUID,再在最后补上一个字符 1。
具体一点,就是这样。
1 PCHAR pBuffer = (PCHAR)h; 2 PCHAR pTemp = pBuffer + 0x3C; 3 pTemp = pBuffer + *(DWORD *)pTemp; 4 if (!(pTemp[0] == 'P' && pTemp[1] == 'E' && pTemp[2] == '