33

私たちの夜間のビルド プロセスは、対応する画像ファイルとは数時間異なる PDB ファイルを生成するなど、長い間機能していませんでした。その後、問題を修正しました。

ただし、シンボル サーバーの使用を開始したいのですが、これらの年齢が一致しない pdb ファイルを使用する必要があるため、使用できません。この問題を回避するには、windbg で .symopt +0x40 メソッドを使用します。つまり、すべての pdb ファイルを手作業で整理する必要があり、何年にもわたるリリースの後、それが積み重なっていきます。

windbg が pdb の経過時間をマークするために使用するメカニズムを変更し、強制的にイメージ ファイルと一致させる方法を探しています。ユーティリティChkMatchは同様のことを行いますが、pdb 署名用です。開発者はページで「ChkMatch は、実行可能ファイルと PDB ファイルの署名が異なるが同じ年齢である場合、それらを一致させることができます (PDB 署名と年齢の詳細については、この記事を参照してください)。年齢が異なる場合、ツールは作成できません。ファイルが一致します。」

hexeditor の内部を調べたところ、年齢に対応するビットのように見えるものさえ見つかりましたが、動作させることができなかったので、内部でさらにいくつかのトリックを引き出す必要があります。

何か案は?

編集:これが役立つかどうかはわかりませんが、私の特定のケースでは、PDBファイルも再作成する不要なdllの再リンクによって年齢差が発生しました。ただし、ビルド プロセスでは、元の dll (再リンク前) と再リンク後の pdb が格納されていました。そういう状況をどうにか手で再現しようと思いました。つまり、DLL の再リンクを強制しますが、どちらの場合も pdb を保存します。次に、2 つのファイルのバイナリ比較を実行して、それらがどのように変更されたかを確認できます。おそらく、これを自動的に行う何らかのパッチソフトウェアを実行しますか? コントロール ケースで正確に何が変更されたかを確認することで、会社のビルド プロセスで保存された DLL と PDB に同じことを行うことができるでしょうか?

編集:私はそれを理解しました!!!! 最初の回答に対するコメントの 1 つを参考に、「文書化されていない Windows 2000 の秘密: プログラマーズ クックブック」という書籍の PDF へのリンクを調べました。また、著者は pdb ファイル形式について詳しく説明しています。前に言ったように、私はすでに pdb を 16 進エディタにロードしており、年齢と署名を一致させたように見えるようにいくつかのビットをひっくり返しましたが、うまくいきませんでした。さて、W2k secrets book のユーティリティを使用して pdb を含まれているストリームに「爆発」させた後、ストリーム 3 に age への別の参照が隠されていることがわかりました!!!!!!!! それもひっくり返したら、windbgで一致しました。これは巨大です!!!! どうもありがとう....シンボル サーバー HERE I COME!

4

4 に答える 4

12

または、ここでの提案を使用して、windbgに不一致の署名と年齢を無視させることもできます。

http://www.debuginfo.com/articles/debuginfomatch.html

...デフォルトでは、[windbg]は一致しないデバッグ情報をロードすることもできませんが、.symoptデバッガコマンドはデフォルトの動作を変更できます。「.symopt+0x40」コマンドを発行した後、デバッガーは一致しないPDBファイルとDBGファイルを適切に受け入れてロードします。

お役に立てれば。

于 2011-12-07T21:05:34.607 に答える
12

windbgはpdbの経過時間を変更しません-実行可能ファイルの経過時間と一致するように検索するだけです-コンパイラは実行可能ファイルとデバッグファイルを(再)生成するときに変更します。

現在、debuginfo.comの記事に基づいて、適切なデバッグディレクトリ(コードビュータイプ)に到達し、それをPDB7署名と照合し、実行可能ファイル内の年齢またはGUIDを変更することはそれほど難しくありません。なぜそれはオプションではないのですか?

代わりにpdbを更新したいですか?恐れ入りますが、pdbは独自のフォーマットです。複数の読み取り専用API(dbghelp.dllとdia sdk)がありますが、変更に関しては、変更できるように詳細を推測する必要があります。

于 2009-04-14T10:05:53.293 に答える
5

SamBが言ったように、PDB(フォーマット7、私のテストはVS2010で生成された.exeと.pdb、およびwindbg 6.9.0003.113 X86に基づいています)では、年齢への追加の参照が1つあるため、PDBファイルで変更する年齢は合計で3つあります. 残念ながら、SamB は魔法の 3rd エイジ、ストリーム 3 を見つける方法を教えてくれませんでしたか? いいえ!私のテストによると、100 以上の pdb ストリームを抽出し、02 (SamB のインデックスが 0 の場合) と 03 を試しましたが、どちらも年齢を見つけることができません。

16 進エディタと windbg があれば、他の 2 つの age を修正するのは簡単です。

  • GUID と年齢を調べる

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
  • 2 つの簡単な年齢を修正する

GUID: 8BDC5152B6E0 の最後の部分を検索します。最後の部分のみがビッグ エンディアン/リトルエンディアンの問題からバイト オーダー フリーであるため、pdb ファイルとまったく同じです。生の 16 進数値として検索するように注意してください。より正確にするために、GUID の他の値 (X86 ではバイト順を逆にする必要があります) が正確に一致することを確認する必要があります。PDB ファイル内には正確に 2 つの GUID があり、付随する age は GUID の最初のバイトの直前にあります。修正してください。それでおしまい!

  • 3歳を見つけるための私の野蛮な方法。

    PDB ファイルの 16 進数を 1 行に 1 バイト (2 つの 16 進数) ダンプします。od -v -t x1 あなたの.pdb | sed 's/^[0-9a-f]* //;s/ /\n/g' > age_offset.txt

    一致したすべての年齢の行番号を取得します。私の場合、値が 88 01 00 00 の 4 つの連続した行です。 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

    ファイルを保存します

    これで、すべての行にオフセットを表す 10 進数が含まれるテキスト ファイルが得られます。このオフセットから、次の 4 バイトが夢の年齢の候補となります。

    次に、可能性のあるすべての年齢を変更してから、一致するまで symchk でチェックしようとしています。毎回 1 つのオフセットのみにパッチが適用されます。

    まず、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

幸運なことに、38 番目のオフセットで適切な場所を見つけました。

パッチを適用する正しいオフセットを試行錯誤する最速の方法ではありませんが、私にとってはうまくいきます。修正する余分な年齢が1つだけであることを確認するのが私のプロトタイプです。したがって、試行錯誤の方法は実用的ではありません。

同じ仕事をより速く行うためのユーティリティを書くのはとても簡単だと思います。

ところで:私のテストによると。chkmatch は一致を報告する可能性がありますが、symchk と windbg は一致していないと見なします。

windbg コマンド !itoldyouso は一致しますが、.reload /f your_module.exe はまだ一致しません。

3 つの age が修正されると、windbg だけでなく、Visual Studio も pdb ファイルを読み込めるようになります。

于 2012-09-03T11:28:55.400 に答える