デバッガ:プロセッサのサポート
プロセッサ = CPUの基本的なデバッグサポートについて紹介しています。
基本的なアーキテクチャ
CPUの種類によらない基本的なアーキテクチャです。
ブレークポイント
ブレークポイントを実現することはデバッガを作る上で欠かせないものですが、最近のCPUではこれが二通りのやり方でサポートされています。
- ハードウェアブレークポイント
- ハードウェアが持つデバッグレジスタとプログラムカウンタとの比較によってブレークを実現します。デバッグレジスタに値を設定するだけでトラップが行えるため、下記のソフトウェアブレークと比べて非常に簡単です。また、この機能を使うとソフトウェアブレークポイントにあるいくつかの問題を避けることができます。残念ながら、レジスタの数に限りがあるためあまり使われることはありません。
- ソフトウェアブレークポイント
- 中断したい個所のコードをプロセッサ特有のトラップ命令で置き換えることにより、ブレークポイントを実現します。当然のことながらブレークポイントの数に限りが無いため、一般のデバッガでは非常によく使われます。
- ソフトウェアブレークポイントを実現する手順は多少複雑なため、下記に記しておきます。
- ブレークポイントを設定したい個所の命令を一度退避しておき、代わりにトラップ命令を置く
- その個所でトラップが発生した場合、それをOSに通知する
- 実行を再開する前に以前あった命令を書き戻しておく
- CPU命令を一つだけ実行する
- 直前にブレークした個所にあらためてトラップ命令を置く
- 通常実行を開始する
- トラップ命令を書いたり戻したりするところがこのアルゴリズムの最大のポイントです。CPUのトラップ命令によりエラーを通知されたOSは、デバッガに対してデバッギの中断を知らせます。その際、なぜ止まったのか、どこで止まったのか、などの情報をセットにすることで、デバッガがデバッギの状態を完全に把握することを可能にします。このトラップ命令というのは、プロセッサが可変長命令を採用している場合は、当然のことながら最も短い命令長を採用するのが普通です。
プロセッサを1命令ずつ実行させる特別なモード
プロセッサを1命令ずつ処理します。シングルステップ実行とも言います。
この機能がCPU上に存在しない場合でも、デバッガはこれをエミュレートすることが可能です。具体的には、実行コードをデコードしその次にある命令にトラップを仕掛けることによってシングルステップ実行を可能にします。そのトラップにかかった段階で、以前の命令を書き戻し、それから通常実行を開始するのです。
これはCPUに必ずしも必要な機能というわけではありませんし、実際にないCPUも存在します。ちなみにx86ではTFレジスタを切り替えることによりこのモードを発動させることが可能です。
データブレークポイント(ウォッチポイント)
データブレークポイントとは、ある特定のアドレスの書き込み時、ないし読み込み時にデバッギの中断を行う機能です。GCの障害など実行コードのトレースだけでは分かりにくいメモリ関係のバグを発見するのに役立ちます。これにも実行コードと同じように、ハードウェアによるものとソフトウェアによるものがあります。
- (データ)ハードウェアブレークポイント
- 一般的にデバッグレジスタによって実現され、そこに設定されたアドレスのデータが読まれたり書き換えられたりした場合にデバッギの中断が行われます。アドレスの範囲指定によるトラップが行える環境も存在するようです。
- コードブレークポイントの場合はあるアドレスを実行したら止まるというものですが、データブレークポイントの場合はあるアドレスへの書き込み/読み込みが行われた時に中断がなされます。実際のところこれらは似ているところが多く、x86の場合はDRn(nは数字)をコードorデータ用のデバッグレジスタとして扱うことができます。(DR7でどちらを採用するか決めます [ x86 debug register ])
- (データ)ソフトウェアブレークポイント
- デバッグレジスタが使えない場合、メモリの保護機能でその機能をエミュレートすることが可能です。具体的には指定されたアドレスを含むメモリページ全体を書き込み/読み込み不可にしトラップを発生させます。トラップ先でメモリアドレスの比較と中断するかどうかの決定を行い、必要に応じてデバッガにそれを通知するということを行います。メモリ保護機能
ときには、特殊なデバッグ用レジスタ
その名のとおり、特殊用途に使われるレジスタのことです。これには例えば、ハードウェアブレークポイントやコードブレークポイントを実現するためのレジスタが含まれます。
マルチスレッド、マルチプロセッサのサポート
当然のことながら、デバッグ用の機能というわけではありません。
例えばスレッドの作成と消滅、停止をデバッガに通知する手段があれば、マルチスレッドにおけるデッドロックは完全にデバッガが把握できるようになります。スレッド停止時にその理由やコードアドレスがデバッガに通知されれば、デバッガはどこでどのような理由でスレッドが止まったのかが分かります。このためデッドロックになった場合でも、どこでどのような理由でデットロックになったのかがすぐに分かるようになります。
残念なことに、ネイティブ環境のデバッガではそのためのコストがあまりに高いことやOSのサポートが十分でないなどの理由からあまり実装されることはないようです。(コストというのは、デバッギからOS→OSからデバッガ→デバッガからOS→OSからデバッギ、の通知サイクルに対してかかるコストのことです)
Last modified : 2009/01/30 12:07:00 UTC