コンテキストの変更

カーネルモードのデバッグでは、同時に実行されているプロセス、スレッド、およびユーザーセッションが多数あります。 "仮想アドレス 0x80002000" や " eax レジスタ" などの語句はあいまいです。 このような語句を理解できる コンテキスト を指定する必要があります。

デバッガーには、デバッグ中に設定できる5つの異なるコンテキストがあります。

  1. セッションコンテキストは、既定のユーザーセッションを示します。

  2. プロセスコンテキストによって、デバッガーが仮想アドレスを解釈する方法が決まります。

  3. ユーザーモードアドレスコンテキスト は、ほとんど設定されていません。 このコンテキストは、プロセスコンテキストを変更したときに自動的に設定されます。

  4. レジスタコンテキストは、デバッガーがレジスタを解釈する方法を決定し、スタックトレースの結果も制御します。 このコンテキストは スレッドコンテキスト とも呼ばれますが、この用語は完全に正確ではありません。 明示的なコンテキスト も、レジスタコンテキストの一種です。 明示的なコンテキストを指定すると、現在のレジスタコンテキストの代わりにそのコンテキストが使用されます。

  5. ローカルコンテキストによって、デバッガーがローカル変数を解釈する方法が決まります。 このコンテキストは、 スコープ とも呼ばれます。

セッションコンテキスト

複数のログオンセッションを同時に実行できます。 各ログオンセッションには、独自のプロセスがあります。

! Session拡張機能は、すべてのログオンセッションを表示するか、現在のセッションコンテキストを変更します。

セッション番号が "-2" として入力されると、セッションコンテキストは ! sprocess および ! spoolused 拡張機能によって使用されます。

セッションコンテキストが変更されると、プロセスコンテキストは、そのセッションのアクティブプロセスに自動的に変更されます。

プロセスコンテキスト

各プロセスには、仮想アドレスを物理アドレスにマップする方法を記録する独自のページディレクトリがあります。 プロセス内のいずれかのスレッドが実行されている場合、Windows オペレーティングシステムはこのページディレクトリを使用して仮想アドレスを解釈します。

ユーザーモードのデバッグ中に、現在のプロセスによってプロセスコンテキストが決定されます。 デバッガーのコマンド、拡張機能、およびデバッグ情報ウィンドウで使用される仮想アドレスは、現在のプロセスのページディレクトリを使用して解釈されます。

カーネルモードのデバッグ中に、 . プロセス (プロセスコンテキストの設定) コマンドを使用してプロセスコンテキストを設定できます。 このコマンドを使用して、仮想アドレスを解釈するために使用されるプロセスのページディレクトリを選択します。 プロセスコンテキストを設定した後、アドレスを受け取る任意のコマンドでこのコンテキストを使用できます。 このアドレスにブレークポイントを設定することもできます。 プロセス コマンドに /i オプションを指定して、干渉のあるデバッグを指定することにより、カーネルデバッガーを使用してユーザー空間にブレークポイントを設定することもできます。

カーネルスペース関数でプロセス固有のブレークポイントを使用して、カーネルデバッガーからユーザーモードのブレークポイントを設定することもできます。 戦略的ブレークポイントを設定し、適切なコンテキストが起動するまで待機します。

ユーザーモードアドレスコンテキスト は、プロセスコンテキストの一部です。 通常、ユーザーモードアドレスコンテキストを直接設定する必要はありません。 プロセスコンテキストを設定した場合、ユーザーモードアドレスコンテキストは、プロセスの関連するページテーブルのディレクトリベースに自動的に変更されます。

カーネルモードのデバッグ中にプロセスコンテキストを設定すると、そのプロセスコンテキストは別の . process コマンドによってコンテキストが変更されるまで保持されます。 また、ユーザーモードアドレスコンテキストは、 . プロセス または コンテキスト コマンドによって変更されるまで保持されます。 これらのコンテキストは、対象のコンピューターの実行時には変更されず、レジスタコンテキストまたはローカルコンテキストの変更による影響を受けません。

コンテキストの登録

各スレッドには、独自のレジスタ値があります。 これらの値は、スレッドが実行されているときに CPU レジスタに格納され、別のスレッドの実行時にメモリに格納されます。

ユーザーモードのデバッグ中に、現在のスレッドは通常、レジスタコンテキストを決定します。 デバッガーのコマンド、拡張機能、およびデバッグ情報ウィンドウでのレジスタへの参照は、現在のスレッドのレジスタに従って解釈されます。

次のコマンドのいずれかを使用してユーザーモードのデバッグを実行しているときに、レジスタコンテキストを現在のスレッド以外の値に変更できます。

.cxr (コンテキスト レコードの表示)

.ecxr (例外コンテキスト レコードの表示)

カーネルモードのデバッグ中に、次のコマンドを含むさまざまなデバッガーコマンドを使用して、レジスタコンテキストを制御できます。

.thread (レジスタ コンテキストの設定)

.cxr (コンテキスト レコードの表示)

.trap (トラップ フレームの表示)

これらのコマンドは、CPU レジスタの値を変更しません。 代わりに、デバッガーは、メモリ内の場所から指定されたレジスタコンテキストを取得します。 実際、デバッガーは 保存さ れているレジスタ値のみを取得できます。 (その他の値は動的に設定され、保存されません。 保存した値は、スタックトレースを再作成するのに十分です。

レジスタコンテキストを設定した後、レジスタ値を使用するすべてのコマンドに新しいレジスタコンテキストが使用されます (k (スタックバックトレースの表示)r (レジスタ) など)

ただし、マルチプロセッサコンピューターをデバッグする場合、一部のコマンドでプロセッサを指定できます。 (そのようなコマンドの詳細については、「 マルチプロセッサ構文」を参照してください)。コマンドのプロセッサを指定する場合、コマンドは、指定されたプロセッサが現在アクティブなプロセッサであっても、現在のレジスタコンテキストではなく、指定されたプロセッサのアクティブスレッドのレジスタコンテキストを使用します。

また、レジスタコンテキストが現在のプロセッサモード設定と一致しない場合、これらのコマンドは正しくない、または無意味な出力を生成します。 出力エラーを回避するために、レジスタの状態に依存するコマンドは、レジスタコンテキストに一致するようにプロセッサモードを変更するまで失敗します。 プロセッサモードを変更するには、 . effmach (有効なコンピューター) コマンドを使用します。

レジスタコンテキストを変更すると、ローカルコンテキストを変更することもできます。 この方法では、レジスタコンテキストはローカル変数の表示に影響を与える可能性があります。

アプリケーションの実行、ステップ実行、またはトレースが発生した場合、レジスタコンテキストは、プログラムカウンターの位置と一致するように直ちにリセットされます。 ユーザーモードでは、現在のプロセスまたはスレッドが変更されると、レジスタコンテキストもリセットされます。

スタックトレースはスタックポインターレジスタ (x86 ベースのプロセッサでは esp ) が指す場所から開始されるため、レジスタコンテキストはスタックトレースに影響します。 レジスタコンテキストが無効またはアクセスできない値に設定されている場合、スタックトレースを取得できません。

(データブレークポイント _ をコンテキストに適用する) コマンドを使用して、特定のレジスタコンテキストにプロセッサブレークポイント (データブレークポイント) を適用できます。

ローカルコンテキスト

プログラムが実行されている場合、ローカル変数の意味は、プログラムカウンターの場所によって異なります。このような変数のスコープは、定義されている関数にのみ拡張されるためです。

ユーザーモードまたはカーネルモードのデバッグを実行している場合、デバッガーは、ローカルコンテキストとして現在の関数 (スタック上の現在のフレーム) のスコープを使用します。 このコンテキストを変更するには、 フレーム (ローカルコンテキストの設定) コマンドを使用するか、 呼び出しウィンドウで目的のフレームをダブルクリックします。

ユーザーモードのデバッグでは、ローカルコンテキストは常に現在のスレッドのスタックトレース内のフレームです。 カーネルモードのデバッグでは、ローカルコンテキストは常に、現在のレジスタコンテキストのスレッドのスタックトレース内のフレームです。

ローカルコンテキストでは、一度に1つのスタックフレームのみを使用できます。 他のフレーム内のローカル変数にはアクセスできません。

次のいずれかのイベントが発生すると、ローカルコンテキストがリセットされます。

  • プログラムの実行、ステップ実行、またはトレース

  • 任意のコマンドでのスレッド区切り記号 (~) の使用

  • レジスタコンテキストの変更

_ 各 _ フレーム拡張に対して!を使用すると、スタック内のフレームごとに1つのコマンドを繰り返し実行できます。 このコマンドは、各フレームのローカルコンテキストを変更し、指定されたコマンドを実行して、ローカルコンテキストを元の値に戻します。