Windows开发,关于通过写代码加载PDB的那些事
最近,接到一个活,要写一个程序,用来批量分析一堆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] == '\0' && pTemp[3] == '\0')) 5 { 6 return NULL; 7 } 8 PVOID *pv; 9 pv = (PVOID*)(pTemp + 0xA8); // 找到调试节 10 pTemp = pBuffer + (DWORD)*pv; // 计算调试节指定的内存地址 11 pv = (PVOID *)(pTemp + 4 * 5); // 找到偏移 12 pTemp = pBuffer + (DWORD)*pv; // 找到 UUID 基址 13 if (!(pTemp[0] == 'R' && pTemp[1] == 'S' && pTemp[2] == 'D' && pTemp[3] == 'S')) 14 { 15 return NULL; 16 } 17 GUID tGuid = { 0 }; 18 memcpy_s(&tGuid, sizeof(tGuid), pTemp + 4, 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就好了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」