« Win32デバッグ | トップページ | Win32デバッグ(3)・・・デバッグ情報 »

2009年5月 4日 (月)

Win32デバッグ(2)・・・クラス設計

前回はWin32のデバッグAPIの基本的なことを書いたが、今回はより実践的な事をやろうと思う。

前回、待機関数WaitForDebugEventでDEBUG_EVENT構造体に発生したイベントに関する情報が返されると書いたが、最初にこの構造体を内容を簡単に見てみる。まずは、DEBUG_EVENT構造体の定義から(定義だけはC言語を使うので、あしからず・・)

前半の3つメンバと後半の共用体の部分から構成されている。まずは、前半の3つのメンバから。これらは前回も触れたが、dwDebugCodeEventには、デバッグイベントの種類、dwProcessId、dwThreadIdにはデバッグイベントが発生したプロセスとスレッドの識別子がそれざれ返される。残りの共用体の部分には、デバッグイベントの種類に応じた追加の情報が返されるのであるが、例えば、CREATE_PROCESS_DEBUG_EVENTイベント発生時には、共用体の部分にCREATE_PROCESS_DEBUG_INFO構造体として返される。

順にCREAET_PROCESS_DEBUG_INFO構造体の定義は

となっている。例えば、上記構造体において、hProcess、hThreadには作成されたプロセス、スレッドのハンドルが返されるのであるが、シングルスレッドアプリケーションをデバッグするのならまだしも、マルチスレッドアプリケーションさらにはCreateProcess関数でDEBUG_PROCESSオプションを指定して、子孫のプロセスまでデバッグする場合、これらの情報を適切に管理しておくと、デバッガAPIを使った何かしらの実践的なアプリケーション(例えば、デバッガ自体やプロファイラなど)を作成する時に楽なので、それらをさっさと設計してしまおうというのが今回の趣旨なのである。

と、前置き長すぎbearing

ということで、ここでは、クラスとして設計するのであるが、まずは、プロセスから。デバッグ対象のプロセスの作成、終了は述べたとおり、CREATE_PROCESS_DEBUG_EVENT、EXIT_PROCESS_DEBUG_EVENTイベントで通知され、また、プロセスはプロセス識別子で一意に識別できるので、例えば、プロセスを表すクラスTProcessは次のようになる。

ProcessIdプロパティはプロセスのプロセス識別子、Handleプロパティはプロセスのプロセスハンドルを表す、また、プロセスは1つ以上のスレッドから構成されるので、そのリストであるTThreadListクラスのThreadsプロパティ、同様に、プロセスは、1つ以上のモジュールから構成されるので、そのリストであるTModuleListクラスのModulesプロパティからなる。また、プロセスを強制終了するTerminiateメソッド、プロセスのアドレス空間のメモリを読み書きできるようヘルパーとしてReadXXX、WriteXXXメソッドも追加してある。ReadXXX、WriteXXXメソッドの実装は前回に出てきたAPIを使って、こんな感じ。

次に、複数のプロセスをデバッグできるようにTProcessクラスのリストを保持するTProcessListクラスを定義する。

Addメソッドはリストに指定のプロセス識別子のプロセスを追加する。戻り値は上記のTProcessクラスのインスタンスで、重複したプロセス識別子を指定すると例外が発生する。Removeメソッドは、指定のプロセス識別子のプロセスをリストから削除する。Itemsプロパティは指定したプロセス識別子のプロセスを表すTProcessクラスのインスタンスを返す(存在しなければnil)。

同様に、スレッドを表すTThreadクラス、モジュールを表すTModuleクラスとそれらのリストクラスであるTThreadList、TModuleListクラスを定義する。プロセス、スレッドの場合はそれぞれプロセス識別子、スレッド識別子で一意に識別できるが、モジュールの場合は、モジュールがロードされたアドレスを使って一意に識別する(実行イメージやDLLはローダーによって衝突しないようプロセスのアドレス空間に配置されるのでロードされたアドレスはプロセス内で一意である、また、CREATE_PROCESS_DEBUG_EVENT、EXIT_PROCESS_DEBUG_EVENT、LOAD_DLL_DEBUG_EVENT、UNLOAD_DLL_DEBUG_EVENTイベント発生時にDEBUG_INFO構造体にそのアドレスが返される)。

TProcessとそのリストTProcessListと同様の設計になっているが、TThreadクラスには、スレッドのコンテキストを取得・設定するGetContextメソッド、SetContextメソッドを、また、スレッドを再開・停止・強制終了するResume、Suspend、Terminateメソッド、TModuleクラスには、モジュールのPEファイルのセクションヘッダを読み込むReadSectionHeadersメソッドをヘルパとして追加してある。

と、以上のクラスを定義すれば、各デバッグイベントのイベントハンドラは例えば次のように書ける。

最後に今回、作成したプログラムのダウンロードはSkyDriveのここから。これだけじゃ、ドライバが無いのでコンパイルもできないがとりあえず、アップロードしといた。Debug.pasは、今回作成したTProcessなどのクラスを定義したユニット、Debugger.pasでは、デバッグループやイベントハンドラを含むTDebuggerクラスを定義してある。複数のプロセスをデバッグできるようスレッドとして動作するようにしてある。

以上。ふぅhappy02

« Win32デバッグ | トップページ | Win32デバッグ(3)・・・デバッグ情報 »

Windows」カテゴリの記事

デバッグ」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1497665/39651725

この記事へのトラックバック一覧です: Win32デバッグ(2)・・・クラス設計:

« Win32デバッグ | トップページ | Win32デバッグ(3)・・・デバッグ情報 »

自作ソフトウェア

無料ブログはココログ

メモ