なぜGDBは実行可能ファイルとコアダンプを必要とするのですか?


11

私はコアダンプを使用してデバッグしています。gdbでは、コアダンプだけでなく実行可能ファイルも指定する必要があることに注意してください。どうしてこれなの?コアダンプにプロセスが使用するすべてのメモリが含まれている場合、実行可能ファイルはコアダンプに含まれていませんか?おそらく、exe全体がメモリに読み込まれる保証はありません(個々の実行可能ファイルは通常それほど大きくありません)。あるいは、コアダンプに関連するすべてのメモリが含まれていないのでしょうか。シンボル用ですか(おそらく、通常はメモリに読み込まれていません)?


1
gdbのドキュメントに記載されているように、実行ファイルにはシンボル情報が含まれています...
Thomas Dickey

1
驚いたことに、DWARF形式について言及した回答はありません(追加したものを除く)
Basile Starynkevitch '27

回答:


15

コアダンプは、プログラムのメモリフットプリントのダンプです。すべてがどこにあるかがわかっている場合は、それを使用できます。

実行可能ファイルを使用するのは、それがメモリ内の(論理アドレスに関して)どこにあるかを説明するためです。つまり、コアファイルです。

コマンドを使用すると、objdump調査中の実行可能オブジェクトに関するメタデータがダンプされます。例としてa.outという名前の実行可能オブジェクトを使用します。

objdump -h a.outヘッダー情報のみをダンプします。たとえば、という名前のセクションが表示されます。.dataまたは.bssまたは.text(もっとたくさんあります)。これらは、カーネルローダーに、オブジェクト内のさまざまなセクションのある場所とプロセスアドレス空間のどこにセクションをロードする必要があるか、一部のセクション(.data .textなど)には何をロードするかを通知します。(.bssセクションにはファイル内のデータは含まれていませんが、初期化されていないデータ用にプロセスで予約するメモリの量を指し、ゼロで埋められています)。

実行可能オブジェクトファイルのレイアウトは、標準のELFに準拠しています。

objdump -x a.out -すべてをダンプします

実行可能なオブジェクトがまだ(それが除去されていない-そのシンボルテーブルが含まれている場合はman strip、あなたが使用-gするデバッグ世代を生成するために、gcc 交流電源のコンパイルと仮定して)あなたは、変数/バッファを持っていた場合は、シンボル名により、例えばコアの内容を調べることができますソースコードでinputLineという名前を付けると、その名前を使用gdbしてコンテンツを確認できます。つまりgdbinputLineが開始するプログラム初期化データセグメントの開始からのオフセットとその変数の長さがわかります。

Article1Article 2、さらに重要な実行可能リンク形式(ELF)仕様についてさらに読むには。


以下の@mirabilosコメントの後に更新してください。

しかし、シンボルテーブルを次のように使用すると、

$ gdb --batch -s a.out -c core -q -ex "x buf1"

生産する

 0x601060 <buf1>:    0x72617453

そして、シンボルテーブルを使用せずに直接アドレスを調べます、

$ gdb --batch -c core -q -ex "x 0x601060"

生産する

0x601060:   0x72617453

2番目のコマンドでシンボルテーブルを使用せずにメモリを直接調べました。


また、@ user580082の回答は説明にさらに追加され、賛成票を投じます。


6
「基本スタックセクション」について聞いたことがない。.bssのはながら、(歴史)「シンボルによって開始ブロック」と実際に、「初期化されないデータ」である.DATAは「初期化データ」となるテキスト(.CODEない)店舗マシンコードに使用されます。スタックは実行時に作成されるため、バイナリにはスタックセクションはありません。
jlliagre 2017

プログラムのすべてが必ずしもフットプリントに含まれているわけではないため、「すべてがどこにあったかがわかっていれば、それをそのまま使用できます」も当てはまりません。
mirabilos 2017

1
@jlliagre正解です。誤って.text .codeと呼びました(回答を作成する際に説明を考えていたため)-更新されました。私は誤ってbssを名前で間違って考え、私の答えを更新しましたが、* Block Started by Symbolは本当に方程式に追加されるとは思わないので避け、それを初期化されていないデータとして使用することを説明しました。共通認識。ありがとうございました-この投稿を修正するためのコメントに感謝します。
X Tian

4

コアファイルは、プロセス終了時のスタックイメージ、メモリマッピング、およびレジスタのスナップショットです。その内容はコアのmanページにあるように操作できます。デフォルトでは、プライベートマッピング、共有マッピング、およびELFヘッダー情報がコアファイルにダンプされます。

あなたの質問来て、 gdbが実行可能を必要とする理由は、それが実行をシミュレートしないためです、代わりにvalgrindのようにバイナリ命令を読んで解釈することによって、それは代わりにプロセスの親になり、実行中のプロセスの動作を制御します時間。コアファイルを使用して、クラッシュ時のメモリマッピングとプロセスのプロセッサの状態を判断します。

Linuxでは、親プロセスは子に関する追加情報を取得できます。特に、ptraceを使用して、デバッガーがメモリの読み取り/書き込み、レジスター、シグナルマッピングの変更、実行の停止などのプロセスの低レベル情報にアクセスできるようにします。

デバッガがどのように機能するかを読んだ後は、コアファイルがあるにもかかわらず実行可能ファイルの要件を理解できます。


1

(他の良い答えに加えて)

最近のLinux(および多くのUnixライク)システムでは、デバッグ情報(シンボルのタイプ、ソースコードの場所、変数のタイプなどに関するメタデータを含む)はDWARF形式であり、ELF実行可能ファイル(またはELF共有ライブラリ)がいくつかの-gオプションでコンパイルされている場合。デバッグするプログラムをコンパイルすることをお勧めします。-g3 -O0おそらく-fno-inline最近のGCCを使用している場合は、ただし、GCCを使用すると、最適化とデバッグ情報の両方を使用してコンパイルすることもできます(例:)-O2 -g1ただし、デバッグ情報は少しあいまいな場合があります(これは、いくつかのいたずらなHeisenbugsを検出するのに少し役立ちます)。

同じ実行可能ファイルに対して多くの異なるコアファイル(多くのユーザーがバグレポートを作成する、広く使用されているソフトウェアを想像してください)がコアファイルにあるので、その情報をコアファイルに入れないようにしてくださいcore。また、core(5)ファイルはカーネルによってダンプされます。カーネルは、elf(5)実行可能ファイル内のDWARFセクションの存在を気にする必要はありません(これらのセクションは、いくつかのシグナルでコアをダンプした障害のあるプロセスの仮想アドレス空間にマップされていないためです( 7))。デバッグ情報が別のファイル(実行可能ファイルの外)に置かれる可能性もあります。

ところで、GDBは、デバッグ情報なしで実行可能ファイルのコアダンプをデバッグするのに苦労して使用できます。しかし、実際にはマシンコードレベルでデバッグします(プログラミング言語とそのコンパイラによって提供されるシンボリックレベルではありません)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.