web-dev-qa-db-ja.com

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

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

11
user13757

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

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

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

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

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

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

実行可能オブジェクトにシンボルテーブルがまだ含まれている場合(ストリップされていない-man stripであり、-gを使用してgccへのデバッグ生成を生成し、acソースコンパイルを想定している場合)、次のことができます。シンボル名でコアの内容を調べます、例えばソースコードにinputLineという名前の変数/バッファがある場合、gdbでその名前を使用してその内容を確認できます。つまり、gdbは、inputLineが始まるプログラム初期化データセグメントの先頭からのオフセットと、その変数の長さを知っています。

さらに読む Article1Article 2 、および要点 Executable and Linking Format(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の回答は説明にさらに追加され、賛成票を投じます。

15
X Tian

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

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

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

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

4
enZyme

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

最近のLinux(および多くのUnixライク)システムでは、デバッグ情報(シンボルのタイプ、ソースコードの場所、変数のタイプなどに関するメタデータなど)は [〜#〜]にあります。 dwarf [〜#〜] フォーマットして [〜#〜] elf [〜#〜] 実行可能ファイル(またはELF共有ライブラリ)の中にある場合、それは_-g_でコンパイルされます。オプション。最近の [〜#〜] gcc [〜#〜] ;を使用している場合は、_-g3 -O0_とおそらく_-fno-inline_でデバッグするプログラムをコンパイルすることをお勧めします。ただし、GCCを使用すると、最適化とデバッグの両方の情報でコンパイルすることもできます。 _-O2 -g1_を使用しますが、その場合、デバッグ情報は少し "あいまい"になる可能性があります(これは、いくつかのいたずらを見つけるのに少し役立ちます Heisenbugs )。

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

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