次の方法で共有


デバッグ ドライバー - ステップ バイ ステップ ラボ (Sysvad カーネル モード)

このラボでは、Sysvad オーディオ カーネル モード デバイス ドライバーをデバッグする方法を示す実践的な演習を提供します。

Microsoft Windows デバッガー (WinDbg) は、ユーザー モードとカーネル モードのデバッグを実行するために使用できる、Windows ベースの強力なデバッグ ツールです。 WinDbg は、Windows カーネル、カーネル モード ドライバー、およびシステム サービスだけでなく、ユーザー モードのアプリケーションとドライバーのソース レベルのデバッグを提供します。

WinDbg では、ソース コードのステップ実行、ブレークポイントの設定、変数の表示 (C++ オブジェクトを含む)、スタック トレース、メモリを実行できます。 デバッガー コマンド ウィンドウを使用すると、ユーザーはさまざまなコマンドを発行できます。

ラボのセットアップ

ラボを完了するには、次のハードウェアが必要です。

  • Windows 10 を実行しているノート PC またはデスクトップ コンピューター (ホスト)
  • Windows 10 を実行しているノート PC またはデスクトップ コンピューター (ターゲット)
  • 2 台の PC を接続するためのネットワーク ハブ/ルーターとネットワーク ケーブル
  • シンボル ファイルをダウンロードするためのインターネットへのアクセス

ラボを完了するには、次のソフトウェアが必要です。

  • Microsoft Visual Studio 2017
  • Windows 10 用 Windows ソフトウェア開発キット (SDK)
  • Windows 10 用 Windows Driver Kit (WDK)
  • Windows 10 用 Sysvad オーディオ ドライバーのサンプル

WDK のダウンロードとインストールの詳細については、「 Windows ドライバー キット (WDK) のダウンロード」を参照してください。

Sysvad デバッグのチュートリアル

このラボでは、カーネル モード ドライバーをデバッグするプロセスについて説明します。 演習では、Syvad 仮想オーディオ ドライバーのサンプルを使用します。 Syvad オーディオ ドライバーは実際のオーディオ ハードウェアと対話しないため、ほとんどのデバイスで使用できます。 ラボでは、次のタスクについて説明します。

エコー ドライバー ラボ

Echo ドライバーは、Sysvad オーディオ ドライバーよりも単純なドライバーです。 WinDbg を初めて使用する場合は、まず デバッグ ユニバーサル ドライバー - ステップ バイ ステップ ラボ (エコー カーネル モード) を完了することを検討してください。 このラボでは、そのラボのセットアップの指示が再利用されるため、そのラボを完了した場合は、ここでセクション 1 と 2 をスキップできます。

セクション 1: カーネル モード WinDbg セッションに接続する

セクション 1 では、ホストとターゲット システムでネットワーク デバッグを構成します。

このラボの PC は、カーネル デバッグにイーサネット ネットワーク接続を使用するように構成する必要があります。

このラボでは、2 台のコンピューターを使用します。 WinDbg は ホスト システムで実行され、Sysvad ドライバーは ターゲット システムで実行されます。

ネットワーク ハブ/ルーターとネットワーク ケーブルを使用して、2 台の PC を接続します。

ネットワーク ハブ/ルーター経由で接続された 2 台の PC を示す図。

カーネル モード アプリケーションを操作し、WinDbg を使用するには、イーサネット トランスポート経由で KDNET を使用することをお勧めします。 イーサネット トランスポート プロトコルの使用方法については、「 WinDbg の概要 (Kernel-Mode)」を参照してください。 ターゲット コンピューターのセットアップの詳細については、「 手動ドライバー展開用のコンピューターの準備KDNET ネットワーク カーネルデバッグの自動設定」を参照してください。

イーサネットを使用してカーネル モードデバッグを構成する

ターゲット システムでカーネル モード デバッグを有効にするには、次の手順を実行します。

<- ホスト システム上

  1. ホスト システムでコマンド プロンプトを開き、「 ipconfig /all」 と入力して IP アドレスを確認します。
C:\>ipconfig /all
Windows IP Configuration

 Host Name . . . . . . . . . . . . : TARGETPC
...

Ethernet adapter Ethernet:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b3
   Autoconfiguration IPv4 Address. . : 169.182.1.1
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . :
  1. ホスト システムの IP アドレスを記録する: ______________________________________

  2. ホスト システムのホスト名を記録する: ______________________________________

-> ターゲット システム上

  1. ターゲット システムでコマンド プロンプトを開き、 ping コマンドを使用して、2 つのシステム間のネットワーク接続を確認します。 サンプル出力に示されている 169.182.1.1 ではなく、記録したホスト システムの実際の IP アドレスを使用します。
C:\> ping 169.182.1.1

Pinging 169.182.1.1 with 32 bytes of data:
Reply from 169.182.1.1: bytes=32 time=1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255

Ping statistics for 169.182.1.1:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 1ms, Average = 0ms

KDNET ユーティリティを使用してターゲット システムでカーネル モード デバッグを有効にするには、次の手順を実行します。

  1. ホスト システムで、WDK KDNET ディレクトリを見つけます。 既定では、ここに配置されています。

    C:\Program Files (x86)\Windows Kits\10\Debuggers\x64

このラボでは、両方の PC がターゲットとホストの両方で 64 ビット バージョンの Windowson を実行していることを前提としています。 そうでない場合は、ターゲットが実行されているのと同じ "ビット数" のツールをホスト上で実行することをお勧めします。 たとえば、ターゲットが 32 ビット Windows を実行している場合は、ホストで 32 バージョンのデバッガーを実行します。 詳細については、「 32 ビットまたは 64 ビット デバッグ ツールの選択」を参照してください。

  1. これら 2 つのファイルを見つけて、ターゲット コンピューターで使用できるように、ネットワーク共有またはサム ドライブにコピーします。

    kdnet.exe

    VerifiedNICList.xml

  2. ターゲット コンピューターで、管理者としてコマンド プロンプト ウィンドウを開きます。 このコマンドを入力して、ターゲット PC 上の NIC がサポートされていることを検証します。

C:\KDNET>kdnet

Network debugging is supported on the following NICs:
busparams=0.25.0, Intel(R) 82579LM Gigabit Network Connection, KDNET is running on this NIC.kdnet.exe
  1. ホスト システムの IP アドレスを設定するには、このコマンドを入力します。 サンプル出力に示されている 169.182.1.1 ではなく、記録したホスト システムの実際の IP アドレスを使用します。 50010 など、操作するターゲットとホストのペアごとに一意のポート アドレスを選択します。
C:\>kdnet 169.182.1.1 50010

Enabling network debugging on Intel(R) 82577LM Gigabit Network Connection.
Key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p

Von Bedeutung

BCDEdit を使用してブート情報を変更する前に、テスト PC で BitLocker やセキュア ブートなどの Windows セキュリティ機能を一時的に中断する必要がある場合があります。 テストが完了し、セキュリティ機能が無効になっている場合は、テスト PC を適切に管理するときに、これらのセキュリティ機能を再度有効にします。 セキュア ブートは通常、UEFI で無効になります。 UEFI 設定にアクセスするには、システム、回復、高度なスタートアップを使用します。 再起動時に、[トラブルシューティング]、[詳細オプション]、[UEFI ファームウェアの設定] の順に選択します。 UEFI オプションを誤って設定したり、BitLocker を無効にしたりすると、システムが動作できなくなる可能性があるため、注意が必要です。

  1. このコマンドを入力して、dbgsettings が正しく設定されていることを確認します。
C:\> bcdedit /dbgsettings
busparams               0.25.0
key                     2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
debugtype               NET
hostip                  169.182.1.1
port                    50010
dhcp                    Yes
The operation completed successfully.

自動生成された一意キーをテキスト ファイルにコピーして、ホスト PC で入力する必要がないようにします。 キーを持つテキスト ファイルをホスト システムにコピーします。

: ファイアウォールとデバッガー

ファイアウォールからポップアップ メッセージを受信し、デバッガーを使用する場合は、 3 つのボックスをすべて オンにします。

Windows ファイアウォールがアプリの一部の機能をブロックしたことを示す Windows セキュリティ アラートのスクリーンショット。

<- ホスト システム上

  1. ホスト コンピューターで、管理者としてコマンド プロンプト ウィンドウを開きます。 WinDbg.exe ディレクトリに移動します。 Windows キットのインストールの一部としてインストールされた Windows Driver Kit (WDK) の x64version の WinDbg.exe を使用します。
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 
  1. 次のコマンドを使用して、リモート ユーザー デバッグで WinDbg を起動します。 キーとポートの値は、ターゲットで BCDEdit を使用して前に設定した値と一致します。
C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p

->ターゲットシステム上で

ターゲット システムを再起動します。

<-ホスト システム上

1 ~ 2 分で、デバッグ出力がホスト システムに表示されます。

ライブ カーネル接続からのコマンド ウィンドウ出力を表示している Windows デバッガーのスクリーンショット。

デバッガー コマンド ウィンドウは、WinDbg のプライマリ デバッグ情報ウィンドウです。 デバッガー コマンドを入力し、このウィンドウでコマンドの出力を表示できます。

デバッガー コマンド ウィンドウは 2 つのペインに分割されます。 ウィンドウの下部にある小さいウィンドウ (コマンド入力ウィンドウ) にコマンドを入力し、ウィンドウの上部にある大きなウィンドウでコマンドの出力を表示します。

コマンド入力ウィンドウで、上方向キーと下方向キーを使用して、コマンド履歴をスクロールします。 コマンドが表示されたら、コマンドを編集するか、 Enter キー を押してコマンドを実行できます。

セクション 2: カーネル モードデバッグのコマンドと手法

セクション 2 では、デバッグ コマンドを使用してターゲット システムに関する情報を表示します。

<- ホスト システム上

.prefer_dmlでデバッガー マークアップ言語 (DML) を有効にする

一部のデバッグ コマンドでは、デバッガー マークアップ言語を使用してテキストが表示されます。この言語を選択すると、詳細情報をすばやく収集できます。

  1. WinDBg で Ctrl + Break (スクロール ロック) を使用して、ターゲット システムで実行されているコードに分割します。 ターゲット システムが応答するまでに少し時間がかかる場合があります。
  2. デバッガー コマンド ウィンドウで DML を有効にするには、次のコマンドを入力します。
0: kd> .prefer_dml 1
DML versions of commands on by default

.hh を使用してヘルプを得る

.hh コマンドを使用して、参照コマンドのヘルプにアクセスできます。

  1. 次のコマンドを入力して、 .prefer_dmlのコマンド参照ヘルプを表示します。
    0: kd> .hh .prefer_dml
    

デバッガー のヘルプ ファイルには、 .prefer_dml コマンドのヘルプが表示されます。

.prefer-dml コマンドのヘルプが表示されているデバッガー ヘルプ アプリケーションのスクリーンショット。

ターゲット システム上の Windows のバージョンを表示する

  1. WinDbg ウィンドウで vertarget (ターゲット コンピューターのバージョンの表示) コマンドを入力して、ターゲット システムの詳細なバージョン情報を表示します。
0: kd> vertarget
Windows 10 Kernel Version 9926 MP (4 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 9926.0.amd64fre.fbl_awesome1501.150119-1648
Machine Name: ""
Kernel base = 0xfffff801`8d283000 PsLoadedModuleList = 0xfffff801`8d58aef0
Debug session time: Fri Feb 20 10:15:17.807 2015 (UTC - 8:00)
System Uptime: 0 days 01:31:58.931

読み込まれたモジュールを一覧表示する

  1. WinDbg ウィンドウに lm (List Loaded Modules) コマンドを入力して、読み込まれたモジュールを表示することで、適切なカーネル モード プロセスを使用していることを確認できます。
0: Kd> lm
start             end                 module name
fffff801`09200000 fffff801`0925f000   volmgrx    (no symbols)           
fffff801`09261000 fffff801`092de000   mcupdate_GenuineIntel   (no symbols)           
fffff801`092de000 fffff801`092ec000   werkernel   (export symbols)       werkernel.sys
fffff801`092ec000 fffff801`0934d000   CLFS       (export symbols)       CLFS.SYS
fffff801`0934d000 fffff801`0936f000   tm         (export symbols)       tm.sys
fffff801`0936f000 fffff801`09384000   PSHED      (export symbols)       PSHED.dll
fffff801`09384000 fffff801`0938e000   BOOTVID    (export symbols)       BOOTVID.dll
fffff801`0938e000 fffff801`093f7000   spaceport   (no symbols)           
fffff801`09400000 fffff801`094cf000   Wdf01000   (no symbols)           
fffff801`094d9000 fffff801`09561000   CI         (export symbols)       CI.dll
...

手記 省略された出力は "... で示されます。 この実験室で。

シンボル パスと読み込まれたシンボルをまだ設定していないため、デバッガーでは限られた情報を使用できます。

セクション 3: Sysvad オーディオ ドライバーをダウンロードしてビルドする

セクション 3 では、Sysvad オーディオ ドライバーをダウンロードしてビルドします。

通常、WinDbg を使用する場合は、独自のドライバー コードを使用します。 オーディオ ドライバーのデバッグに慣れるために、Sysvad 仮想オーディオ サンプル ドライバーが使用されます。 このサンプルは、ネイティブ カーネル モード コードをシングル ステップで実行する方法を示すために使用されます。 この手法は、複雑なカーネル モード コードの問題をデバッグする場合に非常に役立ちます。

Sysvad サンプル オーディオ ドライバーをダウンロードしてビルドするには、次の手順を実行します。

  1. GitHub から Sysvad オーディオ サンプルをダウンロードして抽出する

    ブラウザーを使用して、Sysvad サンプルと Readme.md ファイルをここで表示できます。

    https://github.com/Microsoft/Windows-driver-samples/tree/main/audio/sysvad

    [全般] フォルダーと [ZIP のダウンロード] ボタンが表示されている GitHub リポジトリのスクリーンショット。

    このラボでは、ユニバーサル ドライバー サンプルを 1 つの zip ファイルでダウンロードする方法を示します。

    ある。 master.zip ファイルをローカル ハード ドライブにダウンロードします。

    https://github.com/Microsoft/Windows-driver-samples/archive/master.zip

    b。 Windows-driver-samples-master.zipを長押し (または右クリック) し、[すべて抽出] を選択します。 新しいフォルダーを指定するか、抽出されたファイルを格納する既存のフォルダーを参照します。 たとえば、ファイルを抽出する新しいフォルダーとして C:\WDK_Samples\ を指定できます。

    c. ファイルが抽出されたら、次のサブフォルダーに移動します。

    C:\WDK_Samples\Sysvad

  2. Visual Studio でドライバー ソリューションを開く

    Visual Studio で[ ファイル>開く>プロジェクト/ソリューション...] を選択し、抽出されたファイル ( C:\WDK_Samples\Sysvad など) を含むフォルダーに移動します。 Syvad ソリューション ファイルをダブルクリックします。

    Visual Studio でソリューション エクスプローラーを見つけます。 (まだ開いていない場合は、[表示] メニューからソリューション エクスプローラーを選択します)。ソリューション エクスプローラーでは、多数のプロジェクトを含む 1 つのソリューションを確認できます。

    Sysvad プロジェクトから読み込まれた adapter.cpp ファイルを含む Visual Studio のスクリーンショット。

  3. サンプルの構成とプラットフォームを設定する

    ソリューション エクスプローラーで、 ソリューション 'sysvad' (7/7 プロジェクト) を長押し (または右クリック) し、[ Configuration Manager] を選択します。 構成とプラットフォームの設定が 4 つのプロジェクトで同じであることを確認します。 既定では、構成は "Win10 デバッグ" に設定され、プラットフォームはすべてのプロジェクトに対して "Win64" に設定されます。 1 つのプロジェクトに対して構成やプラットフォームの変更を行う場合は、残りの 3 つのプロジェクトに対して同じ変更を行う必要があります。

    手記 このラボでは、64 ビット Windows が使用されていることを前提としています。 32 ビット Windows を使用している場合は、32 ビットのドライバーをビルドします。

  4. ドライバーの署名を確認する

    TabletAudioSample をロケートします。 Sysvad ドライバーのプロパティ ページを開き、 ドライバー署名>署名モードテスト 署名に設定されていることを確認します。

  5. 既存のドライバーと重複しない値を使用するには、ドライバーサンプルを変更する必要があります。 「 サンプル コードから運用ドライバーへ - Windows に インストールされている既存の実際のドライバーと共存する一意のドライバー サンプルを作成する方法について、サンプルで変更する内容」を参照してください。

  6. Visual Studio を使用してサンプルをビルドする

    Visual Studio で、[ビルド]>[ソリューションのビルド] を選択します。

    ビルド ウィンドウには、6 つのプロジェクトすべてに対するビルドが成功したことを示すメッセージが表示されます。

ヒント

ビルド エラー メッセージが表示された場合は、ビルド エラー番号を使用して修正プログラムを特定します。 たとえば、 MSBuild エラー MSB8040 では、spectre 軽減ライブラリを操作する方法について説明します。

  1. ビルドされたドライバー ファイルを見つける

    エクスプローラーで、サンプルの抽出されたファイルを含むフォルダーに移動します。 たとえば、 C:\WDK_Samples\Sysvad に移動します (先ほど指定したフォルダーの場合)。 そのフォルダー内では、コンパイルされたドライバー ファイルの場所は、 Configuration Manager で選択した構成とプラットフォームの設定によって異なります。 たとえば、既定の設定を変更しない場合、コンパイルされたドライバー ファイルは、64 ビットのデバッグ ビルドの \x64\Debug という名前のフォルダーに保存されます。

    TabletAudioSample ドライバーのビルドファイルを含むフォルダーに移動します。

    C:\WDK_Samples\Sysvad\TabletAudioSample\x64\Debug。 このフォルダーには、TabletAudioSample .SYS ドライバー、シンボル pdp ファイル、および inf ファイルが含まれます。 また、DelayAPO、KWSApo、KeywordDetectorContosoAdapter dll、シンボル ファイルも見つける必要があります。

    ドライバーをインストールするには、次のファイルが必要です。

    ファイル名 説明
    TabletAudioSample.sys ドライバー ファイル。
    TabletAudioSample.pdb ドライバー シンボル ファイル。
    tabletaudiosample.inf ドライバーのインストールに必要な情報を含む情報 (INF) ファイル。
    KeywordDetectorContosoAdapter.dll キーワード検出のサンプル。
    KeywordDetectorContosoAdapter.pdb キーワード検出シンボル ファイルのサンプル。
    DelayAPO.dll サンプル遅延 APO。
    DelayAPO.pdb 遅延 APO シンボル ファイル。
    KWSApo.dll キーワード スッター APO のサンプル。
    KWSApo.pdb キーワード スポッター シンボル ファイル。
    TabletAudioSample.cer TabletAudioSample 証明書ファイル。
  2. USB サム ドライブを見つけるか、ビルドされたドライバー ファイルをホストからターゲット システムにコピーするようにネットワーク共有を設定します。

次のセクションでは、ターゲット システムにコードをコピーし、ドライバーをインストールしてテストします。

セクション 4: ターゲット システムに Sysvad オーディオ ドライバー サンプルをインストールする

セクション 4 では、devcon を使用して Sysvad オーディオ ドライバーをインストールします。

-> ターゲット システム上

ドライバーをインストールするコンピューターは、 ターゲット コンピューター または テスト コンピューターと呼ばれます。 通常、これはドライバー パッケージを開発してビルドするコンピューターとは別のコンピューターです。 ドライバーを開発およびビルドするコンピューターは、 ホスト コンピューターと呼ばれます。

ドライバー パッケージをターゲット コンピューターに移動し、ドライバーをインストールするプロセスは、ドライバーの 展開 と呼ばれます。

ドライバーを展開する前に、テスト署名を有効にしてターゲット コンピューターを準備する必要があります。 その後、ビルドされたドライバー サンプルをターゲット システムで実行する準備ができました。

ターゲット システムにドライバーをインストールするには、次の手順を実行します。

  1. 署名済みドライバーのテストを有効にする

    署名されたドライバーのテストを実行する機能を有効にするには:

    1. Windows の設定を開きます。

    2. [ 更新とセキュリティ] で、[回復] を選択 します

    3. [ スタートアップの詳細設定] で、[ 今すぐ再起動] を選択します。

    4. PC が再起動したら、[トラブルシューティング] を選択 します

    5. 次に、[ 詳細設定] オプション、[ スタートアップ設定] の順に選択し、[再起動] を選択 します

    6. F7 キーを押して[ドライバー署名の適用を無効にする]を選択します。

    7. PC は、新しい値が設定された状態で開始されます。

  2. -> ターゲット システム上

    ドライバーをインストールする

    次の手順では、サンプル ドライバーをインストールしてテストする方法を示します。

    このドライバーをインストールするために必要な INF ファイルは TabletAudioSample.inf です。 ターゲット コンピューターで、管理者としてコマンド プロンプト ウィンドウを開きます。 ドライバー パッケージ フォルダーに移動し、TabletAudioSample.inf ファイルを右クリックし、[ インストール] を選択します。

    テスト ドライバーが署名されていないドライバーであることを示すダイアログ ボックスが表示されます。 続行するには、[このドライバをインストールする] を選択します。

    Windows が発行元を確認できないことを示す Windows セキュリティ警告のスクリーンショット。

    ヒント

     インストールに問題がある場合は、次のファイルで詳細を確認してください。 %windir%\inf\setupapi.dev.log

    詳細な手順については、「 ドライバーの展開、テスト、デバッグのためのコンピューターの構成」を参照してください。

    INF ファイルには、tabletaudiosample.sysをインストールするためのハードウェア ID が含 まれています 。 Syvad サンプルの場合、ハードウェア ID は次のとおりです。 root\sysvad_TabletAudioSample

  3. デバイス マネージャーでドライバーを確認する

    ターゲット コンピューターのコマンド プロンプト ウィンドウで、「 devmgmt 」と入力してデバイス マネージャーを開きます。 デバイス マネージャーの [表示] メニューで、[ 種類別のデバイス] を選択します。

    デバイス ツリーで、[オーディオ デバイス] ノードで [仮想オーディオ デバイス (WDM) - タブレット サンプル ] を見つけます。 これは通常、 サウンド、ビデオ、およびゲーム コントローラー ノードの下にあります。 インストールされ、アクティブであることを確認します。

    デバイス マネージャーで PC 上の実際のハードウェアのドライバーを強調表示します。 次に、ドライバーを長押し (または右クリック) し、[無効] を選択してドライバーを無効にします。

    デバイス マネージャーで、オーディオ ハードウェア ドライバーが下矢印を表示し、無効になっていることを示していることを確認します。

    [Virtual Audio Device Tablet Sample]\(仮想オーディオ デバイス タブレットサンプル\) が強調表示されている Device Manager ツリーのスクリーンショット。

    サンプル ドライバーが正常にインストールされたら、テストする準備ができました。

Sysvad オーディオ ドライバーをテストする

  1. ターゲット コンピューターのコマンド プロンプト ウィンドウで、「 devmgmt 」と入力してデバイス マネージャーを開きます。 デバイス マネージャーの [ 表示 ] メニューで、[ 種類別のデバイス] を選択します。 デバイス ツリーで、 仮想オーディオ デバイス (WDM) - タブレット サンプルを見つけます。

  2. [コントロール パネル] を開き、[ ハードウェアとサウンド>オーディオ デバイスの管理] に移動します。 [サウンド] ダイアログ ボックスで、[ 仮想オーディオ デバイス (WDM) - タブレット サンプル] というラベルの付いたスピーカー アイコンを選択し、[ 既定値の設定] を選択しますが、[ OK] は選択しません。 これにより、[サウンド] ダイアログ ボックスが開いたままになります。

  3. ターゲット コンピューター上で MP3 またはその他のオーディオ ファイルを見つけ、ダブルクリックして再生します。 次に、[サウンド] ダイアログ ボックスで、 仮想オーディオ デバイス (WDM) - タブレット サンプル ドライバーに関連付けられているボリューム レベル インジケーターにアクティビティがあることを確認します。

セクション 5: WinDbg を使用してドライバーに関する情報を表示する

セクション 5 では、シンボル パスを設定し、カーネル デバッガー コマンドを使用して Sysvad サンプル ドライバーに関する情報を表示します。

シンボルを使用すると、WinDbg で変数名などの追加情報を表示できます。これは、デバッグ時に非常に役立ちます。 WinDbg は、ソース レベルのデバッグに Microsoft Visual Studio デバッグ シンボル形式を使用します。 PDB シンボル ファイルを持つモジュールから任意のシンボルまたは変数にアクセスできます。

デバッガーを読み込むには、次の手順を実行します。

<-ホスト システム上

  1. デバッガーを閉じた場合は、管理者コマンド プロンプト ウィンドウで次のコマンドを使用して再度開きます。 キーとポートを以前に構成したキーとポートに置き換えます。

    C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Ctrl+Break (Scroll Lock) を使用して、ターゲット システムで実行されているコードの実行を中断します。

シンボル パスを設定する

  1. WinDbg 環境で Microsoft シンボル サーバーへのシンボル パスを設定するには、 .symfix コマンドを使用します。

    0: kd> .symfix
    
  2. ローカル シンボルを使用するためには、.sympath+ でパスを追加し、その後 .reload /f を実行します。

    0: kd> .sympath+ C:\WDK_Samples\Sysvad
    0: kd> .reload /f
    

    注意.reload コマンドに /f force オプションを指定すると、指定したモジュールのすべてのシンボル情報が削除され、シンボルが再度読み込まれます。 場合によっては、このコマンドによってモジュール自体の再読み込みまたはアンロードも行われます。

手記 WinDbg が提供する高度な機能を使用するには、適切なシンボルを読み込む必要があります。 シンボルが正しく構成されていない場合は、シンボルに依存する機能を使用しようとしたときにシンボルが使用できないことを示すメッセージが表示されます。

0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.

シンボルサーバー

シンボルを操作するために使用できるアプローチは多数あります。 多くの場合、必要に応じて Microsoft が提供するシンボル サーバーからシンボルにアクセスするように PC を構成できます。 このチュートリアルでは、この方法が使用されることを前提としています。 環境内のシンボルが別の場所にある場合は、その場所を使用するように手順を変更します。 詳細については、「 Windows デバッガーのシンボル パス」を参照してください。

ソース コードシンボルの要件を理解する

ソース デバッグを実行するには、チェックされた (デバッグ) バージョンのバイナリをビルドする必要があります。 コンパイラはシンボル ファイル (.pdb ファイル) を作成します。 これらのシンボル ファイルは、バイナリ命令がソース行にどのように対応するかをデバッガーに表示します。 実際のソース ファイル自体もデバッガーからアクセスできる必要があります。

シンボル ファイルには、ソース コードのテキストが含まれていません。 デバッグの場合は、リンカーがコードを最適化しない場合に最適です。 コードが最適化されている場合、ソースのデバッグとローカル変数へのアクセスは困難になり、場合によってはほぼ不可能になります。 ローカル変数またはソース行の表示で問題が発生した場合は、次のビルド オプションを設定します。

set COMPILE_DEBUG=1

set ENABLE_OPTIMIZER=0

  1. デバッガーのコマンド領域に次のように入力して、Sysvad ドライバーに関する情報を表示します。

    0: kd> lm m tabletaudiosample v
    Browse full module list
    start             end                 module name
    fffff801`14b40000 fffff801`14b86000   tabletaudiosample   (private pdb symbols)  C:\Debuggers\sym\TabletAudioSample.pdb\E992C4803EBE48C7B23DC1596495CE181\TabletAudioSample.pdb
        Loaded symbol image file: tabletaudiosample.sys
        Image path: \SystemRoot\system32\drivers\tabletaudiosample.sys
        Image name: tabletaudiosample.sys
        Browse all global symbols  functions  data
        Timestamp:        Thu Dec 10 12:20:26 2015 (5669DE8A)
        CheckSum:         0004891E
    ...  
    

    詳細については、 lm を参照してください。

  2. デバッグ出力で [ すべてのグローバル シンボルの参照 ] リンクを選択すると、文字 a で始まる項目シンボルに関する情報が表示されます。

  3. DML が有効になっているため、出力の一部の要素は、選択できるホット リンクです。 デバッグ出力の データ リンクを選択すると、文字 a で始まる項目シンボルに関する情報が表示されます。

    0: kd> x /D /f tabletaudiosample!a*
     A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    
    fffff806`9adb1000 tabletaudiosample!AddDevice (struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *)
    

    詳細については、「 x (シンボルを調べる)」を参照してください。

  4. !lmi 拡張機能には、モジュールに関する詳細情報が表示されます。 「!lmi tabletaudiosample」と入力します。 出力は、次に示すテキストのようになります。

    0: kd> !lmi tabletaudiosample
    Loaded Module Info: [tabletaudiosample] 
             Module: tabletaudiosample
       Base Address: fffff8069ad90000
         Image Name: tabletaudiosample.sys
       Machine Type: 34404 (X64)
         Time Stamp: 58ebe848 Mon Apr 10 13:17:12 2017
               Size: 48000
           CheckSum: 42df7
    Characteristics: 22  
    Debug Data Dirs: Type  Size     VA  Pointer
                 CODEVIEW    a7,  e5f4,    d1f4 RSDS - GUID: {5395F0C5-AE50-4C56-AD31-DD5473BD318F}
                   Age: 1, Pdb: C:\Windows-driver-samples-master\audio\sysvad\TabletAudioSample\x64\Debug\TabletAudioSample.pdb
                       ??   250,  e69c,    d29c [Data not mapped]
         Image Type: MEMORY   - Image read successfully from loaded memory.
        Symbol Type: PDB      - Symbols loaded successfully from image header.
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
           Compiler: Resource - front end [0.0 bld 0] - back end [14.0 bld 24210]
        Load Report: private symbols & lines, not source indexed 
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
    
  5. 次に示すように、 !dh 拡張子を使用してヘッダー情報を表示します。

    0: kd> !dh tabletaudiosample 
    
    File Type: EXECUTABLE IMAGE
    FILE HEADER VALUES
        8664 machine (X64)
           9 number of sections
    5669DE8A time date stamp Thu Dec 10 12:20:26 2015
    
           0 file pointer to symbol table
           0 number of symbols
          F0 size of optional header
          22 characteristics
                Executable
                App can handle >2gb addresses
    ...
    

セクション 6: プラグ アンド プレイ デバイス ツリー情報の表示

セクション 6 では、Sysvad サンプル デバイス ドライバーと、それがプラグ アンド プレイ デバイス ツリー内のどこに存在するかについての情報を表示します。

プラグ アンド プレイ デバイス ツリーのデバイス ドライバーに関する情報は、トラブルシューティングに役立ちます。 たとえば、デバイス ドライバーがデバイス ツリーに存在しない場合、デバイス ドライバーのインストールに問題がある可能性があります。

デバイス ノードデバッグ拡張機能の詳細については、「 !devnode」を参照してください。

<-ホスト システム上

  1. プラグ アンド プレイ デバイス ツリー内のすべてのデバイス ノードを表示するには、 !devnode 0 1 コマンドを入力します。 このコマンドの実行には 1 ~ 2 分かかることがあります。 その間、WinDbg の状態領域に "*Busy" が表示されます。

    0: kd> !devnode 0 1
    Dumping IopRootDeviceNode (= 0xffffe0005a3a8d30)
    DevNode 0xffffe0005a3a8d30 for PDO 0xffffe0005a3a9e50
      InstancePath is "HTREE\ROOT\0"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe0005a3a3d30 for PDO 0xffffe0005a3a4e50
        InstancePath is "ROOT\volmgr\0000"
        ServiceName is "volmgr"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeEnumerateCompletion (0x30d)
        DevNode 0xffffe0005a324560 for PDO 0xffffe0005bd95ca0…
    ...
    
  2. 生成された出力を検索して、デバイス ドライバー sysvad の名前を検索するには、Ctrl + F キーを押します。

    検索フィールドに

    sysvad_TabletAudioSampleという名前のデバイス ノード エントリは、Syvad の !devnode 出力に存在します。

      DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0
        InstancePath is "ROOT\sysvad_TabletAudioSample\0000"
        ServiceName is "sysvad_tabletaudiosample"
        State = DeviceNodeStarted (0x308)
    ...
    

    PDO アドレスと DevNode アドレスが表示されることに注意してください。

  3. !devnode 0 1 sysvad_TabletAudioSample コマンドを使用して、Sysvad デバイス ドライバーに関連付けられているプラグ アンド プレイ情報を表示します。

    0: kd> !devnode 0 1 sysvad_TabletAudioSample
    Dumping IopRootDeviceNode (= 0xffffe00082df8d30)
    DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0
      InstancePath is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe000897fb650 for PDO 0xffffe00089927e30
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{64097438-cdc0-4007-a19e-62e789062e20}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00086d2f5f0 for PDO 0xffffe00089939ae0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{78880f4e-9571-44a4-a9df-960bde446487}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00089759bb0 for PDO 0xffffe000875aa060
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{7cad07f2-d0a0-4b9b-8100-8dc735e9c447}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00087735010 for PDO 0xffffe000872068c0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{fc38551b-e69f-4b86-9661-ae6da78bc3c6}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088457670 for PDO 0xffffe0008562b830
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{0894b831-c9fe-4c56-86a6-092380fc5628}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000893dbb70 for PDO 0xffffe00089d68060
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{15eb6b5c-aa54-47b8-959a-0cff2c1500db}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088e6f250 for PDO 0xffffe00089f6e990
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{778c07f0-af9f-43f2-8b8d-490024f87239}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000862eb4b0 for PDO 0xffffe000884443a0
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{e4b72c7c-be50-45df-94f5-0f2922b85983}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
    
  4. 前のコマンドに表示される出力には、ドライバーの実行中のインスタンスに関連付けられている PDO が含まれています。この例では 、0xffffe00089c575a0!devobj<PDO address> コマンドを入力して、Sysvad デバイス ドライバーに関連付けられているプラグ アンド プレイ情報を表示します。 ここに示されている PDO アドレスではなく、 !devnode が PC に表示する PDO アドレスを使用します。

    0: kd> !devobj 0xffffe00089c575a0
    Device object (ffffe00089c575a0) is for:
    0000004e \Driver\PnpManager DriverObject ffffe00082d47e60
    Current Irp 00000000 RefCount 65 Type 0000001d Flags 00001040
    SecurityDescriptor ffffc102b0f6d171 DevExt 00000000 DevObjExt ffffe00089c576f0 DevNode ffffe00086e68190 
    ExtensionFlags (0000000000)  
    Characteristics (0x00000180)  FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
    AttachedDevice (Upper) ffffe00088386a50 \Driver\sysvad_tabletaudiosample
    Device queue is not busy.
    
  5. !devobj コマンドに表示される出力には、接続されているデバイスの名前 \Driver\sysvad_tabletaudiosample が含まれます。 接続されているデバイスに関連付けられている情報を表示するには、ビット マスクが 2 の !drvobj コマンドを使用します。

    0: kd> !drvobj \Driver\sysvad_tabletaudiosample 2
    Driver object (ffffe0008834f670) is for:
    \Driver\sysvad_tabletaudiosample
    DriverEntry:   fffff80114b45310  tabletaudiosample!FxDriverEntry
    DriverStartIo: 00000000 
    DriverUnload:  fffff80114b5fea0                tabletaudiosample!DriverUnload
    AddDevice:     fffff80114b5f000  tabletaudiosample!AddDevice
    
    Dispatch routines:
    [00] IRP_MJ_CREATE                      fffff80117b49a20             portcls!DispatchCreate
    [01] IRP_MJ_CREATE_NAMED_PIPE           fffff8015a949a00          nt!IopInvalidDeviceRequest
    [02] IRP_MJ_CLOSE                       fffff80115e26f90                ks!DispatchCleanup
    [03] IRP_MJ_READ                        fffff80115e32710                ks!DispatchRead
    [04] IRP_MJ_WRITE                       fffff80115e327e0              ks!DispatchWrite
    [05] IRP_MJ_QUERY_INFORMATION           fffff8015a949a00         nt!IopInvalidDeviceRequest
    [06] IRP_MJ_SET_INFORMATION             fffff8015a949a00              nt!IopInvalidDeviceRequest
    [07] IRP_MJ_QUERY_EA                    fffff8015a949a00         nt!IopInvalidDeviceRequest
    [08] IRP_MJ_SET_EA                      fffff8015a949a00              nt!IopInvalidDeviceRequest
    [09] IRP_MJ_FLUSH_BUFFERS               fffff80115e32640  ks!DispatchFlush
    [0a] IRP_MJ_QUERY_VOLUME_INFORMATION    fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0b] IRP_MJ_SET_VOLUME_INFORMATION      fffff8015a949a00               nt!IopInvalidDeviceRequest
    [0c] IRP_MJ_DIRECTORY_CONTROL           fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0d] IRP_MJ_FILE_SYSTEM_CONTROL         fffff8015a949a00         nt!IopInvalidDeviceRequest
    [0e] IRP_MJ_DEVICE_CONTROL              fffff80115e27480               ks!DispatchDeviceIoControl
    [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL     fffff8015a949a00   nt!IopInvalidDeviceRequest
    [10] IRP_MJ_SHUTDOWN                    fffff8015a949a00      nt!IopInvalidDeviceRequest
    [11] IRP_MJ_LOCK_CONTROL                fffff8015a949a00  nt!IopInvalidDeviceRequest
    [12] IRP_MJ_CLEANUP                     fffff8015a949a00           nt!IopInvalidDeviceRequest
    [13] IRP_MJ_CREATE_MAILSLOT             fffff8015a949a00               nt!IopInvalidDeviceRequest
    [14] IRP_MJ_QUERY_SECURITY              fffff80115e326a0 ks!DispatchQuerySecurity
    [15] IRP_MJ_SET_SECURITY                fffff80115e32770      ks!DispatchSetSecurity
    [16] IRP_MJ_POWER                       fffff80117b3dce0            portcls!DispatchPower
    [17] IRP_MJ_SYSTEM_CONTROL              fffff80117b13d30              portcls!PcWmiSystemControl
    [18] IRP_MJ_DEVICE_CHANGE               fffff8015a949a00 nt!IopInvalidDeviceRequest
    [19] IRP_MJ_QUERY_QUOTA                 fffff8015a949a00  nt!IopInvalidDeviceRequest
    [1a] IRP_MJ_SET_QUOTA                   fffff8015a949a00       nt!IopInvalidDeviceRequest
    [1b] IRP_MJ_PNP                         fffff80114b5f7d0 tabletaudiosample!PnpHandler
    
  6. !devstack<PDO address> コマンドを入力して、デバイス ドライバーに関連付けられているプラグ アンド プレイ情報を表示します。 !devnode 0 1 コマンドに表示される出力には、ドライバーの実行中のインスタンスに関連付けられている PDO アドレスが含まれています。 この例では 、0xffffe00089c575a0。 次に示すようなアドレスではなく、 !devnode が PC に表示する PDO アドレスを使用します。

    0: kd> !devstack 0xffffe00089c575a0
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe00088d212e0  \Driver\ksthunk    ffffe00088d21430  0000007b
      ffffe00088386a50  \Driver\sysvad_tabletaudiosampleffffe00088386ba0  0000007a
    > ffffe00089c575a0  \Driver\PnpManager 00000000  0000004e
    !DevNode ffffe00086e68190 :
      DeviceInst is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
    

出力は、非常に単純なデバイス ドライバー スタックがあることを示しています。 sysvad_TabletAudioSample ドライバーは、PnPManager ノードの子です。 PnPManager はルート ノードです。

この図は、より複雑なデバイス ノード ツリーを示しています。

約 20 個のノードで構成されるデバイス ノード ツリーの図。

手記 より複雑なドライバー スタックの詳細については、「 ドライバー スタックデバイス ノードとデバイス スタック」を参照してください。

セクション 7: ブレークポイントの操作

セクション 7 では、ブレークポイントを使用して、特定のポイントでのコードの実行を停止します。

コマンドを使用したブレークポイントの設定

ブレークポイントは、特定のコード行でのコード実行を停止するために使用されます。 その後、その時点からコードをステップ フォワードして、コードの特定のセクションをデバッグできます。

デバッグ コマンドを使用してブレークポイントを設定するには、次のいずれかの b コマンドを使用します。

血圧

モジュールがアンロードされるまでアクティブになるブレークポイントを設定します。

bu

モジュールのアンロード時に未解決のブレークポイントを設定し、モジュールの再読み込み時に再度有効にします。

bm

シンボルのブレークポイントを設定します。 このコマンドは bu または bp を適切に使用し、ワイルドカード * を使用して(クラス内のすべてのメソッドと同様に) 一致するすべてのシンボルにブレークポイントを設定できるようにします。

  1. WinDbg UI を使用して、現在の WinDbg セッションで Debug>Source モード が有効になっていることを確認します。

  2. 次のコマンドを入力して、ローカル コードの場所をソース パスに追加します。

    .sympath+ C:\WDK_Samples\Sysvad
    
  3. 次のコマンドを入力して、シンボル パスにローカル シンボルの場所を追加します。

    .sympath+ C:\WDK_Samples\Sysvad
    
  4. デバッグ マスクを設定する

    ドライバーを操作しているときに、表示されるすべてのメッセージを表示すると便利です。 ターゲット システムからのすべてのデバッグ メッセージがデバッガーに表示されるように、既定のデバッグ ビット マスクを変更するには、次のように入力します。

    0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFF
    
  5. ドライバーの名前を使用して bm コマンドでブレークポイントを設定し、次にブレークポイントを設定する関数名 (AddDevice) を感嘆符で区切って設定します。

    0: kd> bm tabletaudiosample!AddDevice
    breakpoint 1 redefined
      1: fffff801`14b5f000 @!"tabletaudiosample!AddDevice"
    

    <module>!<symbol>、<class>::<method>、'<file.cpp>:<line number>' のような構文は、変数を設定する際に使用することができます。また、<条件><#> の回数をスキップすることも可能です。 詳細については、「ブレークポイントの 使用」を参照してください。

  6. bl コマンドを入力して、ブレークポイントが設定されたことを確認するために、現在のブレークポイントを一覧表示します。

    0: kd> bl
    1 e fffff801`14b5f000     0001 (0001) tabletaudiosample!AddDevice
    
  7. go コマンド g を入力して、ターゲット システムでのコード実行を再開します。

  8. ->ターゲットシステム上で

    Windows で、アイコンを使用するか mmc devmgmt.msc と入力してデバイス マネージャーを開きます。 デバイス マネージャー、[サウンド]、[ビデオ]、[ゲーム コントローラー] ノードの順に展開します。 仮想オーディオ ドライバー エントリを長押し (または右クリック) し、メニューから [無効] を選択します。

  9. 仮想オーディオ ドライバーのエントリをもう一度長押し (または右クリック) し、メニューから [有効] を選択します。

  10. <- ホスト システム上

    これにより、Windows によってドライバーが再読み込みされ、AddDevice が呼び出されます。 これにより、AddDevice デバッグ ブレークポイントが起動し、ターゲット システムでのドライバー コードの実行が停止します。

    Breakpoint 1 hit
    tabletaudiosample!AddDevice:
    fffff801`14baf000 4889542410      mov     qword ptr [rsp+10h],rdx
    

    ソース パスが正しく設定されている場合は、adapter.cppの AddDevice ルーチンで停止する必要があります。

    {
        PAGED_CODE();
    
        NTSTATUS        ntStatus;
        ULONG           maxObjects;
    
        DPF(D_TERSE, ("[AddDevice]"));
    
        maxObjects = g_MaxMiniports;
    
        #ifdef SYSVAD_BTH_BYPASS
        // 
        // Allow three (3) Bluetooth hands-free profile devices.
        //
        maxObjects += g_MaxBthHfpMiniports * 3; 
        #endif // SYSVAD_BTH_BYPASS
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
        return ntStatus;
    } // AddDevice
    
  11. p コマンドを入力するか F10 キーを押して、コードを 1 行ずつステップ 実行します。 sysvad AddDevice コードから PpvUtilCall、PnpCallAddDevice、PipCallDriverAddDevice Windows コードにステップ アウトできます。 p コマンドに数値を指定して、p 5 などの複数の行をステップフォワードできます。

  12. コードのステップ実行が完了したら、go コマンド g を使用してターゲット システムでの実行を再開します。

メモリ アクセス ブレークポイントの設定

メモリの場所にアクセスしたときに発生するブレークポイントを設定することもできます。 次の構文を使用して、 ba (アクセス時に中断) コマンドを使用します。

ba <access> <size> <address> {options}
選択肢 説明

e

CPUがアドレスから命令を取得する際に実行する

r

読み取り/書き込み (CPU がアドレスに対して読み取りまたは書き込みを行う場合)

w

書き込み (CPU がアドレスに書き込む場合)

任意の時点で 4 つのデータ ブレークポイントしか設定できないことに注意してください。データを正しく配置しているか、ブレークポイントをトリガーしないようにする必要があることに注意してください (単語は 2 で割り切れるアドレスで終わる必要があり、dwords は 4 で割り切れる必要があり、クワッドワードは 0 または 8 で割り切れる必要があります)。

たとえば、特定のメモリ アドレスに読み取り/書き込みブレークポイントを設定するには、次のようなコマンドを使用します。

ba r 4 fffff800`7bc9eff0

ブレークポイントの状態の変更

次のコマンドを使用して、既存のブレークポイントを変更できます。

bl

ブレークポイントを一覧表示します。

bc

リストからブレークポイントをクリアします。 bc * を使用して、すべてのブレークポイントをクリアします。

bd

ブレークポイントを無効にします。 bd * を使用して、すべてのブレークポイントを無効にします。

いる / ある / です

ブレークポイントを有効にします。 すべてのブレークポイントを有効にするには、*を使用します。

または、 編集>ブレークポイントを選択してブレークポイントを変更することもできます。 ブレークポイント ダイアログ ボックスは、既存のブレークポイントでのみ機能します。 コマンド ラインから新しいブレークポイントを設定する必要があります。

MixerVolume にブレークポイントを設定する

デバイス ドライバーが読み込まれた後、さまざまなイベントに応答するために、オーディオ ドライバー コードのさまざまな部分が呼び出されます。 次のセクションでは、ユーザーが仮想オーディオ ドライバーのボリューム コントロールを調整したときに発生するブレークポイントを設定します。

MixerVolume にブレークポイントを設定するには、次の手順に従います。

  1. <- ホスト システム上

    ボリュームを変更するメソッドを見つけるには、x コマンドを使用して、文字列ボリュームを含む CAdapterCommon のシンボルを一覧表示します。

    kd> x tabletaudiosample!CAdapterCommon::*
    ...
    fffff800`7bce26a0 tabletaudiosample!CAdapterCommon::MixerVolumeWrite (unsigned long, unsigned long, long)
    …
    

    Ctrl + F キーを押してボリュームの出力を上方向に検索し、MixerVolumeWrite メソッドを見つけます。

  2. bc * を使用して前のブレークポイントをクリアします。

  3. 次のコマンドを使用して、CAdapterCommon::MixerVolumeWrite ルーチンにシンボル ブレークポイントを設定します。

    kd> bm tabletaudiosample!CAdapterCommon::MixerVolumeWrite
      1: fffff801`177b26a0 @!"tabletaudiosample!CAdapterCommon::MixerVolumeWrite"
    
  4. ブレークポイントを一覧表示して、ブレークポイントが正しく設定されていることを確認します。

    kd> bl
    1 e fffff801`177b26a0 [c:\WDK_Samples\audio\sysvad\common.cpp @ 1668]    0001 (0001) tabletaudiosample!CAdapterCommon::MixerVolumeWrite
    
  5. go コマンド g を入力して、ターゲット システムでのコード実行を再開します。

  6. コントロール パネルで、 ハードウェアとサウンド>Sound を選択します。 シンクの説明サンプルを長押し (または右クリック) し、[プロパティ] を選択します。 [ レベル ] タブを選択します。スライダーの音量を調整します。

  7. これにより、SetMixerVolume デバッグ ブレークポイントが起動し、ターゲット システムでのドライバー コードの実行が停止します。

    kd> g
    Breakpoint 1 hit
    tabletaudiosample!CAdapterCommon::MixerVolumeWrite:
    fffff801`177b26a0 44894c2420      mov     dword ptr [rsp+20h],r9d
    

    common.cppのこの行で停止する必要があります

    {
        if (m_pHW)
        {
            m_pHW->SetMixerVolume(Index, Channel, Value);
        }
    } // MixerVolumeWrite
    
  8. dv コマンドを使用して、現在の変数とその値を表示します。 変数の詳細については、このラボの次のセクションで説明します。

    2: kd> dv
               this = 0x00000000`00000010
             ulNode = 0x344
          ulChannel = 0x210a45f8
            lVolume = 0n24
    
  9. F10 キーを押して、コードを 1 ステップ実行します。

  10. F5 キーを押して、MixerVolumeWrite コードの実行を完了します。

概要 - デバッガー コマンド ウィンドウからコードをステップ実行する

コードをステップ実行するために使用できるコマンドを次に示します (かっこで囲まれたキーボードのショートカットが関連付けられています)。

  • Break in (Ctrl + Break) - このコマンドは、システムが実行中で WinDbg と通信している限り、システムを中断します (カーネル デバッガーのシーケンスは Ctrl + C です)。

  • ステップ オーバー (F10) – このコマンドにより、コードの実行が一度に 1 つのステートメントまたは 1 つの命令を続行します。 呼び出しが発生した場合、呼び出されたルーチンに入らずにコード実行が呼び出しを通過します。 (プログラミング言語が C または C++ で、WinDbg がソース モードの場合は、デバッグを使用してソース モードを有効または無効にすることができます>ソース モード)。

  • ステップイン (F11) – このコマンドはステップオーバーに似ていますが、呼び出しの実行が呼び出されたルーチンに入る点が異なります。

  • ステップ アウト (Shift + F11) – このコマンドを実行すると、現在のルーチン (呼び出し履歴内の現在の場所) に対して実行が実行され、終了します。 これは、ルーチンを十分に確認した場合に便利です。

  • カーソルまで実行 (F7 または Ctrl + F10) – 実行を中断するソース ウィンドウまたは逆アセンブル ウィンドウにカーソルを置き、F7 キーを押します。コードの実行は、その時点まで実行されます。 コード実行のフローがカーソルによって示されたポイントに到達しない場合 (IF ステートメントが実行されていない場合など)、コード実行が指定されたポイントに達しなかったため、WinDbg は中断されないことに注意してください。

  • 実行 (F5) – ブレークポイントが検出されるか、バグ チェックなどのイベントが発生するまで実行します。

詳細オプション

  • 現在の行に命令を設定する (Ctrl + Shift + I) – ソース ウィンドウでは、カーソルを 1 行に配置し、このキーボード ショートカットを入力すると、コードの実行は続行するとすぐにその時点から開始されます (たとえば、F5 または F10 を使用)。 これは、シーケンスを再試行する場合に便利ですが、注意が必要です。 たとえば、レジスタと変数は、コードの実行がその行に自然に到達した場合に設定されません。

  • eip レジスタの直接設定 -- eip レジスタに値を入れることができ、F5 (または F10、F11 など) を押すとすぐに、そのアドレスから実行が開始されます。 これは、アセンブリ命令のアドレスを指定する点を除き、カーソル指定の現在の行に命令を設定するのと似ています。

コマンド ラインからではなく UI をステップ実行する方が簡単な場合があるため、この方法をお勧めします。 必要に応じて、次のコマンドを使用して、コマンド ラインでソース ファイルをステップ実行できます。

  • .lines - ソース行情報を有効にします。

  • bp main - モジュールの先頭に初期ブレークポイントを設定します。

  • l + t - ステップ実行はソース行で行われます。

  • [デバッグ>ソース モード] を選択してソース モードに入ります。L+t コマンドでは不十分です。

  • l + s - ソース行がプロンプトに表示されます。

  • g - "main" が入力されるまでプログラムを実行します。

  • p - 1 つのソース行を実行します。

詳細については、デバッグ リファレンス ドキュメント の WinDbg (クラシック) でのソース コード のデバッグを参照してください。

コードにブレークポイントを設定する

DebugBreak() ステートメントを追加し、プロジェクトを再構築してドライバーを再インストールすることで、コードにブレークポイントを設定できます。 このブレークポイントは、ドライバーが有効になるたびに起動されるため、運用コードではなく、初期の開発段階で使用する手法になります。 この手法は、ブレークポイント コマンドを使用してブレークポイントを動的に設定するほど柔軟ではありません。

ヒント: さらにラボ作業を行うために、ブレークポイントを追加していない Sysvad ドライバーのコピーを保持しておきたい場合があります。

  1. DebugBreak() ステートメントをサンプル コードに追加して、AddDevice メソッドが実行されるたびに中断を発生するように設定します。

    ...
        // Insert the DebugBreak() statment before the  PcAddAdapterDevice is called.
        //
    
        DebugBreak()
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
    
        return ntStatus;
    } // AddDevice
    
  2. 前に説明したすべての手順に従って、Microsoft Visual Studio でドライバーを再構築し、ターゲット コンピューターに再インストールします。 更新されたドライバーをインストールする前に、必ず既存のドライバーをアンインストールしてください。

  3. 前のブレークポイントをクリアし、デバッガーがターゲット PC にアタッチされていることを確認します。

  4. コードが実行され、 DebugBreak ステートメントに到達すると、実行が停止し、メッセージが表示されます。

    KERNELBASE!DebugBreak:
    77b3b770 defe     __debugbreak
    

セクション 8: 変数を表示する

セクション 8 では、デバッガー コマンドを使用して変数を表示します。

コードの実行時に変数を調べて、コードが期待どおりに動作していることを確認すると便利です。 このラボでは、オーディオ ドライバーがサウンドを生成する場合に変数を調べます。

  1. dv コマンドを使用して、tabletaudiosample に関連付けられているロケール変数を調べます。CMiniportWaveRT::New*.

    kd> dv tabletaudiosample!CMiniportWaveRT::New*
    
  2. 前のブレークポイントをクリアする

    bc *
    
  3. 次のコマンドを使用して、CMiniportWaveCyclicStreamMSVAD ルーチンにシンボル ブレークポイントを設定します。

    0: kd> bm tabletaudiosample!CMiniportWaveRT::NewStream
      1: fffff801`177dffc0 @!"tabletaudiosample!CMiniportWaveRT::NewStream"
    
  4. go コマンド g を入力して、ターゲット システムでのコード実行を再開します。

  5. -> ターゲット システム上

    小さなメディア ファイル (ファイル拡張子が.wavの Windows 通知サウンド ファイルなど) を見つけて、再生するファイルを選択します。 たとえば、Windows\Media ディレクトリにあるRing05.wavを使用できます。

  6. <- ホスト システム上

    メディア ファイルが再生されると、ブレークポイントが起動し、ターゲット システムでのドライバー コードの実行が停止します。

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::NewStream:
    fffff801`177dffc0 44894c2420      mov     dword ptr [rsp+20h],r9d
    

    ソースコードのウィンドウで、NewStream関数の開始部分の括弧が強調表示されている必要があります。

    /*++
    
    Routine Description:
    
      The NewStream function creates a new instance of a logical stream 
      associated with a specified physical channel. Callers of NewStream should 
      run at IRQL PASSIVE_LEVEL.
    
    Arguments:
    
      OutStream -
    
      OuterUnknown -
    
      Pin - 
    
      Capture - 
    
      DataFormat -
    
    Return Value:
    
      NT status code.
    
    --*/
    {
    
    ...
    
  7. ローカル変数

    dv コマンドを入力すると、特定のフレームのすべてのローカル変数の名前と値を表示できます。

    0: kd> dv
                    this = 0xffffe000`4436f8e0
               OutStream = 0xffffe000`49d2f130
            OuterUnknown = 0xffffe000`4436fa30
                     Pin = 0
                 Capture = 0x01 '
              DataFormat = 0xffffe000`44227790
    signalProcessingMode = {487E9220-E000-FFFF-30F1-D24900E0FFFF}
                ntStatus = 0n1055
                  stream = 0x00000000`00000200
    
  8. DML を使用して変数を表示する

    DML を使用して変数を探索するには、下線付き要素を選択します。 select アクションは、入れ子になったデータ構造をドリルダウンできる dx (Display NatVis Expression) コマンドを作成します。

    0: kd> dx -r1 (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380))
    (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380)) :  [Type: CMiniportWaveRT]
        [+0x020] m_lRefCount      : 0
        [+0x028] m_pUnknownOuter  : 0xffffe001d1477e50 : [Type: IUnknown *]
        [+0x030] m_ulLoopbackAllocated : 0x2050
        [+0x034] m_ulSystemAllocated : 0x180
        [+0x038] m_ulOffloadAllocated : 0x0
        [+0x03c] m_dwCaptureAllocatedModes : 0x0
    
    0: kd> dx -r1 (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) : {487E9220-E000-FFFF-30F1-D24900E0FFFF} [Type: _GUID]
        [<Raw View>]    
    
    0: kd> dx -r1 -n (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) :  [Type: _GUID]
        [+0x000] Data1            : 0x487e9220
        [+0x004] Data2            : 0xe000
        [+0x006] Data3            : 0xffff
        [+0x008] Data4            :  [Type: unsigned char [8]]
    
    0: kd> dx -r1 -n (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350))
    (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350)) :  [Type: unsigned char [8]]
        [0]              : 0x30
        [1]              : 0xf1
        [2]              : 0xd2
        [3]              : 0x49
        [4]              : 0x0
        [5]              : 0xe0
        [6]              : 0xff
        [7]              : 0xff
    
  9. グローバル変数

    「? 」と入力すると、グローバル変数のメモリ位置を見つけることができます<変数名>

    0: kd> ? signalProcessingMode
    Evaluate expression: -52768896396472 = ffffd001`c8acd348
    
  10. これにより、変数のメモリ位置 (この場合 は ffffd001'c8acd348) が返されます。 前のコマンドから返されたメモリ位置を使用して 、dd コマンドを入力してその場所の値をダンプすることで、メモリの場所の内容を表示できます。

    0: kd> dd ffffd001`c8acd348
    ffffd001`c8acd348  487e9220 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd358  4837c468 ffffe000 18221570 ffffc000
    ffffd001`c8acd368  4436f8e0 ffffe000 487e9220 ffffe000
    ffffd001`c8acd378  18ab145b fffff801 4837c420 ffffe000
    ffffd001`c8acd388  4436f8e0 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd398  4436fa30 ffffe000 00000000 00000000
    ffffd001`c8acd3a8  00000001 00000000 44227790 ffffe000
    ffffd001`c8acd3b8  18adc7f9 fffff801 495972a0 ffffe000
    
  11. dd コマンドで変数名を使用することもできます。

    0: kd> dd signalProcessingMode
    ffffd001`c8acd348  487e9220 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd358  4837c468 ffffe000 18221570 ffffc000
    ffffd001`c8acd368  4436f8e0 ffffe000 487e9220 ffffe000
    ffffd001`c8acd378  18ab145b fffff801 4837c420 ffffe000
    ffffd001`c8acd388  4436f8e0 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd398  4436fa30 ffffe000 00000000 00000000
    ffffd001`c8acd3a8  00000001 00000000 44227790 ffffe000
    ffffd001`c8acd3b8  18adc7f9 fffff801 495972a0 ffffe000
    
  12. 変数の表示

    ローカル変数を表示するには、[ 表示>ローカル ] メニュー項目を使用します。 このインターフェイスでは、より複雑なデータ構造をドリルダウンすることもできます。

    サンプル コードのローカルとコマンド ウィンドウを表示する WinDbg インターフェイス。

  13. p または F10 を押して、コード内で約 10 行前進し、ntStatus = IsFormatSupported(Pin、Capture、DataFormat) の行まで到達して強調表示します。

        PAGED_CODE();
    
        ASSERT(OutStream);
        ASSERT(DataFormat);
    
        DPF_ENTER(("[CMiniportWaveRT::NewStream]"));
    
        NTSTATUS                    ntStatus = STATUS_SUCCESS;
        PCMiniportWaveRTStream      stream = NULL;
        GUID                        signalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
    
        *OutStream = NULL;
    
         //
        // If the data format attributes were specified, extract them.
        //
        if ( DataFormat->Flags & KSDATAFORMAT_ATTRIBUTES )
        {
            // The attributes are aligned (QWORD alignment) after the data format
            PKSMULTIPLE_ITEM attributes = (PKSMULTIPLE_ITEM) (((PBYTE)DataFormat) + ((DataFormat->FormatSize + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
            ntStatus = GetAttributesFromAttributeList(attributes, attributes->Size, &signalProcessingMode);
        }
    
        // Check if we have enough streams.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = ValidateStreamCreate(Pin, Capture, signalProcessingMode);
        }
    
        // Determine if the format is valid.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = IsFormatSupported(Pin, Capture, DataFormat);
        }
    
    ...
    
  14. dv コマンドを使用して、特定のフレームのすべてのローカル変数の名前と値を表示します。 ローカル変数を変更する追加コードが実行され、一部の変数が現在のフレームに含まれていないか、その値が変更されたため、予想どおり、値はこのコマンドを最後に実行した時点とは異なっていることに注意してください。

    2: kd> dv
                    this = 0xffffe001`d1182000
               OutStream = 0xffffe001`d4776d20
            OuterUnknown = 0xffffe001`d4776bc8
                     Pin = 0
                 Capture = 0x00 '
              DataFormat = 0xffffe001`cd7609b0
    signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
                ntStatus = 0n0
                  stream = 0x00000000`00000000
    

セクション 9: 呼び出し履歴を表示する

セクション 9 では、呼び出し元/呼び出し先コードを調べるための呼び出し履歴を表示します。

呼び出し履歴は、プログラム カウンターの現在の場所に至った関数呼び出しのチェーンです。 呼び出し履歴の最上位の関数は現在の関数で、次の関数は現在の関数を呼び出した関数です。

呼び出し履歴を表示するには、k* コマンドを使用します。

キロバイト

スタックと最初の 3 つのパラメーターを表示します。

kp

スタックとパラメーターの完全な一覧を表示します。

kn

スタックの横にフレーム情報を表示できます。

呼び出し履歴を利用可能にしておく場合は、表示>呼び出し履歴 を選択して表示できます。 ウィンドウの上部にある列を選択して、追加情報の表示を切り替えます。

呼び出し履歴ウィンドウを表示する WinDbg インターフェイス。

この出力は、中断状態のサンプル アダプター コードのデバッグ中の呼び出し履歴を示しています。

0: kd> kb
# RetAddr           : Args to Child                                                           : Call Site
00 fffff800`7a0fa607 : ffffe001`d1182000 ffffe001`d4776d20 ffffe001`d4776bc8 ffffe001`00000000 : tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
01 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d122bb10 ffffe001`ceb81750 ffffe001`d173f058 : portcls!CPortPinWaveRT::Init+0x2e7
02 fffff800`7a0fc7f9 : ffffe001`d4776bc0 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
04 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
05 fffff800`7bd314b1 : ffffe001`d122bb10 ffffd001`c3098590 ffffe001`d122bd90 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
06 fffff803`cda1bfa8 : 00000000`00000024 00000000`00000000 00000000`00000000 ffffe001`d122bb10 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 fffff803`cda7b306 : 00000000`000001f0 ffffe001`d48ce690 ffffe001`d13d6400 ffffe001`d13d64c0 : nt!IopParseDevice+0x7c8
08 fffff803`cda12916 : 00000000`000001f0 ffffd001`c30988d0 ffffe001`d13d6490 fffff803`cda7b250 : nt!IopParseFile+0xb6
09 fffff803`cda1131c : ffffe001`d2ccb001 ffffd001`c30989e0 00ffffe0`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
0a fffff803`cd9fedb8 : ffffe001`00000001 ffffe001`d48ce690 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
0b fffff803`cd9fe919 : 000000ee`6d1fc8d8 000000ee`6d1fc788 000000ee`6d1fc7e0 000000ee`6d1fc7d0 : nt!IopCreateFile+0x3d8
0c fffff803`cd752fa3 : ffffc000`1f296870 fffff803`cd9d9fbd ffffd001`c3098be8 00000000`00000000 : nt!NtCreateFile+0x79
0d 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
0e 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
0f 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
10 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
11 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

DML を使用して、コードをさらに詳しく調べることができます。 最初の 00 エントリを選択すると、 .frame (ローカル コンテキストの設定) コマンドを使用してコンテキストが設定され、 dv (ローカル変数の表示) コマンドによってローカル変数が表示されます。

0: kd> .frame 0n0;dv /t /v
00 ffffd001`c30981d0 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
ffffd001`c30982b0 class CMiniportWaveRT * this = 0xffffe001`d1182000
ffffd001`c30982b8 struct IMiniportWaveRTStream ** OutStream = 0xffffe001`d4776d20
ffffd001`c30982c0 struct IPortWaveRTStream * OuterUnknown = 0xffffe001`d4776bc8
ffffd001`c30982c8 unsigned long Pin = 0
ffffd001`c30982d0 unsigned char Capture = 0x00 '
ffffd001`c30982d8 union KSDATAFORMAT * DataFormat = 0xffffe001`cd7609b0
ffffd001`c3098270 struct _GUID signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
ffffd001`c3098210 long ntStatus = 0n0
ffffd001`c3098218 class CMiniportWaveRTStream * stream = 0x00000000`00000000

セクション 10: プロセスとスレッドを表示する

セクション 10 では、デバッガー コマンドを使用してプロセスとスレッドを表示します。

処理

現在のプロセス コンテキストを変更するには、.process <process> コマンドを使用します。 次の例では、プロセスを識別してコンテキストを切り替える方法を示します。

出力は、プロセスが audiodg.exeに関連付けられていることを示しています。 このトピックの前のセクションで説明したブレークポイントにまだ移動している場合は、現在のプロセスを audiodg.exe イメージに関連付ける必要があります。

<- ホスト システム上

0: kd> !process
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 70 Clone 0 Private 504. Modified 16. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       <Invalid>
    UserTime                          00:00:00.000
    KernelTime                        00:00:00.000
    QuotaPoolUsage[PagedPool]         81632
    QuotaPoolUsage[NonPagedPool]      9704
    Working Set Sizes (now,min,max)  (2154, 1814, 2109) (8616KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2101
    VirtualSize                       2097192 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2336
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1573

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject

        THREAD ffffe001ceb77080  Cid 10f0.16dc  Teb: 000000ee6cf8d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d112c840  Cid 10f0.0a4c  Teb: 000000ee6cf8f000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d16c7840  Cid 10f0.13c4  Teb: 000000ee6cf91000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001cec67840  Cid 10f0.0dbc  Teb: 000000ee6cf93000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001d1117840  Cid 10f0.1d6c  Teb: 000000ee6cf95000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001cdeae840  Cid 10f0.0298  Teb: 000000ee6cf97000 Win32Thread: 0000000000000000 RUNNING on processor 2

このプロセスに関連付けられているスレッドの 1 つが RUNNING 状態であることに注意してください。 このスレッドは、ブレークポイントにヒットしたときにメディア クリップの再生をサポートしていました。

!process 0 0 コマンドを使用して、すべてのプロセスの概要情報を表示します。 コマンド出力で Ctrl + F キーを押して、audiodg.exe イメージに関連付けられているプロセスのプロセス ID を見つけます。 次に示す例では、プロセス ID は ffffe001d147c840 です

このラボの後半で使用するために、PC 上の audiodg.exe に関連付けられているプロセス ID を記録します。 ________________________

...

PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
...

デバッガーに g を入力して、メディア クリップの再生が完了するまでコードを前方に実行します。 次に、Ctrl + ScrLk (Ctrl + Break) キーを押してデバッガーに中断します。!process コマンドを使用して、別のプロセスが実行されていることを確認します。

!process
PROCESS ffffe001cd0ad040
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001aa000  ObjectTable: ffffc00017214000  HandleCount: <Data Not Accessible>
    Image: System
    VadRoot ffffe001d402b820 Vads 438 Clone 0 Private 13417. Modified 87866. Locked 64.
    DeviceMap ffffc0001721a070
    Token                             ffffc00017216a60
    ElapsedTime                       05:04:54.716
    UserTime                          00:00:00.000
    KernelTime                        00:00:20.531
    QuotaPoolUsage[PagedPool]         0
    QuotaPoolUsage[NonPagedPool]      0
    Working Set Sizes (now,min,max)  (1720, 50, 450) (6880KB, 200KB, 1800KB)
    PeakWorkingSetSize                15853
    VirtualSize                       58 Mb
    PeakVirtualSize                   74 Mb
    PageFaultCount                    46128
   MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      66

        THREAD ffffe001cd0295c0  Cid 0004.000c  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0120  SynchronizationEvent

        THREAD ffffe001cd02a6c0  Cid 0004.0010  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0ba0  Semaphore Limit 0x7fffffff
...

上記の出力は、 ffffe001cd0ad040 の別のシステム プロセスが実行されていることを示しています。 イメージ名には、audiodg.exeではなく System が表示されます。

次に、!process コマンドを使用して、audiodg.exeに関連付けられたプロセスに切り替えます。 この例では、プロセス ID は ffffe001d147c840 です。 この例のプロセス ID を、前に記録したプロセス ID に置き換えます。

0: kd> !process  ffffe001d147c840
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 60 Clone 0 Private 299. Modified 152. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       1 Day 01:53:14.490
    UserTime                          00:00:00.031
    KernelTime                        00:00:00.031
    QuotaPoolUsage[PagedPool]         81552
    QuotaPoolUsage[NonPagedPool]      8344
    Working Set Sizes (now,min,max)  (1915, 1814, 2109) (7660KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2116
    VirtualSize                       2097189 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2464
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1418

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      36             IdealProcessor: 0             
        UserTime                  00:00:00.015
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007ff7fb928de0
        Stack Init ffffd001c2ec6dd0 Current ffffd001c2ec60c0
        Base ffffd001c2ec7000 Limit ffffd001c2ec1000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d115c080  Cid 10f0.15b4  Teb: 000000ee6cf9b000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d0bf0640  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      1              IdealProcessor: 0             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c3143dd0 Current ffffd001c3143520
        Base ffffd001c3144000 Limit ffffd001c313e000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      518918         Ticks: 17616 (0:00:04:35.250)
        Context Switch Count      9              IdealProcessor: 1             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
        Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
        Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

このコードはアクティブではないので、すべてのスレッドが想定どおりに WAIT 状態になります。

スレッド

スレッドを表示および設定するコマンドは、プロセスのコマンドとよく似ています。 !thread コマンドを使用してスレッドを表示します。 現在のスレッドを設定するには 、.thread を使用します。

メディア プレーヤーに関連付けられているスレッドを調べるには、メディア クリップをもう一度再生します。 前のセクションで説明したブレークポイントがまだ設定されている場合は、audiodg.exeのコンテキストで停止します。

現在のスレッドの簡単な情報を表示するには、!thread -1 0 を使用します。 スレッド アドレス、スレッドとプロセス ID、スレッド環境ブロック (TEB) アドレス、実行するスレッドが作成された Win32 関数のアドレス (存在する場合)、スレッドのスケジュール状態が表示されます。

0: kd> !thread -1 0
THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0

実行中のスレッドの詳細を表示するには、「 !thread」と入力します。 次のような情報が表示されます。

0: kd> !thread
THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0
IRP List:
    ffffe001d429e580: (0006,02c8) Flags: 000008b4  Mdl: 00000000
Not impersonating
DeviceMap                 ffffc00019113080
Owning Process            ffffe001d147c840       Image:         audiodg.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      537630         Ticks: 0
Context Switch Count      63             IdealProcessor: 1             
UserTime                  00:00:00.000
KernelTime                00:00:00.015
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           : Args to Child                                                           : Call Site
ffffd001`c70c62a8 fffff800`7a0fa607 : ffffe001`d4aec5c0 ffffe001`cdefd3d8 ffffe001`d4aec5c0 ffffe001`cdefd390 : tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
ffffd001`c70c62b0 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d429e580 ffffe001`d4ea47b0 ffffe001`cdefd3d8 : portcls!CPortPinWaveRT::Init+0x2e7
ffffd001`c70c6340 fffff800`7a0fc7f9 : ffffe001`d4aec430 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
ffffd001`c70c63c0 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
ffffd001`c70c6450 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
ffffd001`c70c6510 fffff800`7bd314b1 : ffffe001`d429e580 ffffd001`c70c6590 ffffe001`d429e800 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
ffffd001`c70c6540 fffff803`cda1bfa8 : 00000000`00000025 00000000`00000000 00000000`00000000 ffffe001`d429e580 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
ffffd001`c70c65a0 fffff803`cda7b306 : 00000000`000002fc ffffe001`d5e0d510 00000000`00000000 ffffe001`d3341bd0 : nt!IopParseDevice+0x7c8
ffffd001`c70c6770 fffff803`cda12916 : 00000000`000002fc ffffd001`c70c68d0 ffffe001`d3341ba0 fffff803`cda7b250 : nt!IopParseFile+0xb6
ffffd001`c70c67d0 fffff803`cda1131c : ffffe001`ceb6c601 ffffd001`c70c69e0 00000000`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
ffffd001`c70c6970 fffff803`cd9fedb8 : ffff8ab8`00000001 ffffe001`d5e0d510 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
ffffd001`c70c6a90 fffff803`cd9fe919 : 000000ee`6d37c6e8 00000004`6d37c500 000000ee`6d37c5f0 000000ee`6d37c5e0 : nt!IopCreateFile+0x3d8
ffffd001`c70c6b40 fffff803`cd752fa3 : fffff6fb`7da05360 fffff6fb`40a6c0a8 fffff681`4d815760 ffff8ab8`92895e23 : nt!NtCreateFile+0x79
ffffd001`c70c6bd0 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`c70c6c40)
000000ee`6d37c568 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
000000ee`6d37c570 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
000000ee`6d37c578 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
000000ee`6d37c580 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

k コマンドを使用して、スレッドに関連付けられている呼び出し履歴を表示します。

0: kd> k
# Child-SP          RetAddr           Call Site
00 ffffd001`c70c62a8 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
01 ffffd001`c70c62b0 fffff800`7a0fb2c3 portcls!CPortPinWaveRT::Init+0x2e7
02 ffffd001`c70c6340 fffff800`7a0fc7f9 portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 ffffd001`c70c63c0 fffff800`7a180552 portcls!xDispatchCreate+0xd9
04 ffffd001`c70c6450 fffff800`7a109a9a ks!KsDispatchIrp+0x272
05 ffffd001`c70c6510 fffff800`7bd314b1 portcls!DispatchCreate+0x7a
06 ffffd001`c70c6540 fffff803`cda1bfa8 ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 ffffd001`c70c65a0 fffff803`cda7b306 nt!IopParseDevice+0x7c8
08 ffffd001`c70c6770 fffff803`cda12916 nt!IopParseFile+0xb6
09 ffffd001`c70c67d0 fffff803`cda1131c nt!ObpLookupObjectName+0x776
0a ffffd001`c70c6970 fffff803`cd9fedb8 nt!ObOpenObjectByNameEx+0x1ec
0b ffffd001`c70c6a90 fffff803`cd9fe919 nt!IopCreateFile+0x3d8
0c ffffd001`c70c6b40 fffff803`cd752fa3 nt!NtCreateFile+0x79
0d ffffd001`c70c6bd0 00007fff`69805b74 nt!KiSystemServiceCopyEnd+0x13
0e 000000ee`6d37c568 00007fff`487484e6 0x00007fff`69805b74
0f 000000ee`6d37c570 0000029b`00000003 0x00007fff`487484e6
10 000000ee`6d37c578 00000000`0000012e 0x0000029b`00000003
11 000000ee`6d37c580 00000000`00000000 0x12e

デバッガーに g を入力して、メディア クリップの再生が完了するまでコードを前方に実行します。 次に、Ctrl - ScrLk (Ctrl-Break) キーを押してデバッガーに侵入します。!thread コマンドを使用して、別のスレッドが実行されていることを確認します。

0: kd> !thread
THREAD ffffe001ce80b840  Cid 17e4.01ec  Teb: 00000071fa9b9000 Win32Thread: ffffe001d41690d0 RUNNING on processor 0
Not impersonating
DeviceMap                 ffffc0001974e2c0
Owning Process            ffffe001d1760840       Image:         rundll32.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      538040         Ticks: 0
Context Switch Count      3181840        IdealProcessor: 0             
UserTime                  00:00:08.250
KernelTime                00:00:10.796
Win32 Start Address 0x00007ff6d2f24270
Stack Init ffffd001cd16afd0 Current ffffd001cd16a730
Base ffffd001cd16b000 Limit ffffd001cd165000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5

Child-SP          RetAddr           : Args to Child                                                           : Call Site
fffff803`cf373d18 fffff800`7a202852 : fffff803`cf373e60 00000000`00000001 ffffe001`cf4ed330 00000000`0000ffff : nt!DbgBreakPointWithStatus
fffff803`cf373d20 fffff803`cd6742c6 : ffffe001`cf4ed2f0 fffff803`cf373e60 00000000`00000001 00000000`0004e4b8 : kdnic!TXSendCompleteDpc+0x142
fffff803`cf373d60 fffff803`cd74d495 : 00000000`00000000 fffff803`cd923180 fffff803`cde1f4b0 fffff901`40669010 : nt!KiRetireDpcList+0x5f6
fffff803`cf373fb0 fffff803`cd74d2a0 : 00000000`00000090 0000000e`0000006a 00000000`00000092 00000000`00000000 : nt!KxRetireDpcList+0x5 (TrapFrame @ fffff803`cf373e70)
ffffd001`cd16a6c0 fffff803`cd74bd75 : 00000000`00000000 fffff803`cd74a031 00000000`00000000 00000000`00000000 : nt!KiDispatchInterruptContinue
ffffd001`cd16a6f0 fffff803`cd74a031 : 00000000`00000000 00000000`00000000 ffffe001`cff4d2a0 fffff803`cd67738e : nt!KiDpcInterruptBypass+0x25
ffffd001`cd16a700 fffff960`50cdb5a4 : fffff901`400006d0 00000000`00000001 fffff901`40000d60 ffffd001`cd16a9f0 : nt!KiInterruptDispatchNoLockNoEtw+0xb1 (TrapFrame @ ffffd001`cd16a700)
ffffd001`cd16a890 fffff960`50c66b2f : 00000000`00000000 fffff901`40669010 fffff901`42358580 fffff901`40000d60 : win32kfull!Win32FreePoolImpl+0x34
ffffd001`cd16a8c0 fffff960`50c68cd6 : 00000000`00000000 ffffd001`cd16a9f0 fffff901`400006d0 fffff901`400c0460 : win32kfull!EXLATEOBJ::vAltUnlock+0x1f
ffffd001`cd16a8f0 fffff803`cd752fa3 : 00000000`00000000 00000000`00000000 ffffe001`ce80b840 00000000`00000000 : win32kfull!NtGdiAlphaBlend+0x1d16
ffffd001`cd16add0 00007fff`674c1494 : 00007fff`674b1e97 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`cd16ae40)
00000071`fa74c9a8 00007fff`674b1e97 : 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 00000000`00ffffff : 0x00007fff`674c1494
00000071`fa74c9b0 0000a7c6`daee0559 : 00000000`00000001 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 : 0x00007fff`674b1e97
00000071`fa74c9b8 00000000`00000001 : 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 00000000`01010bff : 0x0000a7c6`daee0559
00000071`fa74c9c0 0000020b`741f3c50 : 00000000`00ffffff 00000000`00000030 00000000`01010bff 00000000`00000000 : 0x1
00000071`fa74c9c8 00000000`00ffffff : 00000000`00000030 00000000`01010bff 00000000`00000000 00000000`000000c0 : 0x0000020b`741f3c50
00000071`fa74c9d0 00000000`00000030 : 00000000`01010bff 00000000`00000000 00000000`000000c0 00000000`00000030 : 0xffffff
00000071`fa74c9d8 00000000`01010bff : 00000000`00000000 00000000`000000c0 00000000`00000030 00000071`00000030 : 0x30
00000071`fa74c9e0 00000000`00000000 : 00000000`000000c0 00000000`00000030 00000071`00000030 00000071`01ff8000 : 0x1010bff

イメージ名は rundll32.exe。メディア クリップの再生に関連付けられているイメージ名ではありません。

手記 現在のスレッドを設定するには、「.thread <thread number>」と入力します。

スレッドとプロセスの詳細については、次のリファレンスを参照してください。

スレッドとプロセス

コンテキストの変更

セクション 11: IRQL、レジスタ、および逆アセンブル

保存した IRQL を表示する

セクション 11 では、IRQL とレジストリの内容を表示します。

<- ホスト システム上

割り込み要求レベル (IRQL) は、割り込みサービスの優先順位を管理するために使用されます。 各プロセッサには、スレッドが増減できる IRQL 設定があります。 プロセッサの IRQL 設定以下で発生する割り込みはマスクされ、現在の操作に干渉しません。 プロセッサの IRQL 設定より上に発生する割り込みは、現在の操作よりも優先されます。 !irql 拡張機能は、デバッガーの中断が発生する前に、ターゲット コンピューターの現在のプロセッサで割り込み要求レベル (IRQL) を表示します。 ターゲット コンピューターがデバッガーに侵入すると、IRQL が変更されますが、デバッガーの中断直前に有効だった IRQL が保存され、!irql によって表示されます。

0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)

< レジスタと逆アセンブルを表示する

レジスタを表示する

r (Registers) コマンドを使用して、現在のプロセッサ上の現在のスレッドのレジスタの内容を表示します。

0: kd> r
rax=000000000000c301 rbx=ffffe00173eed880 rcx=0000000000000001
rdx=000000d800000000 rsi=ffffe00173eed8e0 rdi=ffffe00173eed8f0
rip=fffff803bb757020 rsp=ffffd001f01f8988 rbp=ffffe00173f0b620
 r8=000000000000003e  r9=ffffe00167a4a000 r10=000000000000001e
r11=ffffd001f01f88f8 r12=0000000000000000 r13=ffffd001f01efdc0
r14=0000000000000001 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
nt!DbgBreakPointWithStatus:
fffff803`bb757020 cc              int     3

または、 ビュー>登録を選択して、レジスタの内容を表示することもできます。

約 12 個のレジスタを表示する WinDbg レジスタ ウィンドウのスクリーンショット。

アセンブリ言語コードの実行やその他のシナリオでは、レジスタの内容を表示すると便利です。 詳細については、 r (レジスタ) を参照してください。

レジスタの内容については、 x86 アーキテクチャと x64 アーキテクチャ に関 するページを参照してください。

分解

実行中のコードを逆アセンブルして、実行中のアセンブリ言語コードを表示するには、[ 表示>Disassembly] を選択します。

アセンブリ言語コードを示す WinDbg 逆アセンブリ ウィンドウのスクリーンショット。

アセンブリ言語の逆アセンブリの詳細については、「 注釈付き x86 逆アセンブリ 」および「 注釈付き x64 逆アセンブリ」を参照してください。

セクション 12: メモリの操作

セクション 12 では、デバッガー コマンドを使用してメモリの内容を表示します。

メモリの表示

メモリを調べて問題を特定したり、変数やポインターなどを調べたりする必要がある場合があります。 次の d* <address> コマンドのいずれかを入力すると、メモリを表示できます。

データベース

バイト値と ASCII 文字でデータを表示します。

dd

データを 2 倍幅の単語 (4 バイト) として表示します。

デュ

データを Unicode 文字として表示します。

ディーダブリュー

データを単語値 (2 バイト) および ASCII 文字として表示します。

手記 無効なアドレスを表示しようとすると、その内容が疑問符 (?) として表示されます。

または、[表示]<Memory を選択してメモリを表示することもできます。 表示形式プルダウンを使用して、メモリの表示方法を変更します。

さまざまな表示形式オプションを含む WinDbg ビュー のメモリ ウィンドウのスクリーンショット。

  1. ボリューム コントロールに関連付けられているデータを表示するには、bm コマンドを使用して PropertyHandlerAudioEngineVolumeLevel ルーチンを対象にしたブレークポイントを設定します。 新しいブレークポイントを設定する前に、bc * を使用して前のすべてのブレークポイントをクリアします。

    kd> bc *
    
  2. bm コマンドを使用して PropertyHandlerAudioEngineVolumeLevel ルーチンにブレークポイントを設定します。

    kd> bm tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  3. ブレークポイントを一覧表示して、ブレークポイントが正しく設定されていることを確認します。

    kd> bl
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  4. g コマンドを使用してコードの実行を再開します。

    ターゲット・システムで、システム・トレイ内のボリュームを調整します。 これにより、ブレークポイントが起動します。

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume:
    fffff80f`02c3a4b0 44894c2420      mov     dword ptr [rsp+20h],r9d
    
  5. ローカル変数を表示するには、[ 表示>ローカル メニュー項目を使用します。 IVolume 変数の現在の値に注意してください。

  6. サンプル コードで IVolume 変数のデータ型と現在の値を表示するには、 dt コマンドと変数の名前を入力します。

    kd> dt lVolume
    Local var @ 0xa011ea50 Type long
    0n-6291456
    
  7. ブレークポイントがSetDeviceChannelVolumeの入力時にヒットします。

    STDMETHODIMP_(NTSTATUS) CMiniportWaveRT::SetDeviceChannelVolume(_In_  ULONG _ulNodeId, _In_ UINT32 _uiChannel, _In_  LONG  _Volume)
    {
        NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    
        PAGED_CODE ();
    
        DPF_ENTER(("[CMiniportWaveRT::SetEndpointChannelVolume]"));
        IF_TRUE_ACTION_JUMP(_ulNodeId != KSNODE_WAVE_AUDIO_ENGINE, ntStatus = STATUS_INVALID_DEVICE_REQUEST, Exit);
    
        // Snap the volume level to our range of steppings.
        LONG lVolume = VOLUME_NORMALIZE_IN_RANGE(_Volume); 
    
        ntStatus = SetChannelVolume(_uiChannel, lVolume);
    Exit:
        return ntStatus;
    }
    
  8. dt (Display Type) コマンドを使用して、IVolume のメモリ位置に値を表示しようとします。

    kd> dt dt lVolume
    Local var @ 0xffffb780b7eee664 Type long
    0n0
    

    変数はまだ定義されていないため、情報は含まれません。

  9. F10 キーを押して、SetDeviceChannelVolume のコードの最後の行に進みます。

        return ntStatus;
    
  10. dt (Display Type) コマンドを使用して、IVolume のメモリ位置に値を表示します。

    kd> dt lVolume
    Local var @ 0xffffb780b7eee664 Type long
    0n-6291456
    

    変数がアクティブになったので、この例では 6291456 の値が表示されます。

  11. IVolume のメモリ位置を表示するには、? (式の評価) コマンドを使用することもできます。

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  12. 示されているアドレス ffffb780'b7eee664 は lVolume 変数のアドレスです。 dd コマンドを使用して、その場所のメモリの内容を表示します。

    kd>  dd ffffb780`b7eee664
    ffffb780`b7eee664  ffa00000 00000018 00000000 c52d7008
    ffffb780`b7eee674  ffffc98e e0495756 fffff80e c52d7008
    ffffb780`b7eee684  ffffc98e 00000000 fffff80e 00000000
    ffffb780`b7eee694  ffffc98e ffa00000 ffffb780 b7eee710
    ffffb780`b7eee6a4  ffffb780 00000000 00000000 c7477260
    ffffb780`b7eee6b4  ffffc98e b7eee7a0 ffffb780 b7eee6f0
    ffffb780`b7eee6c4  ffffb780 e04959ca fffff80e 00000000
    ffffb780`b7eee6d4  00000000 00000028 00000000 00000002
    
  13. 範囲パラメーター L4 を指定することで、アドレスの最初の 4 バイトを表示できます。

    kd> dd ffffb780`b7eee664 l4
    ffffb780`b7eee664  ffa00000 00000018 00000000 c52d7008
    
  14. 表示されるメモリ出力の種類を確認するには、 dudadb コマンドを入力します。

    kd> du ffffb780`b7eee664 
    ffffb780`b7eee664  ""
    
    kd> a ffffb780`b7eee664 
    ffffb780`b7eee664  ""
    
    kd> db 0xffffae015ff97664 
    ffffae01`5ff97664  00 80 bc ff 18 00 00 00-00 00 00 00 08 50 e0 51  .............P.Q
    ffffae01`5ff97674  00 c0 ff ff 56 57 da 56-0e f8 ff ff 08 50 e0 51  ....VW.V.....P.Q
    ffffae01`5ff97684  00 c0 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00  ................
    ffffae01`5ff97694  00 c0 ff ff aa 80 bc ff-01 ae ff ff 10 77 f9 5f  .............w._
    ffffae01`5ff976a4  01 ae ff ff 40 00 00 00-00 e6 ff ff 10 dc 30 55  ....@.........0U
    ffffae01`5ff976b4  00 c0 ff ff a0 77 f9 5f-01 ae ff ff f0 76 f9 5f  .....w._.....v._
    ffffae01`5ff976c4  01 ae ff ff ca 59 da 56-0e f8 ff ff 00 00 00 00  .....Y.V........
    ffffae01`5ff976d4  00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00  ....(...........
    

    df float オプションを使用して、単精度浮動小数点数 (4 バイト) としてデータを表示します。

    df ffffb780`b7eee664 
    ffffb780`b7eee664          -1.#QNAN   3.3631163e-044                0        -2775.002
    ffffb780`b7eee674          -1.#QNAN  -5.8032637e+019         -1.#QNAN        -2775.002
    ffffb780`b7eee684          -1.#QNAN                0         -1.#QNAN                0
    ffffb780`b7eee694          -1.#QNAN         -1.#QNAN         -1.#QNAN  -2.8479408e-005
    

メモリへの書き込み

メモリの読み取りに使用されるコマンドと同様に、e* コマンドを使用してメモリの内容を変更できます。

コマンド 説明

ASCII 文字列 (NULL 終端ではない)

eu

Unicode 文字列 (NULL で終了しない)

うわっ

ワード値 (2 バイト)

eza

NULL で終わる ASCII 文字列

ezu

NULL で終わる Unicode 文字列

eb

バイト値

専門家

ダブルワード値 (4 バイト)

次の例は、メモリを上書きする方法を示しています。

  1. 最初に、サンプル コードで使用されている lVolume のアドレスを見つけます。

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  2. eb コマンドを使用して、そのメモリ アドレスを新しい文字で上書きします。

    kd> eb 0xffffb780`b7eee664 11 11 11 11 11
    
  3. db コマンドを入力して、文字が上書きされたことを確認するメモリの場所を表示します。

    kd> db 0xffffb780`b7eee664
    ffffb780`b7eee664  11 11 11 11 11 00 00 00-00 00 00 00 08 70 2d c5  .............p-.
    ffffb780`b7eee674  8e c9 ff ff 56 57 49 e0-0e f8 ff ff 08 70 2d c5  ....VWI......p-.
    ffffb780`b7eee684  8e c9 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00  ................
    ffffb780`b7eee694  8e c9 ff ff 00 00 a0 ff-80 b7 ff ff 10 e7 ee b7  ................
    ffffb780`b7eee6a4  80 b7 ff ff 00 00 00 00-00 00 00 00 60 72 47 c7  ............`rG.
    ffffb780`b7eee6b4  8e c9 ff ff a0 e7 ee b7-80 b7 ff ff f0 e6 ee b7  ................
    ffffb780`b7eee6c4  80 b7 ff ff ca 59 49 e0-0e f8 ff ff 00 00 00 00  .....YI.........
    ffffb780`b7eee6d4  00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00  ....(...........
    

または、ウォッチ ウィンドウまたはローカル ウィンドウでメモリの内容を変更することもできます。 ウォッチ ウィンドウでは、現在のフレームのコンテキストから外れている変数が表示される場合があります。 コンテキスト内にない場合、変更は関係ありません。

セクション 13: WinDbg セッションを終了する

<-ホスト システム上

デバッガーをアタッチしたままでターゲットで作業する場合は、ターゲット コンピューターがホスト コンピューター デバッガーに接続しないように、 bc *を使用してブレークポイントをクリアします。 次に、 g コマンドを使用して、ターゲット コンピューターをもう一度実行します。

デバッグ セッションを終了するには、ホスト システムでデバッガーに中断し、 qd (終了およびデタッチ) コマンドを入力するか、メニューから [ デバッグの停止 ] を選択します。

0: kd> qd

詳細については、デバッグ リファレンス ドキュメント の WinDbg (クラシック) でのデバッグ セッションの終了 を参照してください。

セクション 14: Windows デバッグ リソース

Windows のデバッグに関する追加情報を参照してください。 これらの書籍の一部では、Windows Vista などの古いバージョンの Windows が使用されますが、説明されている概念はほとんどのバージョンの Windows に適用されることに注意してください。

書物

  • Mario Hewardt と Daniel Pravat による高度な Windows デバッグ

  • Windowsデバッグの内側: Tarik SoulamiによるWindows®デバッグとトレース戦略の実用ガイド

  • Windows Internals 著 パベル・ヨシフォビッチ、アレックス・イオネスク、マーク・ルッシノビッチ、デビッド・ソロモン

ビデオ

Defrag Tools ショー WinDbg エピソード 13-29: </shows/defrag-tools/>

トレーニング業者:

OSR - https://www.osr.com/

こちらもご覧ください

Windows デバッグの概要