最近,接到一个活,要写一个程序,用来批量分析一堆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。

具体一点,就是这样。

 PCHAR pBuffer = (PCHAR)h;
PCHAR pTemp = pBuffer + 0x3C;
pTemp = pBuffer + *(DWORD *)pTemp;
if (!(pTemp[] == 'P' && pTemp[] == 'E' && pTemp[] == '\0' && pTemp[] == '\0'))
{
return NULL;
}
PVOID *pv;
pv = (PVOID*)(pTemp + 0xA8); // 找到调试节
pTemp = pBuffer + (DWORD)*pv; // 计算调试节指定的内存地址
pv = (PVOID *)(pTemp + * ); // 找到偏移
pTemp = pBuffer + (DWORD)*pv; // 找到 UUID 基址
if (!(pTemp[] == 'R' && pTemp[] == 'S' && pTemp[] == 'D' && pTemp[] == 'S'))
{
return NULL;
}
GUID tGuid = { };
memcpy_s(&tGuid, sizeof(tGuid), pTemp + , sizeof(tGuid));

先根据可执行文件,找到PE头,从PE头里面找到调试节,

调试节里面找到GUID的偏移地址,

GUID偏移地址的前四个字符固定是RSDS,判断了之后,如果没有问题,

那么之后就是一个GUID的长度,

最后把这个GUID格式化出来变成字符串,最后再在后面补一个字符 '1' 即拼装成了当前文件对应的PDB目录名字,

然后通过这个目录名字可以拼接出一个完整的目录,很像Windows dbghelp.dll 拼接出来的目录,

然后去里面就能找到自己对应的pdb。

整个过程叙述结束。

最后总结一下。

解决pdb无法加载的方法:自己下载,独立加载。

方法:

1:使用WinDBG命令行下载可执行文件对应的PDB文件。

2:根据可执行文件计算PDB路径,寻找目标PDB。

3:找到目标PDB之后,loadDataFromPdb 直接加载PDB就好了。

最新文章

  1. 关于Window Server2008 服务器上无法播放音频文件的解决方案
  2. 使用zxing生成二维码
  3. SQL语句里怎么获得当前年份(MySQL数据库)
  4. android github
  5. spring整合freemarker 自定义标签
  6. 20160122.CCPP详解体系(0001天)
  7. leetcode-WordLadder
  8. WPF绘制党徽(立体效果,Cool)
  9. Webservice 实践
  10. url_for()中的坑,url_for操作对象是函数,而不是route里的路径
  11. c51的学习
  12. day-08文件的操作
  13. C#版 - 剑指offer 面试题9:斐波那契数列及其变形(跳台阶、矩形覆盖) 题解
  14. 使用Python进行并发编程
  15. Python基础(十三) 为什么说python多线程没有真正实现多现程
  16. 140 - The 12th Zhejiang Provincial Collegiate Programming Contest(第三部分)
  17. go标准库的学习-database/sql/driver
  18. java网页数据抓取实例
  19. 腾讯云服务器 安装fastdfs文件服务器
  20. spss-非参数检验-K多个独立样本检验( Kruskal-Wallis检验)案例解析

热门文章

  1. linux性能分析工具Swap
  2. linux驱动启动顺序
  3. Kintex7 XC7K325T 板卡五兄弟
  4. canvas 绘制二次贝塞尔曲线
  5. 排查Java高CPU占用原因
  6. 如何在Sketch 54 for mac创建符号?
  7. firewall&iptables
  8. 重磅干货免费下载!阿里云RDS团队论文被数据库顶会SIGMOD 2018收录
  9. 阿里云数据库备份DBS商业化发布,数据库实时备份到OSS
  10. php ucfirst()函数 语法