pj4*_*533 29 windows symbols windbg symbol-server pdb-files
我们的夜间构建过程已经被打破了很长时间,因此它生成的PDB文件的年龄与相应的图像文件相差几个小时.我已经解决了这个问题.
但是,我想开始使用符号服务器,但不能因为必须使用这些年龄不匹配的pdb文件.我通过在windbg中使用.symopt + 0x40方法解决此问题.这意味着我必须手工组织我的所有pdb文件,经过多年的发布后,这就相加了.
我正在寻找一种方法来修改windbg用于标记pdb年龄的机制,并强制它匹配我的图像文件.实用程序ChkMatch执行类似的操作,但是对于pdb签名.开发人员在页面上声明"ChkMatch能够使可执行文件和PDB文件匹配,如果他们有不同的签名但年龄相同(有关PDB签名和年龄的更多信息,请参阅此文章).如果年龄不同,该工具无法生成文件匹配."
我看了一下hexeditor,甚至找到了与年龄相对应的东西,但它必须在内部拉出一些技巧,因为我无法让它工作.
有任何想法吗?
编辑:我不知道这是否有帮助,但在我的特殊情况下,年龄差异是由于不必要地重新连接dll引起的,这也会重新创建PDB文件.但是,我们的构建过程是存储原始dll(在重新链接之前),以及重新链接之后的pdb.我想过以某种方式手工重建这种情况.意思是,强制重新链接DLL,但在两种情况下都保存了pdb.然后我可以对这两个文件进行二进制比较,看看它们是如何变化的.也许运行某种自动执行此操作的修补软件?通过查看我的控制案例中究竟发生了哪些变化,或许我可以对我公司构建过程中保存的DLL和PDB做同样的事情?
编辑:我想出来!!!! 感谢第一个答案的评论之一,我查看了"未记载的Windows 2000 Secrets:A Programmers Cookbook"一书的pdf链接.作者详细介绍了pdb文件格式.正如我之前所说的那样,我已经将pdb加载到十六进制编辑器中,然后翻出一些看起来我的年龄/签名匹配,但它没有用.好吧,在使用W2k秘密书中的实用程序将pdb"爆炸"到包含的流中之后,我发现它们隐藏了对流3中年龄的另一个引用!!!!!!! 一旦我翻过那个,它在windbg中匹配.这太棒了!!!! 非常感谢....这里的符号服务器我来了!
dee*_*mok 10
windbg不会修改pdb的年龄 - 它只查找匹配可执行文件的时间 - 编译器在(重新)生成可执行文件和调试文件时执行的操作.
现在,基于debuginfo.com文章,到达正确的调试目录(类型为codeview)并将其与PDB7签名匹配并对可执行文件中的age或GUID进行修改并不困难.为什么这不是一个选择?
我想,你想更新pdb吗?我担心,pdb是一种专有格式.有多个只读API(dbghelp.dll和dia sdk),但就修改而言,你需要猜测能够修改的细节.
小智 8
或者你可以使用这里的建议让windbg忽略不匹配的签名和年龄:
http://www.debuginfo.com/articles/debuginfomatch.html
...虽然默认情况下[windbg]也不允许加载不匹配的调试信息,.symopt debugger命令可以更改默认行为.在我们发出".symopt + 0x40"命令后,调试器将很乐意接受并加载不匹配的PDB和DBG文件.
希望这可以帮助.
虽然正如 SamB 所说,在 PDB(格式 7,我的测试基于 VS2010 生成的 .exe 和 .pdb,以及 windbg 6.9.0003.113 X86)有一个额外的年龄参考,所以在 PDB 文件中总共会有 3 个年龄要修改. 不幸的是,SamB 没有告诉我们如何找到魔法第三纪,流 3?不!根据我的测试,我提取了100多个pdb流,我尝试了02(如果SamB是0索引)和03,都找不到年龄。
只要您拥有十六进制编辑器和 windbg,就可以轻松修复其他 2 个年龄。
使用 symchk 获取不匹配的 PDB 文件的签名(GUID): symchk your.exe /v /s 。
通常的输出将包含:
[SYMCHK] ------------------------------------
SymbolCheckVersion 0x00000002
Result 0x00010001
DbgFilename CPP_Snippet.dbg
DbgTimeDateStamp 0x00000000
DbgSizeOfImage 0x00000000
DbgChecksum 0x00000000
PdbFilename E:\zrf\C_CPP\CPP_Snippet.pdb
PdbSignature {6D8D99B0-E96B-4093-9D97-8BDC5152B6E0}
PdbDbiAge 0x00000188
Run Code Online (Sandbox Code Playgroud)
搜索 GUID 的最后一部分:8BDC5152B6E0,因为只有最后一部分是从 big-endian/little-endian 问题中无字节顺序的,它与 pdb 文件中的完全相同。小心搜索原始十六进制值,以使其更准确,您应该验证 GUID 中的其他值(需要在 X86 中反转字节顺序)完全匹配。在 PDB 文件中将恰好有 2 个 GUID,伴随的年龄正好在 GUID 的第一个字节之前。修改它。就是这样!
我找出第三个时代的粗暴方法。
转储 PDB 文件的十六进制数,每行一个字节(2 个十六进制数)。od -v -t x1 your.pdb | sed 's/^[0-9a-f]* //;s/ /\n/g' > age_offset.txt
获取每个匹配年龄的行号,在我的情况下,它是 4 个连续的行,其值为 88 01 00 00,vim age_offset.txt :g/88\n01\n00\n00/s/^/\= (line('. ') . ':')/
这是一个 ex 模式命令,最近版本的 vim 应该支持它。
:v/:/d
这将删除所有不包含 ':' 的行,剩余的行是行号,即每个匹配年龄的偏移量。
:%s/:.*//
这将修剪 :88 并单独保留偏移量。
:%s/.*/\=(子匹配(0) - 1)/
这个命令将每个数字减1,我这样做是因为vim中的行号是1-index,并且每个age的字节偏移量应该是0-index,以使同事实用程序满意。
:w
保存文件
现在我们得到一个文本文件,每行包含一个代表偏移量的十进制数,从这个偏移量中,接下来的 4 个字节是你梦想中的年龄的候选者。
接下来,我尝试修改每个潜在的年龄,然后尝试通过 symchk 检查它,直到匹配为止,每次只修补一个偏移量。
首先,我将备份一个修改了 2 个年龄(和 GUID)的 PDB。我们称之为ori.pdb
这是完成艰苦工作的批处理脚本:
Run Code Online (Sandbox Code Playgroud)for /F usebackq %%i in (`type age_offset.txt`) DO ( copy /y ori.pdb CPP_Snippet.pdb @rem dd if=ori.pdb bs=1c count=4 skip=%%i | xxd -g1 | grep "88 01 00 00" || echo "Bad data at %%i" && goto exit dd if=pdb_age.dat of=CPP_Snippet.pdb bs=1c count=4 seek=%%i conv=notrunc symchk CPP_Snippet.exe /s . && echo "Found it at offset %%i" && goto exit ) :exit
幸运的是,我在第 38 个偏移处找到了正确的位置。
这不是尝试错误修补正确偏移的最快方法,但它对我有用,这是我的原型,以确保只有 1 个额外的年龄需要修复,否则,可能的组合是巨大的(我有 111 岁的候选人尝试),因此尝试错误的方式是不实用的。
我认为编写一个实用程序以更快的方式完成相同的工作非常容易。
BTW:根据我的测试。chkmatch 可能会报告匹配,而 symchk 和 windbg vs 认为它不匹配。
windbg 命令 !itoldyouso 匹配,而 .reload /f your_module.exe 仍然无法匹配。
3个时代修复后,不仅windbg,visual studio也可以加载pdb文件。
| 归档时间: |
|
| 查看次数: |
18002 次 |
| 最近记录: |