2

PE と COFF の仕様、Matt Pietrek の「Peering Inside the PE: A Tour of the Win32 Portable Executable File Format」「An In-Depth Look into the Win32 Portable Executable File Format」、およびこの件に関する他のいくつかのソースを読みました。 .
MinGW GCC 4.7 によって生成されたオブジェクト ファイルから、COFF セクション テーブルと COFF シンボル テーブルを読み取ることができました (デバッグ モードでスタティック ライブラリをコンパイルしていました)。
最終的な目標は、特定のオブジェクト ファイル (COFF) で定義されているすべての関数にアクセスし、それらのマシン コードを構成するすべてのバイトを読み取ることです。

質問 1 : COFF ファイル内の単一関数の開始アドレスを計算するにはどうすればよいですか? 「SectionNumber」で指定されたセクションへのオフセットとして、シンボル レコードの「Value」フィールドを使用する必要があると思います。

質問 2 : 特定の関数の長さ (読み取る必要があるバイト数) を調べるにはどうすればよいですか?

質問 3 : Microsoft の PE & COFF 仕様によると、関数を定義する各シンボル レコードの後に​​、補助シンボル テーブル レコードが必要です。3 つの定義済み関数のオブジェクト ファイル (デバッグ モードでコンパイルされた .a ファイルから抽出) で、そのような補助レコードが 1 つしかないのはなぜですか? そして、それもゼロで完全に埋められていますか?

4

1 に答える 1

1

Q1: はい、それは妥当だと思います。

Q2: おそらく難しいでしょう。プロセッサのアーキテクチャに依存します。関数の長さを示す関数情報が存在するという保証はまったくありません。特に、x86 (32 ビット) で利用できるものはないようで、長さに関する情報は他のアーキテクチャで利用できる場合があります。 [例外後の巻き戻しに必要な場合]。

おそらく最良の方法は、シンボル テーブルをロードし、アドレス順で NEXT 関数がどこにあるかを見つけ、その長さが関数の先頭から次の関数の直前のバイトまでであると想定することです。最後の機能については、明らかに「セクションの終わりまで」です。何年も前に、関数の長さを見つけるために return 命令を認識する方法を使用しましたが、最近のコンパイラは複数の return 命令を持つコードを生成することが多く、リターンの後に if/else コードを置き、メインの関数コードにジャンプします。など、信頼できる方法ではないかもしれません[もちろん、誰かがそうする場合x = $0xc3;、0xc3はリターン命令のように見えますが、実際にはデータです... ;)

Q3: 補助レコードは完全にオプションです:

各標準シンボル テーブル レコードの直後に、0 個以上の補助シンボル テーブル レコードが続きます。ただし、通常、標準のシンボル テーブル レコードの後に​​複数の補助シンボル テーブル レコードが続くことはありません (長いファイル名を持つ .file レコードを除く)。

補助シンボル テーブル レコードがある場合は、シンボル テーブル レコードのオフセット 17 に示されます。

後のテキストだけを読むと、これは混乱する可能性があります。

補助シンボル テーブル レコードは常に、いくつかの標準シンボル テーブル レコードに続き、それに適用されます。

これは「補助記号表レコードがあれば、標準表レコードの直後」と考えるべきだと思います。

于 2014-09-14T16:42:12.323 に答える