windows 如何将年龄不匹配的 PDB 更改为正确匹配?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/744870/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can you change an age-mismatched PDB to match properly?
提问by pj4533
Our nightly build process was broken for a long time, such that it generated PDB files that were a few hours different in age than the corresponding image files. I have since fixed the problem.
我们的夜间构建过程被破坏了很长时间,因此它生成的 PDB 文件与相应的图像文件的时间相差几个小时。我已经解决了这个问题。
However, I would like to start using a symbol server, but cannot due to having to use these age-mismatched pdb files. I work around this issue by using the .symopt +0x40 method in windbg. That means I have to organize all my pdb files by hand, and after years upon years of releases, that adds up.
但是,我想开始使用符号服务器,但由于必须使用这些年龄不匹配的 pdb 文件而无法使用。我通过在 windbg 中使用 .symopt +0x40 方法解决了这个问题。这意味着我必须手动组织我所有的 pdb 文件,并且经过多年的发布,这加起来了。
I am looking for a way to modify the mechanism that windbg uses to mark a pdb's age, and force it to match my image file. The utility ChkMatchdoes something similar, but for pdb signatures. The developer states on the page "ChkMatch is capable of making an executable and PDB file match if they have different signatures but the same age (see this article for more information about PDB signature and age). If the age differs, the tool cannot make the files match."
我正在寻找一种方法来修改windbg 用来标记pdb 年龄的机制,并强制它与我的图像文件匹配。实用程序ChkMatch执行类似的操作,但用于 pdb 签名。开发人员在页面上声明“ChkMatch 能够使可执行文件和 PDB 文件匹配,如果它们具有不同的签名但相同的年龄(有关 PDB 签名和年龄的更多信息,请参阅此文章)。如果年龄不同,该工具无法使文件匹配。”
I took a look inside a hexeditor, and even found what looked like the bits corresponding to the age, but it must pull some more tricks internally, cause I couldn't get it to work.
我查看了一个十六进制编辑器的内部,甚至找到了与年龄对应的位,但它必须在内部拉一些更多的技巧,因为我无法让它工作。
Any ideas?
有任何想法吗?
EDIT: I don't know if this helps, but in my particular case the age difference was caused by unnecessarily relinking dll's, which would recreate the PDB files as well. However, our build process was storing the original dlls (before the relink), and the pdb after the relink. I thought about somehow recreating such a situation by hand. Meaning, forcing a relink on a DLL, but saving off the pdb in both cases. Then I could do a binary compare of the two files to see how they changed. Perhaps run some sort of patching software that does this automatically? By seeing what exactly changed in my control case, perhaps I could do the same to the DLLs and PDBs saved in my companies build process?
编辑:我不知道这是否有帮助,但在我的特殊情况下,年龄差异是由不必要的重新链接 dll 引起的,这也会重新创建 PDB 文件。但是,我们的构建过程存储了原始 dll(重新链接之前)和重新链接之后的 pdb。我想以某种方式手工重现这种情况。意思是,强制重新链接 DLL,但在两种情况下都保存了 pdb。然后我可以对这两个文件进行二进制比较,看看它们是如何变化的。也许运行某种自动执行此操作的修补软件?通过查看我的控制案例中究竟发生了什么变化,也许我可以对保存在我公司构建过程中的 DLL 和 PDB 做同样的事情?
EDIT: I FIGURED IT OUT!!!! Thanks to one of the comments on the first answer, I checked out a link to the pdfs of the book "Undocumented Windows 2000 Secrets: A Programmers Cookbook". And the author goes into great detail about the pdb file format. As I said before, I had already loaded the pdb into a hex editor and flipped some bits around appearing that I made the age/signature match, but it didn't work. Well, after using the utility from the W2k secrets book to "explode" the pdb into the included streams, I found out that they hide another reference to the age in stream 3!!!!!!! Once I flipped that one as well, it matched up in windbg. THIS IS HUGE!!!! Thank you so much....symbol server HERE I COME!
编辑:我想通了!!!!由于对第一个答案的评论之一,我查看了“未记录的 Windows 2000 秘密:程序员手册”一书的 pdf 文件的链接。作者详细介绍了 pdb 文件格式。正如我之前所说,我已经将 pdb 加载到十六进制编辑器中并翻转了一些看起来我进行了年龄/签名匹配的位,但它没有用。好吧,在使用 W2k secrets book 中的实用程序将 pdb“分解”到包含的流中后,我发现它们在流 3 中隐藏了对年龄的另一个引用!!!!!!!!!一旦我也翻转了那个,它在windbg中匹配。这太棒了!!!!非常感谢....符号服务器我来了!
采纳答案by deemok
the windbg will not modify pdb's age - it only looks it up to match that of executable - the compiler does when it (re)generates executable and debug files.
windbg 不会修改 pdb 的年龄 - 它只会查找它以匹配可执行文件的年龄 - 编译器在(重新)生成可执行文件和调试文件时会这样做。
now, based on the debuginfo.com article, it is not too difficult to arrive at the proper debug directory (of type codeview), match it against PDB7 signature and make modifications to either age or GUID inside an executable. why is that not an option?
现在,根据 debuginfo.com 文章,找到正确的调试目录(codeview 类型),将其与 PDB7 签名进行匹配并修改可执行文件中的年龄或 GUID 并不困难。为什么这不是一个选择?
i guess, you want to update pdb instead? i'm afraid, pdb is a proprietary format. there're multiple read-only APIs (dbghelp.dll and dia sdk), but as far as modifications go, you need to guess the details to be able to modify.
我想,您想改为更新 pdb 吗?恐怕,pdb 是一种专有格式。有多个只读 API(dbghelp.dll 和 dia sdk),但就修改而言,您需要猜测细节才能修改。
回答by Richard Myers
Or you could just use the suggestion here to have windbg ignore mismatched signatures and age:
或者你可以使用这里的建议让windbg忽略不匹配的签名和年龄:
http://www.debuginfo.com/articles/debuginfomatch.html
http://www.debuginfo.com/articles/debuginfomatch.html
... While by default it [windbg] also does not allow to load unmatched debug information, .symopt debugger command can change the default behaviour. After we have issued “.symopt+0x40” command, the debugger will happily accept and load unmatched PDB and DBG files.
...虽然默认情况下 [windbg] 也不允许加载不匹配的调试信息,.symopt debugger 命令可以更改默认行为。在我们发出“.symopt+0x40”命令后,调试器将愉快地接受并加载不匹配的 PDB 和 DBG 文件。
Hope this helps.
希望这可以帮助。
回答by zhaorufei
Although as SamB said, in PDB(format 7, my test is based on VS2010 generated .exe and .pdb, and windbg 6.9.0003.113 X86) there's one extra reference to age, so totally there will be 3 ages to modify in PDB file. Unfortunately, SamB did not told us how to find the magic 3rd age, the stream 3? no! according to my test, I extract more than 100 pdb streams, I tried 02(if SamB is 0-indexed) and 03, both cannot find the age.
虽然正如 SamB 所说,在 PDB(格式 7,我的测试基于 VS2010 生成的 .exe 和 .pdb,以及 windbg 6.9.0003.113 X86)有一个额外的年龄参考,所以在 PDB 文件中总共会有 3 个年龄要修改. 不幸的是,SamB 没有告诉我们如何找到魔法第三纪,流 3?不!根据我的测试,我提取了 100 多个 pdb 流,我尝试了 02(如果 SamB 是 0 索引)和 03,都找不到年龄。
Fixing the other 2 ages is easy, as soon as you have a hex editor and windbg.
只要您拥有十六进制编辑器和 windbg,就可以轻松修复其他 2 个年龄。
- Find the GUID and age
- 查找 GUID 和年龄
using symchk to get the Signature(a GUID) of the your mismatched PDB file: symchk your.exe /v /s .
使用 symchk 获取不匹配的 PDB 文件的签名(GUID): symchk your.exe /v /s 。
The typically output will contains:
通常的输出将包含:
[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
- Fix the 2 easier ages
- 修复 2 个更容易的年龄
Search the last part of the of the GUID: 8BDC5152B6E0, because only the last part is byte-order-free from big-endian/little-endian issue, it's just exactly same as in pdb files. Be careful to search as raw hex value, to make it more accurate, you should verify the other values in the GUID(need to rever byte-order in X86)exactly matches. There will be exactly 2 GUIDs found inside the PDB file, the accompanying age is just before the first byte of the GUID. Modify it. That's it!
搜索 GUID 的最后一部分:8BDC5152B6E0,因为只有最后一部分是从 big-endian/little-endian 问题中无字节顺序的,它与 pdb 文件中的完全相同。小心搜索原始十六进制值,以使其更准确,您应该验证 GUID 中的其他值(需要在 X86 中反转字节顺序)完全匹配。在 PDB 文件中将恰好有 2 个 GUID,伴随的年龄正好在 GUID 的第一个字节之前。修改它。就是这样!
my brute way to find out the 3rd age.
dump the hex number of your PDB file, one byte(2 hex numbers) per line. od -v -t x1 your.pdb | sed 's/^[0-9a-f]* //;s/ /\n/g' > age_offset.txt
get the line number of every matched age, in my case it's 4 consecutive lines which has value 88 01 00 00, vim age_offset.txt :g/88\n01\n00\n00/s/^/\= (line('.') . ':')/
This is a ex mode command, which should be support by a recent version of vim.
:v/:/d
This will delete all lines which does not contains ':', the remained lines are line numbers which is the offset of every matched age.
:%s/:.*//
This will trim :88 and leaving the offset alone.
:%s/.*/\=(submatch(0) - 1)/
This command substract every number by 1, I do this because the line number in vim is 1-index, and the byte offset of every age should be 0-index to make the co-worker utility happy.
:w
save the file
Now we get a text file with every line contains a decimal number representing an offset, from this offset, the following 4 bytes is candidate for your dreaming age.
Next I'm trying to modify every potential age and then try to check it by symchk until it matches, every time only one offset will be patched.
First of all, I will backup a PDB with the 2 ages(and GUID) be modified. Let's called it ori.pdb
Here's the batch script to do the hard work:
我找出第三个时代的粗暴方法。
转储 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
这是完成艰苦工作的批处理脚本:
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
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
Good lucky, I found the right place at 38th offset.
幸运的是,我在第 38 个偏移处找到了正确的位置。
It's not the fastest way to try-error out the correct offset to patch, but it works for me, it's my prototype to make sure there's only 1 extra age to fix, otherwise, the possible combination is huge(I've 111 age candidate to try) and thus a try-error way is not pragmatic.
这不是尝试错误修补正确偏移的最快方法,但它对我有用,这是我的原型,以确保只有 1 个额外的年龄需要修复,否则,可能的组合是巨大的(我有 111 岁的候选人尝试),因此尝试错误的方式是不实用的。
I think it's very easy to write an utility to do the same job in a faster way.
我认为编写一个实用程序以更快的方式完成相同的工作非常容易。
BTW: according to my test. chkmatch may report match while symchk and windbg vs think it mismatch.
BTW:根据我的测试。chkmatch 可能会报告匹配,而 symchk 和 windbg vs 认为它不匹配。
windbg command !itoldyouso match while .reload /f your_module.exe still cannot match.
windbg 命令 !itoldyouso 匹配,而 .reload /f your_module.exe 仍然无法匹配。
After the 3 ages being fixed, not only windbg but also visual studio can load the pdb files.
3个时代修复后,不仅windbg,visual studio也可以加载pdb文件。