スレッドとプロセスの制御

デバッガー エンジンのスレッドとプロセスの概要については、「スレッドとプロセス」を参照してください。

イベントが発生すると、イベント スレッドとイベント プロセスが、イベントが発生したスレッドとプロセス (オペレーティング システムまたは仮想) に設定されます。 これらは、それぞれ GetEventThreadGetEventProcess を使用して見つけることができます。

暗黙的なスレッドとプロセス

カーネル モードデバッグでは、デバッガー エンジンは暗黙的なプロセスを使用して、仮想から物理アドレスへの変換を実行するときに使用する仮想アドレス空間を決定します。たとえば、VirtualToPhysical メソッドや ReadVirtual メソッドなどです。 イベントが発生すると、暗黙的なプロセスが現在のプロセスに設定されます。

暗黙的なプロセスは、SetImplicitProcessDataOffset を使用して変更できます。 暗黙的なプロセスを決定するには、GetImplicitProcessDataOffset を使用します。

注: ライブ カーネル デバッグ セッション中にブレークポイントを設定すると、デバッガー エンジンはブレークポイントの仮想アドレスをターゲットに渡し、ターゲットはブレークポイントを設定します。 この場合、ブレークポイントを処理するときにターゲットのプロセス コンテキストのみが使用されます。 暗黙的なプロセスの値は無関係です。

カーネル モード デバッグでは、デバッガー エンジンは暗黙的なスレッドを使用して、ターゲットのレジスタの一部を決定します。 これには、プロセッサ スタック (GetStackOffset を参照)、フレーム オフセット (GetFrameOffset を参照)、命令オフセット (GetInstructionOffset を参照) が含まれます。 イベントが発生すると、暗黙的なスレッドが現在のスレッドに設定されます。

暗黙的なスレッドは、SetImplicitThreadDataOffset を使用して変更できます。 暗黙的なスレッドを特定するには、GetImplicitThreadDataOffset を使用します。

すべてのレジスタが暗黙的なスレッドによって決定されるわけではありません。 一部のレジスタはメイン暗黙的なスレッドが変更されたときに同じになります。

警告 : 暗黙的なプロセスと暗黙的なスレッドは独立しています。 暗黙的スレッドが暗黙的プロセスに属していない場合、暗黙的スレッドのユーザーおよびセッション状態は間違った仮想アドレス空間に存在し、この情報にアクセスしようとするとエラーが発生したり、誤った結果が返されたりします。 カーネル メモリのアドレスはすべての仮想アドレス空間にわたって一定であるため、カーネル メモリにアクセスする場合には、この問題は発生しません。 したがって、カーネル メモリにある暗黙的スレッドの情報は、暗黙的プロセスとは独立してアクセスできます。

スレッド数

エンジン スレッド ID は、デバッガー エンジンによって、各オペレーティング システム スレッドとターゲットの各仮想スレッドを識別するために使用されます。

ターゲットが停止している間、各スレッドには、そのスレッドが属するプロセスに対する相対インデックスもあります。 どのプロセスでも、プロセスの最初のスレッドのインデックスは 0 で、最後のスレッドのインデックスはプロセス内のスレッドの数から 1 を引いた数です。 現在のプロセス内のスレッドの数は、GetNumberThreads を使用して見つけることができます。 現在のターゲット内のすべてのプロセスのスレッドの合計数は、GetTotalNumberThreads を使用して見つけることができます。

現在のプロセス内の 1 つ以上のスレッドのエンジン スレッド ID とシステム スレッド ID は、GetThreadIdsByIndex を使用してインデックスから見つけることができます。

エンジンは、各スレッドに関するいくつかの情報を保持します。 この情報は、現在のスレッドに対して照会でき、スレッドのエンジン スレッド ID を見つけるために使用できます。

システム スレッド ID (ユーザー モード デバッグのみ)
現在のスレッドのシステム スレッド ID は、GetCurrentThreadSystemId を使用して見つけることができます。 特定のシステム スレッド ID の場合、対応するエンジン スレッド ID は GetThreadIdBySystemId を使用して見つけることができます。

スレッド環境ブロック (TEB)
現在のスレッドの TEB のアドレスは、GetCurrentThreadTeb を使用して見つけることができます。 特定の TEB アドレスに対して、対応するエンジン スレッド ID が GetThreadIdByTeb を使用して見つかる場合があります。 カーネル モード デバッグでは、(仮想) スレッドの TEB は、最後のイベントが発生したときに対応するプロセッサ上で実行されていたシステム スレッドの TEB です。

データ オフセット
ユーザー モード デバッグでは、(システム) スレッドのデータ オフセットは、そのスレッドの TEB の場所です。 カーネル モードのデバッグでは、(仮想) スレッドのデータ オフセットは、最後のイベントが発生したときに対応するプロセッサ上で実行されていたシステム スレッドの KTHREAD 構造体です。 現在のスレッドのデータ オフセットは、GetCurrentThreadDataOffset を使用して見つけることができます。 特定のデータ オフセットに対して、対応するエンジン スレッド ID は GetThreadIdByDataOffset を使用して見つけることができます。

システムハンドル
現在のスレッドのシステム ハンドルは、GetCurrentThreadHandle を使用して見つけることができます。 特定のシステム ハンドルの場合、対応するエンジン スレッド ID は、GetThreadIdByHandle を使用して見つけることができます。 カーネル モード デバッグでは、(仮想) プロセスごとに人工ハンドルが作成されます。 このハンドルは、デバッガー エンジン API クエリでのみ使用できます。

プロセス

エンジン プロセス ID は、デバッガー エンジンによって、各オペレーティング システム プロセスとターゲットの各仮想プロセスを識別するために使用されます。

ターゲットが停止している間、各プロセスにはターゲットに対する相対インデックスがあります。 ターゲット内の最初のプロセスのインデックスは 0 で、最後のプロセスのインデックスはターゲット内のプロセスの数から 1 を引いた値です。 現在のターゲット内のプロセスの数は、GetNumberProcesses を使用して見つけることができます。

現在のプロセス内の 1 つ以上のスレッドのエンジン スレッド ID とシステム スレッド ID は、GetThreadIdsByIndex を使用してインデックスから見つけることができます。

エンジンは、各プロセスに関するいくつかの情報を保持します。 この情報は、現在のプロセスに対してクエリを実行でき、プロセスのエンジン プロセス ID を検索するために使用できます。

システム プロセス ID (ユーザー モード デバッグのみ)
現在のプロセスのシステム プロセス ID は、GetCurrentProcessSystemId を使用して見つけることができます。 特定のシステム プロセス ID に対して、対応するエンジン プロセス ID が GetProcessIdBySystemId を使用して見つかる場合があります。

プロセス環境ブロック (PEB)
現在のスレッドの PEB のアドレスは、GetCurrentThreadTeb を使用して見つけることができます。 特定の PEB アドレスについては、GetProcessIdByPeb を使用して、対応するエンジン プロセス ID が見つかる場合があります。 カーネル モード デバッグでは、(仮想) プロセスの PEB は、最後のイベントが発生したときに実行されていたシステム プロセスの PEB です。

データ オフセット
ユーザー デバッグ モードでは、(システム) プロセスのデータ オフセットは、そのプロセスの PEB の場所です。 カーネル モード デバッグでは、(仮想) プロセスのデータ オフセットは、最後のイベントが発生したときに実行されていたシステム プロセスの KPROCESS 構造体です。 現在のスレッドのデータ オフセットは、GetCurrentThreadDataOffset を使用して見つけることができます。 特定のデータ オフセットに対して、対応するエンジン スレッド ID は GetProcessIdByDataOffset を使用して見つけることができます。

システムハンドル
現在のスレッドのシステム ハンドルは、GetCurrentProcessHandle を使用して見つけることができます。 特定のシステム ハンドルの場合、対応するエンジン スレッド ID は、GetProcessIdByHandle を使用して見つけることができます。 カーネル モード デバッグでは、(仮想) プロセスごとに人工ハンドルが作成されます。 このハンドルは、デバッガー エンジン クエリでのみ使用できます。

イベント

ライブ ユーザー モード デバッグでは、スレッドが作成されるか、ターゲットで終了するたびに、スレッドの作成と終了スレッドのデバッグ イベントが生成されます。 これらのイベントにより、IDebugEventCallbacks::CreateThread および IDebugEventCallbacks::ExitThread コールバック メソッドが呼び出されます。

ライブ ユーザー デバッグ モードでは、プロセスがターゲット内で作成または終了するたびに、create-process および exit-process デバッグ イベントが生成されます。 これらのイベントにより、IDebugEventCallbacks::CreateProcess および IDebugEventCallbacks::ExitProcess コールバック メソッドが呼び出されます。

イベントの詳細については、「監視イベント」 に関するページを参照してください。

追加情報

TEB、KTHREAD、PEB、KPROCESS の構造体を含むスレッドとプロセスの詳細については、David ソロモンと Mark Russinovich による「Microsoft Windows Internals」を参照してください。