コアダンプ
コアダンプ(英語:core dump)は、ある時点の使用中のメモリの内容をそのまま記録したものであり、一般に異常終了したプログラムのデバッグに使われる。最近では、特定のプロセスのメモリイメージ(あるいはその一部)とレジスタの内容などの情報を格納したファイルを指すのが一般的である。しかし、本来は使用中メモリの内容を全てプリントアウトしたものを指した。
その名前は、かつて主記憶用に利用された磁気コアメモリの内容を、ダンプトラックが砂利や小麦などを大量にダンプ(どさっと落とす)するかのようにプリントアウトすることから来ている。
背景
オペレーティングシステム (OS) が生まれ、大きなデータファイルを扱えるようになる以前は、コアダンプはメモリの内容を紙にプリントアウトしたものであり、一般に8進数か16進数(ヘックスダンプと呼ばれる)で記され、場合によっては、その横に何らかの形式に翻訳したものも表示された(機械語命令として翻訳したり、ASCII文字列として翻訳したり、十進数や浮動小数点数として翻訳したりする)。その後、コアダンプは特定のプロセスのアドレス空間の一部または全部のメモリイメージを格納したファイルとなり、同時にレジスタの値などの情報も格納するようになった。このようなファイルは適当なツールを使えば、かつての紙のコアダンプと同じように、人間が読める形式で参照可能となる。
コアダンプの原因
コアダンプは、プログラマがプログラムのバグを特定するのに使われることが多い。高級言語では、コンパイラによって機械語命令列が生成される。コンパイル時にエラーとならない場合でも、実行してみると不正なメモリアクセスなどのエラーが発生することが多く、コアダンプが生成される。その原因は、データ量を小さく見積もったことに起因するバッファオーバフロー、初期化していない変数を使用したことによるNullポインタアクセスなどである。また、kill -3
やgcore
でコアダンプを手動で生成することもできる。プロセスを終了する前に、gcore
コマンドの引数に process-id を指定することで、process-id のコアダンプを取得できる[1]。
コアダンプの利用
コアダンプはある種の状況では有益なデバッグツールとなる。初期のスタンドアロンシステムやバッチ処理システムでは、コアダンプを使うことでユーザーは非常に高価なコンピュータ資源を独占せずにプログラムをデバッグすることができた。さらに、スイッチとライトを使ってデバッグするよりも、プリントアウトは便利であった。タイムシェアリングやバッチ処理やサーバ機能を兼ねているようなシステムでは、コアダンプを使うとOSのオフラインでのデバッグが可能となり、システムは即座に通常の作業に戻すことができた。コアダンプは後で解析したり、他のコアダンプと比較検討したりすることができた。コンピュータ自体にデバッグ機能を組み込むのは現実的ではないような組み込みシステムでも、コアダンプを用いれば他のコンピュータ上でシステムを分析することができる。いくつかのオペレーティングシステム(初期のUNIXなど)は、動作中のプロセスをデバッグする機能をサポートしていなかったため、コアダンプを使って障害発生時のプロセスのメモリ内容上でデバッグを行った。もちろん、現在でも対話型デバッガのないシステムでは有用である。また、障害の発生条件が不明で再現性がない場合もコアダンプの解析が重要となるし、タイミング条件で発生するバグの場合には、対話型デバッガを使っていると再現しないこともある。
多くのオペレーティングシステムでプログラムの中の致命的エラーは自動的にコアダンプを引き起こす。コアダンプで生成されるファイルの最大サイズは、limit coredumpsize max-size
にて設定できる。また、コアダンプを全部削除するにはlimit coredumpsize 0
が使用できる[2]。従って、実際にコアダンプファイルが生成されたかどうかに関わらず、致命的エラーが発生したことを「コアを吐いた」と呼ぶこともある。プログラムのデバッグをするプログラマは、コアダンプが生成されるようになるunlimit coredumpsize
コマンドを知っている[3]。
コアダンプはあるメモリ領域の内容をそのまま完全に格納している。従って、アセンブリ言語やメモリの使用法に制限のないC言語などで起きやすいポインターの不正(ポインターが壊れる現象)の状態を確認するのに適している。このようなバグに関しては、ソースレベルのデバッガは有効な情報を提供できないことが多い。デバッガは可能ならばシンボルテーブルを使ってダンプを翻訳し、変数名をシンボルとして表示したり、対応するソースコードを表示したりできる。またdump analyzerと呼ばれる特殊なツールも存在する。
最近のUnix系OSでは、コアダンプファイルをGNU BinutilsのBFDライブラリを使って読むことができ、GNUデバッガ (gdb) やobjdump(英語版)はこのライブラリを使っている。このライブラリはメモリアドレスを指定すると、そのアドレスに相当する位置のコアダンプ内の生のデータを返すだけで、変数やデータ構造に関する知識は持たない。従って、このライブラリを利用する側が変数のアドレスやデータ構造を把握する必要があり、対象プログラムのシンボルテーブルなどを使ってデバッグすることになる。
コアダンプをある時点で(gcore
コマンドなどで)セーブしておき、後でその状態に戻すのに使うこともできる。高可用性システムによっては、このようなコアダンプファイルをプロセッサ間で転送することで高可用性を実現することもある。この手法はGNU EmacsやPerlといった、起動時のコストが非常に高いソフトウエアでも利用されている。またプリコンパイルヘッダーと呼ばれる技術ではコンパイラがヘッダファイルを処理した時点でコアダンプを作成し、ヘッダファイル処理時間を節約するといった利用方法もある。
コアダンプは生成時のメモリの内容をそのまま書き出すことから、セキュリティ上敏感な情報を含むことがあるため信頼できない第三者にアクセスさせない等取り扱いに注意を要する。ユーザプロセスのコアダンプの場合、所有者以外が一切アクセスできないようカーネルがパーミッションを設定することが多い。また、setuidないしはsetgidビットにより実効UIDないしは実効GIDを変更したプロセスにあっては、実UIDないしは実GIDのユーザからの覗き見を防ぐため、コアダンプを生成しないのが一般的である。カーネルのコアダンプではOSを使用していた全てのユーザの情報が見えてしまうため、所有者は通常スーパーユーザーとする。解析のためにコアダンプを外部へ持ち出す場合は、持ち出し先がコアダンプの取り扱いに際して信頼できることの確認や、コアダンプの暗号化等のセキュリティ対策を行うことが望ましい。
コアダンプファイルの形式
古いOSでは、プロセスのアドレス空間は連続であり、コアダンプファイルは単にアドレス順にバイトが並んでいるだけだった。最近のOSでは、プロセスのアドレス空間には使っていない部分があり、それを表現するためにファイル形式も複雑化している。また、ダンプ採取時のプログラムの状態などの情報も格納される。
Unix系システムでは、コアダンプはメモリイメージの再現が容易になることから、実行ファイルのファイルフォーマットを使っている。古いUNIXでは、a.outフォーマットが使われていた。ELF形式の普及に伴いコアダンプにもELFが採用されるようになり、Linux、System V、Solaris、BSD等にて使用されている。macOSではMach-O 形式が使われている。いずれも、実行ファイルのロードとは逆の処理を実行することによりメモリイメージをファイルに書き出し、コンテキストや仮想記憶の状態などメモリイメージ以外でデバッグに必要な情報を付加した上でコアダンプとする処理が基本となる。デバッガではコアダンプを生成した実行ファイルを実行時と同様にロードし、それにコアダンプが出力したメモリイメージを上書きすることでコアダンプ生成時のメモリを再現する。
例としてELFの場合、メモリイメージはプログラムヘッダのLOADセクション、付加情報はプログラムヘッダのNOTEセクションに記述する。
ジャーゴン
日本語では異常終了したプロセスがコアダンプを出力することを、俗に「コアを吐く」という。ここから転じて、嘔吐の意で「(リアル)コアダンプする」というジャーゴンがある。
関連項目
出典
参考文献
外部リンク
- GDBマニュアル
- OS毎のファイル形式
- Solaris
- HP-UX
- AIX
- NetBSD
- FreeBSD
- OpenBSD
- macOS