Delphiプログラムまたはコンパイラが生成したデバッグ情報からローカル変数情報(アドレスとタイプ)をどのように抽出しますか?


105

私の目標は:

  • Delphiでコンパイルされた32ビットまたは64ビットのWindowsプログラムで中断されたスレッドを指定して、スタックをウォークする(実行可能)
  • スタックエントリを指定して、各メソッドのローカル変数とその値を列挙します。つまり、少なくとも、それらのアドレスとタイプ(integer32 / 64 / signed / unsigned、string、float、record、class ...)を見つけ、それらの組み合わせを使用して値を見つけることができます。

1つ目は問題ありませんが、この質問に関する2つ目です。高レベルで、Delphiのスタックエントリを指定してローカル変数をどのように列挙しますか?


低レベルでは、これは私が調査してきたものです:

RTTI:メソッドに関するこの種の情報はリストしません。これは、私が実際に現実的な選択肢であると思ったものではありませんでしたが、とにかくここにリストします。

デバッグ情報:デバッグビルド用に生成されたデバッグ情報をロードします。

  • マップファイル:詳細なマップファイル(テキスト形式のファイルです。ファイルを開いて確認してください)にも、ローカル変数情報は含まれていません。基本的には、アドレスとソースファイルの行番号のリストです。アドレスとファイルの行の関連付けに最適です。たとえば、樋の青いドットです。より詳細な情報には不向き
  • リモートデバッグ情報(RSMファイル)- その内容や形式に関する既知の情報はありません
  • TD32 / TDSファイル:現在の研究内容。それらは他の多くの情報の中でグローバルとローカルのシンボルを含んでいます。

ここで遭遇する問題は次のとおりです。

  • TD32ファイル形式のドキュメントはありません(見つけられます)。
  • それらに関する私の知識のほとんどは、それらを使用するJedi JCLコード(JclTD32.pas)からのものであり、そのコードの使用方法や、ローカル変数を表示するのに十分な構造があるかどうかはわかりません。私はそれがグローバルシンボルを処理することを確信していますが、ローカルについては非常に不確かです。多種多様な定数が定義されており、形式に関するドキュメントはありません。それらが何を意味するかを読むために、私は推測しておきます。ただし、これらの定数とその名前はどこかに由来している必要があります。
  • TDS情報を使用して見つけることができるソースは、ローカルシンボルをロードまたは処理しません。

これが正しいアプローチである場合、この質問は「TDS / TD32ファイル形式のドキュメントはありますか?ローカル変数をロードするコードサンプルはありますか?」

コードサンプルは必須ではありませんが、最小限の場合でも非常に便利です。


2
私は実際にJedi JCLユニットを使用してTD32情報にアクセスしていません-そのための独自のライブラリがありますが、JclTD32.pasに必要な基本的な配管はすべてあるようです。ただし、変数情報にアクセスするためのデモコードはありませんが、そこにあるサンプル(.. \ jcl \ examples \ windows \ debug \ sourcelocにあります)は、TD32データから行番号情報を取得する方法を示しているため、あなたはそれを基にして必要なものを手に入れることができるはずです。見つけた情報をここに報告してください:)
内部サーバーエラー

2
@ 500-InternalServerErrorありがとう。行番号の情報は簡単です(マップファイルにも含まれています)。ただし、ローカルシンボルに特に関連するJCLコードの情報を提供できますか?また、好奇心から、あなたのTD32独自のライブラリは何ですか?それは公開/公的に使用可能ですか、それとも社内でのみですか?
デビッド

3
その下の各プロシージャ/関数/メソッドシンボルには、そのローカルなシンボルのリストが含まれています。ほとんどの定義はジェダイのユニットにあるように見えますが、一部はコメントアウトされています。私の提案は、小さなテストアプリを作成し、シンボルの列挙が返す結果を確認することです。私が持っているコードは独自のものであり、私が公開するものではありません。とにかく、それはローカル変数のトピックをカバーしていません。しかし、それが基づいている情報は半ば公開されているので、特定の壁にぶつかった場合、私は手助けできるかもしれません。
500-

4
tds2pdb(code.google.com/p/map2dbg)には、tdsファイルのパーサーがあるようです。C#コードですが。
Graymatter

4
以前は非公式のドキュメントがありましたが、当時ボーランドは(当時)デバッグ情報にアクセスする代わりにDLLをリリースして、内部形式を変更してドキュメントを更新する必要がないようにすることを決定していました。残念ながら、現在のところ元のドキュメントもdllも見つかりません。Embarcaderoのテクニカルサポートに連絡して、質問することをお勧めします。
500-

回答:


2

バイナリにないデバッグシンボルがないか確認します。また、GDBを使用することもできます(Windowsでの移植)。.dbgファイルまたは.dSYMファイルが見つかったら、すばらしいでしょう。それらはソースコードを含んでいます。

gdb> list foo
56 void foo()
57 {
58  bar();
59  sighandler_t fnc = signal(SIGHUP, SIG_IGN);
60  raise(SIGHUP);
61  signal(SIGHUP, fnc);
62  baz(fnc);
63 }

デバッグファイルがない場合は、MinGWまたはCygwinを取得して、nm(1)を使用してみてくださいmanページ)。バイナリからシンボル名を読み取ります。C ++のようないくつかの型が含まれる場合があります。

int abc::def::Ghi::jkl(const std::string, int, const void*)

--demangleオプションを追加することを忘れないでください。そうしないと、次のようなものが得られます。

__ZN11MRasterFont21getRasterForCharacterEh

の代わりに:

MRasterFont::getRasterForCharacter(unsigned char)

2
ジャクブ、答えてくれてありがとう。残念ながら、おそらく特定のデバッグ形式-TDSを読む必要があります。Delphiアプリは、WindowsのGDB互換デバッグ情報でコンパイルされていません。nmがどのように役立つかわかりません。Delphiが生成するものではない特定のデバッグファイル形式に依存するためです。または、私はあなたの答えを誤解しました-たとえば、GDBはDelphiのシンボルを読み取ることができますか?
デビッド

@DavidM、あなたのコメントは非常に重要です。WindowsでGNU BinutilsまたはGNUデバッガのポートを探してみてください(私はBinutilsポートしか知りません)。GDB用のBFDライブラリがあります。Binutilsでも使用されています。複数のファイル形式を読み取って、マジックナンバーで認識することができます。すべてが失敗した場合は、というツールを使用しますstrings。バイナリファイルから文字列を抽出します。manページを参照してください。これは役立つかもしれないが必要ではない文字列を
出力し

0

見てみましょうhttp://download.xskernel.org/docs/file%20formats/omf/borland.txtオープンアーキテクチャハンドブック。それは古いですが、ファイル形式に関するいくつかの関連情報を見つけるかもしれません。


コンテキストを追加してください。リンクが将来壊れる可能性があります。
ヒンタム

リンクには、Borlandコンパイラが使用するOMFファイル形式とBorlandが使用するその他のバイナリファイル形式に関するBorlandの公式ドキュメントが含まれています。数年前、TDSファイル形式を確認しましたが、文書化されたファイル形式と互換性のある部分があるようです。TDSファイルからローカル変数に関する情報を収集する場合は、リンクされたドキュメントを使用または参照する必要があります。リンクが壊れると、私の答えは役に立たなくなり、必要な情報が失われます。リンクされた「Open Architecture Handbook」は、古いTurbo PascalおよびCリリースの一部でした。
Muetze1
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.