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

このラボでは、WinDbg カーネル デバッガーについて説明します。 WinDbg は、エコー カーネル モードのサンプル ドライバー コードをデバッグするために使用されます。

ラボの目的

このラボには、デバッグ ツールの導入、一般的なデバッグ コマンドの説明、ブレーク ポイントの使用の説明、デバッグ拡張機能の使用を示す演習が含まれています。

このラボでは、ライブ カーネル デバッグ接続を使用して次の情報を確認します。

  • Windows デバッガー コマンドを使用する
  • 標準コマンドを使用する (呼び出し履歴、変数、スレッド、IRQL)
  • 高度なドライバー デバッグ コマンドを使用する (!コマンド)
  • シンボルを使用する
  • ライブ デバッグでブレークポイントを設定する
  • 呼び出し履歴を表示する
  • デバイス ツリープラグ アンド プレイ表示する
  • スレッドとプロセスのコンテキストを使用する

Windows デバッガーを使用する場合、実行できるデバッグには、ユーザー モードまたはカーネル モードのデバッグの 2 種類があります。

ユーザー モード - アプリケーションとサブシステムは、ユーザー モードでコンピューター上で実行されます。 ユーザー モードで実行されるプロセスは、独自の仮想アドレス空間内で実行されます。 システムハードウェア、使用のために割り当てられていないメモリ、システムの整合性を損なう可能性があるシステムの他の部分など、システムの多くの部分への直接アクセスが制限されています。 ユーザー モードで実行されるプロセスは、システムや他のユーザー モード プロセスから効果的に分離されます。ため、これらのリソースに干渉することはできません。

カーネル モード - カーネル モードは、オペレーティング システムと特権プログラムが実行されるプロセッサ アクセス モードです。 カーネル モード コードは、システムの任意の部分にアクセスするためのアクセス許可を持ち、ユーザー モード コードのように制限されません。 ユーザー モードまたはカーネル モードで実行されている他のプロセスの任意の部分にアクセスできます。 コア OS 機能と多くのハードウェア デバイス ドライバーの多くは、カーネル モードで実行されます。

このラボでは、カーネル モードのデバッグに重点を置きます。これは、多くのデバイス ドライバーをデバッグするために使用される方法です。

この演習では、ユーザー モードとカーネル モードの両方のデバッグ中に頻繁に使用されるデバッグ コマンドについて説明します。 この演習では、カーネル モードのデバッグに使用されるデバッグ拡張機能 ("!commands" とも呼ばれる) も対象とします。

ラボのセットアップ

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

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

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

  • Visual Studio
  • Windows 10 用 Windows ソフトウェア開発キット (SDK)
  • Windows Driver Kit (WDK) (WDK) for Windows 10
  • テスト用のサンプル エコー ドライバー Windows 10

ラボには、次の 11 個のセクションがあります。

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

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

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

このラボでは、2 つの PC を使用します。 Windows デバッガーはホスト システム で実行 され、KMDF エコー ドライバーはターゲット システムで 実行 されます。

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

二重矢印で接続された 2 つの PC。

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

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

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

<- ホスト システム上

  1. ホスト システムでコマンド プロンプトを開き 、「ipconfig」と入力 して IP アドレスを確認します。
C:\>ipconfig
Windows IP Configuration
Ethernet adapter Ethernet:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b%3
   Autoconfiguration IPv4 Address. . : 169.182.1.1
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . :
  1. ホスト システムの IP アドレスを記録します。 ______________________________________

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

  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

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

重要

BCDEdit を使用してブート情報を変更する前に、テスト PC で BitLocker やセキュア ブートなどの Windows セキュリティ機能を一時的に中断する必要がある場合があります。 テストが完了したら、これらのセキュリティ機能を再び有効にし、セキュリティ機能が無効になっているときにテスト PC を適切に管理します。

  1. ターゲット コンピューターで、管理者としてコマンド プロンプト ウィンドウを開きます。 デバッグを有効にするには、次のコマンドを入力します。

    C:\> bcdedit /set {default} DEBUG YES
    
  2. テスト署名を有効にするには、次のコマンドを入力します。

    C:\> bcdedit /set TESTSIGNING ON 
    
  3. ホスト システムの IP アドレスを設定するには、次のコマンドを入力します。 前に記録したホスト システムの IP アドレスを使用します。表示された IP アドレスは使用されません。

    C:\> bcdedit /dbgsettings net hostip:192.168.1.1 port:50000 key:2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    

警告 接続のセキュリティを強化し、ランダムなクライアント デバッガー接続要求のリスクを軽減するには、自動生成されたランダム キーの使用を検討してください。 詳細については 、「KDNET ネットワーク カーネル の自動デバッグの設定」を参照してください

  1. このコマンドを入力して、dbgsettings が正しく設定されていることを確認します。

    C:\> bcdedit /dbgsettings
    key                     2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    debugtype               NET
    hostip                  169.168.1.1
    port                    50000
    dhcp                    Yes
    The operation completed successfully.
    

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

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

Windows セキュリティ アラート - Windows ファイアウォールによって、このアプリの一部の機能がブロックされています。

<- ホスト システム上

  1. ホスト コンピューターで、管理者としてコマンド プロンプト ウィンドウを開きます。 Windows キットのインストールの一部としてインストールされた WinDbg.exe (WDK) の x64 バージョンの Windows Driver Kit (WDK) を使用します。 既定では、この場所に表示されます。

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

注意

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

  1. 次のコマンドを使用して、リモート ユーザー デバッグを使用して WinDbg を起動します。 キーとポートの値は、ターゲットの BCDEdit を使用して前に設定した値と一致します。

    WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    

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

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

<-ホスト システム上

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

Microsoft (R) Windows Debugger Version 10.0.17074.1002 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

Using NET for debugging
Opened WinSock 2.0
Waiting to reconnect...
Connected to target 169.182.1.1 on port 50005 on local IP 169.182.1.2
You can get the target MAC address by running .kdtargetmac command.
Connected to Windows 10 16299 x64 target at (Wed Feb 28 17:16:23.051 2018 (UTC - 8:00)), ptr64 TRUE
Kernel Debugger connection established.  (Initial Breakpoint requested)
Symbol search path is: srv*
Executable search path is: 
Windows 10 Kernel Version 16299 MP (4 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 16299.15.amd64fre.rs3_release.170928-1534
Machine Name:
Kernel base = 0xfffff800`9540d000 PsLoadedModuleList = 0xfffff800`95774110
Debug session time: Wed Feb 28 17:16:23.816 2018 (UTC - 8:00)
System Uptime: 0 days 0:00:20.534

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

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

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

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

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

<- ホスト システム上

.prefer dml を使用してデバッガー マークアップ言語 (DML) _ を有効にする

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

  1. WinDBg で Ctrl + Break (スクロール ロック) を使用して、ターゲット システムで実行されているコードを分割します。 ターゲット システムが応答するには少し時間がかかる場合があります。

ライブ カーネル接続からのコマンド ウィンドウ出力を示す Windows デバッガー。

  1. 次のコマンドを入力して、[デバッガー] ウィンドウで 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 ( 読み込まれたモジュールの一覧表示) コマンドを入力して、読み込まれたモジュールを表示することで、適切なカーネル モード プロセスを使用しているのを確認できます。
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
...

省略された出力は"... で示されます。 このラボの " 。

  1. 特定のモジュールに関する詳細情報を要求するには、次に示すように v (verbose) オプションを使用します。
0: Kd> lm v m tcpip
Browse full module list
start             end                 module name
fffff801`09eeb000 fffff801`0a157000   tcpip      (no symbols)           
    Loaded symbol image file: tcpip.sys
    Image path: \SystemRoot\System32\drivers\tcpip.sys
    Image name: tcpip.sys
    Browse all global symbols  functions  data
    Timestamp:        Sun Nov 09 18:59:03 2014 (546029F7)
    CheckSum:         00263DB1
    ImageSize:        0026C000
    Translations:     0000.04b0 0000.04e4 0409.04b0 0409.04e4

Unable to enumerate user-mode unloaded modules, Win32 error 0n30
  1. シンボル パスと読み込まれたシンボルをまだ設定していないので、デバッガーでは限られた情報を使用できます。

セクション 3: KMDF エコー ドライバーをダウンロードしてビルドする

セクション 3 では、KMDF エコー ドライバーをダウンロードしてビルドします。

通常、WinDbg を使用する場合は、独自のドライバー コードを使用します。 WinDbg 操作を理解するために、KMDF テンプレート "Echo" サンプル ドライバーが使用されます。 ソース コードを使用すると、WinDbg に表示される情報を理解しやすくなります。 さらに、このサンプルは、ネイティブ カーネル モード コードを 1 ステップ実行する方法を示す場合に使用します。 この手法は、複雑なカーネル モード コードの問題をデバッグする場合に非常に役立つ場合があります。

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

  1. GitHub から KMDF Echo サンプルをダウンロードして抽出する

    ブラウザーを使用して、GitHub のエコー サンプルを次の場所で表示できます。

    https://github.com/Microsoft/Windows-driver-samples/tree/master/general/echo/kmdf

    サンプルについては、次の記事を参照してください。

    https://github.com/microsoft/Windows-driver-samples/blob/master/general/echo/kmdf/README.md

    Windows ドライバーのサンプルはすべて、こちらから参照できます。

    https://github.com/Microsoft/Windows-driver-samples

    KMDF エコー サンプルは、general フォルダーにあります。

    一般的なフォルダーとダウンロード zip ボタンが強調表示されている github windows-driver-samples。

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

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

    b. ローカル ハード master.zipファイルをダウンロードします。

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

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

    C: \ DriverSamples \ の一般的 \ なエコー \ kmdf

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

    このMicrosoft Visual Studio[ファイルを開くプロジェクト/ソリューション...] を選択し、抽出されたファイルを含むフォルダーに移動します > > (例: C: \ DriverSamples 一般的なエコー \ \ \ kmdf)。 kmdfecho ソリューション ファイルを ダブルクリックして開きます。

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

    visual studio。device.c ファイルが kmdfecho プロジェクトから読み込まれています。

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

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

  4. ランタイム ライブラリを設定する

    ランタイム ライブラリを設定する - エコー ドライバーのプロパティ ページを開き 、C/C++ コード生成 を > 見つける。 ランタイム ライブラリを DLL バージョンから DLL 以外のバージョンに変更します。 この設定を行わずに、MSVC ランタイムをターゲット コンピューターに個別にインストールする必要があります。

    ランタイム ライブラリ設定が強調表示されている echo プロパティ ページ。

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

    また、ドライバーのプロパティで、[ドライバー署名署名 モード] が > [ テスト 署名] に設定されている必要があります。 Windows ではドライバーの署名が必要なので、これは必須です。

    署名モード設定が強調表示されている echo プロパティ ページ。

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

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

    すべてが問題ない場合は、3 つのプロジェクトすべてでビルドが成功したことを示すメッセージがビルド ウィンドウに表示されます。

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

    [エクスプローラー、サンプル用に抽出されたファイルを含むフォルダーに移動します。 たとえば、先に指定したフォルダーである 場合は、C: \ DriverSamples の一般的なエコー \ \ \ kmdf に移動します。 そのフォルダー内のコンパイル済みドライバー ファイルの場所は、 で選択した構成とプラットフォーム設定によって異 構成マネージャー。 たとえば、既定の設定を変更しないままにした場合、コンパイルされたドライバー ファイルは \ 、64 \ ビットのデバッグ ビルドの x64 Debug という名前のフォルダーに保存されます。

    自動同期ドライバー用にビルドされたファイルが格納されているフォルダーに移動します。

    C: \DriverSamples \ 一般的 \ な \ エコー kmdf ドライバー \ \ AutoSync \ x64 \ デバッグ

    フォルダーには、次のファイルが含まれている必要があります。

    ファイル 説明
    Echo.sys ドライバー ファイル。
    Echo.inf ドライバーのインストールに必要な情報を含む情報 (INF) ファイル。

    さらに、echoapp.exeファイルがビルドされ、C: DriverSamples の一般的なエコー \ \ \ \ kmdf exe \ \ x64 \ Debug に置く必要があります

    ファイル 説明
    EchoApp.exe ドライバーと通信するコマンド プロンプト実行可能テスト ファイルecho.sysします。
  8. USB サム ドライブを見つけるか、ネットワーク共有を設定して、ビルドされたドライバー ファイルとテスト EchoApp をホストからターゲット システムにコピーします。

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

セクション 4: ターゲット システムに KMDF エコー ドライバー サンプルをインストールする

セクション 4 では、devcon を使用してエコー サンプル ドライバーをインストールします。

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

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

テスト署名済みドライバーを展開する前に、テスト署名を有効にすることでターゲット コンピューターを準備する必要があります。 また、WDK インストールで DevCon ツールを見つけて、ターゲット システムにコピーする必要があります。

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

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

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

テスト署名済みドライバーを実行する機能を有効にする:

a. [Windows の設定] を開きます。

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

c. [高度なスタートアップ] で、[今すぐ 再起動] を選択します

d. PC が再起動したら、[スタートアップ オプション] を選択します。 [スタートWindows 10オプションのトラブルシューティング ] [ スタートアップ設定] の順に > > 選択 し、[再起動] ボタンを選択します。

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

f. ターゲット コンピューターを再起動します。

<- ホスト システム上

WDK インストールの [ツール] フォルダーに移動し、DevCon ツールを探します。 たとえば、次のフォルダーを探します。

C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe

ビルドされたドライバー パッケージのターゲットにフォルダーを作成します (例: C: \ EchoDriver)。 ターゲット devcon.exeコピーします。 ホスト システムで .cer 証明書を探します。これは、ビルドされたドライバー ファイルが格納されているフォルダー内のホスト コンピューター上の同じフォルダーにあります。 ホスト コンピューターで前述したビルドされたドライバーからすべてのファイルをコピーし、ターゲット コンピューターで作成したのと同じフォルダーに保存します。

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

ターゲット コンピューターで、証明書ファイルを長押し (または右クリック) し、[インストール] を選択し、指示に従ってテスト証明書をインストールします。

ターゲット コンピューターを設定するための詳細な手順が必要な場合は、「ドライバーの手動展開用にコンピューターを準備する 」を参照してください

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

ドライバーのインストール

次の手順では、サンプル ドライバーをインストールしてテストする方法を示します。 ここで示しているのは、ドライバーのインストールに使う devcon ツールの一般的な構文です。

devcon install <INF ファイル> <ハードウェア ID>

このドライバーのインストールに必要な INF ファイルは echo.inf です。 inf ファイルには、 ファイルをインストールするハードウェア ID echo.sys。 エコー サンプルの場合、ハードウェア ID は ルート \ ECHO です

ターゲット コンピューターで、管理者としてコマンド プロンプト ウィンドウを開きます。 ドライバー パッケージ フォルダーに移動し、次のコマンドを入力します。

devcon install echo.inf root \ECHO devcon が認識されないというエラー メッセージが表示される場合は 、devcon ツールにパスを追加してみてください。 たとえば 、C: \ Tools というフォルダーにコピーした場合は、次のコマンドを使用してみてください。

c: \ tools \ devcon install echo.inf root \ ECHO テスト ドライバーが署名されていないドライバーであることを示すダイアログ ボックスが表示されます。 [かまわず続行] を選択して続行します。

Windows セキュリティ警告 - Windows では、このドライバー ソフトウェアの発行元を確認できない。

ヒント

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

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

デバイスでドライバーを調デバイス マネージャー

ターゲット コンピューターのコマンド プロンプト ウィンドウで 、「devmgmt open デバイス マネージャー」と入力します。 [デバイス マネージャー] メニューの [種類別のデバイス] を選択します。 デバイス ツリーで、[サンプル デバイス] ノードで [ サンプル WDF エコー ドライバー] を探します。

サンプル wdf エコー ドライバーが強調表示されたデバイス マネージャー ツリー。

ドライバーをテストする

「echoapp」と 入力してテスト エコー アプリを開始し、ドライバーが機能しているのを確認します。

C:\Samples\KMDF_Echo_Sample> echoapp
DevicePath: \\?\root#sample#0005#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
512 Pattern Bytes Written successfully
512 Pattern Bytes Read successfully
Pattern Verified successfully
30720 Pattern Bytes Written successfully
30720 Pattern Bytes Read successfully
Pattern Verified successfully

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

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

次の手順を実行して、ドライバーに関する情報を表示します。

<-ホスト システム上

  1. デバッガーを閉じた場合は、管理者コマンド プロンプト ウィンドウで次のコマンドを使用して再度開きます。

    WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Ctrl + Break (スクロール ロック) を使用して、ターゲット システムで実行されているコードを分割します。

シンボル パスの設定

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

    0: kd> .symfix
    
  2. ローカル シンボルを使用するローカル シンボルの場所を追加するには、 .reload /f を使用してパスを追加します。

    0: kd> .sympath+ C:\DriverSamples\general\echo\kmdf
    0: kd> .reload /f
    

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

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 を構成できます。 このチュートリアルでは、このアプローチを使用する必要があります。 環境内のシンボルが別の場所にある場合は、その場所を使用する手順を変更します。 詳細については、「シンボル ストアと シンボル サーバー」を参照してください

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

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

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

set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
  1. デバッガーのコマンド領域に次のコマンドを入力して、エコー ドライバーに関する情報を表示します。

    0: kd> lm m echo* v
    Browse full module list
    start             end                 module name
    fffff801`4ae80000 fffff801`4ae89000   ECHO       (private pdb symbols)  C:\Samples\KMDF_ECHO_SAMPLE\echo.pdb
        Loaded symbol image file: ECHO.sys
        Image path: \SystemRoot\system32\DRIVERS\ECHO.sys
        Image name: ECHO.sys
    ...  
    

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

  2. [prefer dml =1 earlier]/(dml =1 を優先する)を以前に設定したので、出力の一部の要素は選択できる _ ホット リンクです。 デバッグ出力 の [すべてのグローバル シンボルを 参照] リンクを選択すると、文字 "a" で始まる項目シンボルに関する情報が表示されます。

    0: kd> x /D Echo!a*
    
  3. 結局のところ、エコー サンプルには文字 "a" で始まるシンボルが含まれているので、「」と入力して、Echo で始まるエコー ドライバーに関連付けられているすべてのシンボルに関する情報を表示します。 x ECHO!Echo*

    0: kd> x ECHO!Echo*
    fffff801`0bf95690 ECHO!EchoEvtIoQueueContextDestroy (void *)
    fffff801`0bf95000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *)
    fffff801`0bf95ac0 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *)
    fffff801`0bf9b120 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *)
    ...
    

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

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

    0: kd> !lmi echo
    Loaded Module Info: [echo] 
             Module: ECHO
       Base Address: fffff8010bf94000
         Image Name: ECHO.sys
    … 
    
  5. !dh 拡張子を使用して、次に示すようにヘッダー情報を表示します。

    0: kd> !dh echo
    
    File Type: EXECUTABLE IMAGE
    FILE HEADER VALUES
         14C machine (i386)
           6 number of sections
    54AD8A42 time date stamp Wed Jan 07 11:34:26 2015
    ...
    
  6. デバッグ マスクの設定

    次のコマンドを入力して、ターゲット システムのすべてのデバッグ メッセージがデバッガーに表示される既定のデバッグ ビット マスクを変更します。

    0: kd> ed nt!Kd_DEFAULT_MASK  0xFFFFFFFF
    

    一部のドライバーでは、マスクが使用されている場合に追加情報0xFFFFFFFF表示されます。 表示される情報0x00000000量を減らす場合は、マスクを [マスク] に設定します。

    0: kd> ed nt!Kd_DEFAULT_MASK  0x00000000
    

    dd コマンドを使用して、すべてのデバッガー メッセージを表示するためにマスクが設定されている確認を表示します。

    0: kd> dd nt!kd_DEFAULT_MASK 
    fffff802`bb4057c0  ffffffff 00000000 00000000 00000000
    fffff802`bb4057d0  00000000 00000000 00000000 00000000
    fffff802`bb4057e0  00000001 00000000 00000000 00000000
    fffff802`bb4057f0  00000000 00000000 00000000 00000000
    fffff802`bb405800  00000000 00000000 00000000 00000000
    fffff802`bb405810  00000000 00000000 00000000 00000000
    fffff802`bb405820  00000000 00000000 00000000 00000000
    fffff802`bb405830  00000000 00000000 00000000 00000000
    

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

セクション 6 では、エコー サンプル デバイス ドライバーと、そのデバイス ツリー内の場所に関するプラグ アンド プレイ表示します。

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

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

<-ホスト システム上

  1. デバイス ツリー内のすべてのデバイス ノードを プラグ アンド プレイ!devnode 0 1 コマンドを入力 します。

    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. Ctrl + F キーを使用して、生成された出力を検索してデバイス ドライバーの名前を検索します。エコー。

    検索するエコーという用語を示す [検索] ダイアログ ボックス。

  3. エコー デバイス ドライバーを読み込む必要があります。 !devnode 0 1 echo コマンドを使用して、次プラグ アンド プレイエコー デバイス ドライバーに関連付けられている情報を表示します。

    0: Kd> !devnode 0 1 echo
    Dumping IopRootDeviceNode (= 0xffffe0007b725d30)
    DevNode 0xffffe0007b71a630 for PDO 0xffffe0007b71a960
      InstancePath is "ROOT\SAMPLE\0000"
      ServiceName is "ECHO"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
    …
    
  4. 前のコマンドに表示される出力には、ドライバーの実行中のインスタンスに関連付けられている PDO が含まれています。この例では、が0xffffe0007b71a960。 !devobj < PDO address > コマンドを入力して、エコー プラグ アンド プレイ関連付けられている情報を表示します。 ここに示すのではなく 、!devnode によって PC に表示される PDO アドレスを使用します。

    0: kd> !devobj 0xffffe0007b71a960
    Device object (ffffe0007b71a960) is for:
     0000000e \Driver\PnpManager DriverObject ffffe0007b727e60
    Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040
    Dacl ffffc102c9b36031 DevExt 00000000 DevObjExt ffffe0007b71aab0 DevNode ffffe0007b71a630 
    ExtensionFlags (0x00000800)  DOE_DEFAULT_SD_PRESENT
    Characteristics (0x00000180)  FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
    AttachedDevice (Upper) ffffe000801fee20 \Driver\ECHO
    Device queue is not busy.
    
  5. !devnode 0 1 コマンドに表示される出力には、ドライバーの実行中のインスタンスに関連付けられている PDO アドレスが含まれています。この例では、 0xffffe0007b71a960。 !devstack < PDO address > コマンドを入力して、デバイス プラグ アンド プレイ関連付けられている情報を表示します。 !devnode によって PC に表示される PDO アドレスを使用します。次に示すアドレスは使用できません。

    0: kd> !devstack 0xffffe0007b71a960
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe000801fee20  \Driver\ECHO       ffffe0007f72eff0  
    > ffffe0007b71a960  \Driver\PnpManager 00000000  0000000e
    !DevNode ffffe0007b71a630 :
      DeviceInst is "ROOT\SAMPLE\0000"
      ServiceName is "ECHO"
    

出力には、非常に単純なデバイス ドライバー スタックが表示されます。 エコー ドライバーは PnPManager ノードの子です。 PnPManager はルート ノードです。

\Driver\ECHO

\Driver\PnpManager

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

約 20 ノードのデバイス ノード ツリー。

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

セクション 7: ブレークポイントとソース コードの操作

セクション 7 では、ブレークポイントを設定し、カーネル モードのソース コードを 1 ステップ実行します。

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

コードをステップ実行し、変数の値をリアルタイムで確認するには、ブレークポイントを有効にし、ソース コードへのパスを設定する必要があります。

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

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

bp

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

Bu

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

Bm

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

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

<-ホスト システム上

  1. WinDbg UI を使用して、現在の WinDbg セッションで デバッグ ソース > モードが有効になっているか確認します。

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

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

    .sympath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
    
  4. x コマンドを使用 して 、エコー ドライバーに関連付けられているシンボルを調べて、ブレークポイントに使用する関数名を決定します。 ワイルドカードまたは Ctrl + F キーを使用して 、DeviceAdd 関数名を 検索できます。

    0: kd> x ECHO!EchoEvt*
    8b4c7490          ECHO!EchoEvtIoQueueContextDestroy (void *)
    8b4c7000          ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *)
    8b4c7820          ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *)
    8b4cb0e0          ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *)
    8b4c75d0          ECHO!EchoEvtIoWrite (struct WDFQUEUE__ *, struct WDFREQUEST__ *, unsigned int)
    8b4cb170          ECHO!EchoEvtDeviceAdd (struct WDFDRIVER__ *, struct 
    …
    

    上記の出力は、 エコー ドライバーの DeviceAdd メソッドが ECHO であるのを 示しています。EchoEvtDeviceAdd

    または、ソース コードを確認して、ブレークポイントの目的の関数名を見つける方法があります。

  5. ドライバーの名前を使用して bm コマンドを使用してブレークポイントを設定し、その後に、ブレークポイントを設定する関数名 (AddDevice など) を感嘆符で区切って設定します。 AddDevice を使用して、読み込まれているドライバーを監視します。

    0: kd> bm ECHO!EchoEvtDeviceAdd
      1: fffff801`0bf9b1c0 @!"ECHO!EchoEvtDeviceAdd"
    

    注:
    module! のような変数の設定と組み合わせて、異なる構文を < 使用できます > 。 <symbol > 、 < class > :: method < > ,' < file.cpp : 行番号 '、または回数条件 を > < > スキップ < します > < # > 。 詳細については、「WinDbg および他の Windows デバッガーの条件付きブレークポイント 」を参照してください

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

    0: kd> bl
    1 e fffff801`0bf9b1c0     0001 (0001) ECHO!EchoEvtDeviceAdd
    

    上記の出力の "e" は、ブレークポイント番号 1 が発生可能な状態を示しています。

  7. go コマンド g を入力して、ターゲット システムでコードの 実行を 再開 します

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

    Windows で、アイコンを **デバイス マネージャー、**または「mmc devmgmt.msc」 と入力して、次のコマンドを開きます。 [サンプルデバイス マネージャー] ノードを 展開 します。

  9. KMDF Echo ドライバー エントリを長押し (または右クリック) し、メニューから [無効] を選択します。

  10. KMDF Echo ドライバー エントリを長押し (または右クリック) し、メニューから [有効 にする] を選択します。

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

    ドライバーが有効になっていると 、AddDevice デバッグ ブレークポイントが起動し、ターゲット システムでのドライバー コードの実行が停止します。 ブレークポイントにヒットすると、AddDevice ルーチンの最初に実行 を停止する必要 があります。 デバッグ コマンドの出力に "ブレークポイント 1 ヒット" が表示されます。

    サンプル コードのローカルウィンドウとコマンド ウィンドウを示す windbg。

  12. コードを 1 行でステップ実行するには 、p コマンドを入力するか 、AddDevice ルーチンの次の末尾に到達するまで F10 キーを押します。 次に示すように、中かっこ文字 "}" が強調表示されます。

    adddevice ルーチンの開始時に強調表示されている中かっこの文字を示すコード ウィンドウ。

  13. 次のセクションでは、DeviceAdd コードが実行された後の変数の状態を確認します。

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

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

bl

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

紀元 前

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

Bd

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

Bve

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

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

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

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

ba <access> <size> <address> {options}
オプション 説明

e

execute (CPU がアドレスから命令をフェッチする場合)

r

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

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

任意の時点で4つのデータブレークポイントのみを設定できます。また、データを適切に配置していることを確認するか、ブレークポイントをトリガーしないようにします (単語は2に割り切れ、dword は4で割り切れる必要があり、quadwords は0または8になります)。

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

ba r 4 0x0003f7bf0

注:
デバッガーからのコードのステップ実行コマンドウィンドウ

コードをステップ実行するために使用できるコマンドを次に示します (関連するキーボードショートカットをかっこ内に示します)。

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

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

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

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

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

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

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

セクション 8: 変数と呼び出し履歴の表示

セクション8では、変数と呼び出し履歴に関する情報を表示します。

このラボでは、前に説明したプロセスを使用して、 AddDevice ルーチンで停止していることを前提としています。 出力例を表示するには、必要に応じて、前述の手順を繰り返します。

<-ホストシステム上

変数の表示

ローカル > 変数を表示するには、[ローカル の表示] メニュー項目を使用します。

windbg ローカル変数ウィンドウ。

グローバル変数

グローバル変数アドレスの場所は、「?」と入力すると確認できます 。 <変数名 >

ローカル変数

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

0: kd> dv
         Driver = 0x00001fff`7ff9c838
     DeviceInit = 0xffffd001`51978190
         status = 0n0

呼び出し履歴

注:
呼び出し履歴は、プログラムカウンターの現在の場所に led がある関数呼び出しのチェーンです。 呼び出し履歴の一番上の関数は現在の関数であり、次の関数は、現在の関数を呼び出した関数です。

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

kb

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

kp

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

kn

を使用すると、その隣にあるフレーム情報を含むスタックを表示できます。

<-ホストシステム上

  1. 呼び出し履歴を使用可能な状態にしたままにする場合は、[呼び出し履歴の 表示] を選択し > て表示します。 ウィンドウの上部にある列を選択して、追加情報の表示を切り替えます。

windbg 表示呼び出し履歴ウィンドウ。

  1. 破損状態のサンプルアダプターコードをデバッグしているときに、 kn コマンドを使用して呼び出し履歴を表示します。
3: kd> kn
# Child-SP          RetAddr           Call Site
00 ffffd001`51978110 fffff801`0942f55b ECHO!EchoEvtDeviceAdd+0x66 [c:\Samples\kmdf echo sample\c++\driver\autosync\driver.c @ 138]
01 (Inline Function) --------`-------- Wdf01000!FxDriverDeviceAdd::Invoke+0x30 [d:\wbrtm\minkernel\wdf\framework\shared\inc\private\common\fxdrivercallbacks.hpp @ 61]
02 ffffd001`51978150 fffff801`eed8097d Wdf01000!FxDriver::AddDevice+0xab [d:\wbrtm\minkernel\wdf\framework\shared\core\km\fxdriverkm.cpp @ 72]
03 ffffd001`51978570 fffff801`ef129423 nt!PpvUtilCallAddDevice+0x35 [d:\9142\minkernel\ntos\io\pnpmgr\verifier.c @ 104]
04 ffffd001`519785b0 fffff801`ef0c4112 nt!PnpCallAddDevice+0x63 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 7397]
05 ffffd001`51978630 fffff801`ef0c344f nt!PipCallDriverAddDevice+0x6e2 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 3390]
...

呼び出し履歴には、カーネル (nt) がプラグアンドプレイコード (PnP) に呼び出されたことが示されます。これは、その後 echo driver Deviceadd 関数を呼び出した driver framework CODE (WDF) と呼ばれます。

セクション 9: プロセスとスレッドの表示

プロセス

セクション9では、カーネルモードで実行されているプロセスとスレッドに関する情報を表示します。

注:
プロセス情報は、 ! プロセス デバッガー拡張機能を使用して表示または設定できます。 サウンドが再生されるときに使用されるプロセスを調べるために、ブレークポイントを設定します。

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

    Dv コマンドを入力して、 EchoEvtIo ルーチンに関連付けられているロケール変数を確認します。

    0: kd> dv ECHO!EchoEvtIo*
    ECHO!EchoEvtIoQueueContextDestroy
    ECHO!EchoEvtIoWrite
    ECHO!EchoEvtIoRead         
    
  2. Bc * を使用して、前のブレークポイントをクリアします。

    0: kd> bc *  
    
    1. 次のコマンドを使用して、 EchoEvtIo ルーチンにシンボルのブレークポイントを設定します。
    0: kd> bm ECHO!EchoEvtIo*
      2: aade5490          @!”ECHO!EchoEvtIoQueueContextDestroy”
      3: aade55d0          @!”ECHO!EchoEvtIoWrite”
      4: aade54c0          @!”ECHO!EchoEvtIoRead”
    
  3. ブレークポイントを一覧表示して、ブレークポイントが適切に設定されていることを確認します。

    0: kd> bl
    1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197]    0001 (0001) ECHO!EchoEvtIoQueueContextDestroy
    ...
    
  4. コードの実行を再開するには、「 g 」と入力します。

    0: kd> g
    
  5. -> ターゲットシステム上

    ターゲットシステムで EchoApp.exe driver テストプログラムを実行します。

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

    テストアプリを実行すると、ドライバーの i/o ルーチンが呼び出されます。 これにより、ブレークポイントが起動され、ターゲットシステムでのドライバーコードの実行が停止します。

    Breakpoint 2 hit
    ECHO!EchoEvtIoWrite:
    fffff801`0bf95810 4c89442418      mov     qword ptr [rsp+18h],r8
    
  7. echoapp.exe の実行に関係している現在のプロセスを表示するには、 ! process コマンドを使用します。

    0: kd> !process
    PROCESS ffffe0007e6a7780
        SessionId: 1  Cid: 03c4    Peb: 7ff7cfec4000  ParentCid: 0f34
        DirBase: 1efd1b000  ObjectTable: ffffc001d77978c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000802c79f0 Vads 30 Clone 0 Private 135. Modified 5. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf270050
        ElapsedTime                       00:00:00.052
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (682, 50, 345) (2728KB, 200KB, 1380KB)
        PeakWorkingSetSize                652
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    688
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe00080e32080  Cid 03c4.0ec0  Teb: 00007ff7cfece000 Win32Thread: 0000000000000000 RUNNING on processor 1
    

    出力には、プロセスがドライバー書き込みイベントのブレークポイントにヒットしたときに実行されていた echoapp.exe に関連付けられていることが示されています。 詳細については、「 ! process」を参照してください。

  8. すべてのプロセスの概要情報を表示するには、 ! process 0 0 を使用します。 出力で、CTRL キーを押しながら F キーを押して、echoapp.exe イメージに関連付けられているプロセスと同じプロセスアドレスを検索します。 次に示す例では、プロセスのアドレスは ffffe0007e6a7780 です。

    ...
    
    PROCESS ffffe0007e6a7780
        SessionId: 1  Cid: 0f68    Peb: 7ff7cfe7a000  ParentCid: 0f34
        DirBase: 1f7fb9000  ObjectTable: ffffc001cec82780  HandleCount:  34.
        Image: echoapp.exe
    
    ...
    
  9. このラボで後で使用するために echoapp.exe に関連付けられているプロセス ID を記録します。 CTRL + C キーを使用して、後で使用するためにアドレスをコピーバッファーにコピーすることもできます。

    _____________________________________________________(echoapp.exe プロセスアドレス)

  10. echoapp.exe が実行を終了するまでコードを実行するには、必要に応じて「 g 」をデバッガーに入力します。 読み取りと書き込みイベントのブレークポイントが回数回ヒットします。 echoapp.exe が終了したら、CTRL + ScrLk (Ctrl + Break) キーを押してデバッガーを中断します。

  11. 現在、別のプロセスが実行されていることを確認するには、 ! process コマンドを使用します。 次に示す出力では、Image 値が System のプロセスが Echo Image 値と異なります。

    1: kd> !process
    PROCESS ffffe0007b65d900
        SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
        DirBase: 001ab000  ObjectTable: ffffc001c9a03000  HandleCount: 786.
        Image: System
        VadRoot ffffe0007ce45930 Vads 14 Clone 0 Private 22. Modified 131605. Locked 64.
        DeviceMap ffffc001c9a0c220
        Token                             ffffc001c9a05530
        ElapsedTime                       21:31:02.516
    ...
    

    上記の出力は、OS を停止したときに、システムプロセス ffffe0007b65d900 が実行されていたことを示しています。

  12. ここで、 ! process コマンドを使用して、前に記録した echoapp.exe に関連付けられているプロセス ID を確認します。 次に示すプロセスアドレスの例ではなく、先ほど記録した echoapp.exe プロセスアドレスを指定します。

    0: kd> !process ffffe0007e6a7780
    TYPE mismatch for process object at 82a9acc0
    

    echoapp.exe プロセスが実行されなくなったため、プロセスオブジェクトは使用できなくなりました。

レッド

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

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

    デバッガーに g を入力して、ターゲットシステムでコードの実行を再開します。

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

    ターゲットシステムで EchoApp.exe driver テストプログラムを実行します。

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

    ブレークポイントにヒットすると、コードの実行は停止します。

    Breakpoint 4 hit
    ECHO!EchoEvtIoRead:
    aade54c0 55              push    ebp
    
  4. 実行中のスレッドを表示するには、「 ! thread」と入力します。 次のような情報が表示されます。

    0: kd>  !thread
    THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    IRP List:
        ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0008096c900       Image:         echoapp.exe
    ...
    

    echoapp.exe のイメージ名をメモしておきます。これは、テストアプリに関連付けられているスレッドを調べていることを示しています。

    1. ! Process コマンドを使用して、これが echoapp.exe に関連付けられているプロセスで実行されている唯一のスレッドであるかどうかを確認します。 プロセスで実行されているスレッドのスレッド番号は、! thread コマンドを表示したスレッドと同じスレッドであることに注意してください。
    0: kd> !process
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf5dc050
        ElapsedTime                       00:00:00.048
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (681, 50, 345) (2724KB, 200KB, 1380KB)
        PeakWorkingSetSize                651
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    686
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    
  5. ! Process 0 0 コマンド を使用して、関連する2つのプロセスのプロセスアドレスを検索し、これらのプロセスアドレスをここに記録します。

    Cmd.exe: ____________________________________________________________

    EchoApp.exe: _______________________________________________________

    0: kd> !process 0 0 
    
    …
    
    PROCESS ffffe0007bbde900
        SessionId: 1  Cid: 0f34    Peb: 7ff72dfa7000  ParentCid: 0c64
        DirBase: 19c5fa000  ObjectTable: ffffc001d8c2f300  HandleCount:  31.
        Image: cmd.exe
    …
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
    …
    

    メモ また、 ! process 0 17 を使用して、すべてのプロセスに関する詳細情報を表示することもできます。 このコマンドからの出力には時間がかかる場合があります。 Ctrl キーを押しながら F キーを押すと、出力を検索できます。

  6. PC を実行している両方のプロセスのプロセス情報を一覧表示するには、 ! process コマンドを使用します。 次に示すアドレスではなく、 ! process 0 0 出力からプロセスアドレスを指定します。

    この例の出力は、前に記録された cmd.exe プロセス ID を示しています。 このプロセス ID のイメージ名は cmd.exe であることに注意してください。

    0: kd>  !process ffffe0007bbde900
    PROCESS ffffe0007bbde900
        SessionId: 1  Cid: 0f34    Peb: 7ff72dfa7000  ParentCid: 0c64
        DirBase: 19c5fa000  ObjectTable: ffffc001d8c2f300  HandleCount:  31.
        Image: cmd.exe
        VadRoot ffffe0007bb8e7b0 Vads 25 Clone 0 Private 117. Modified 20. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001d8c48050
        ElapsedTime                       21:33:05.840
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         24656
        QuotaPoolUsage[NonPagedPool]      3184
        Working Set Sizes (now,min,max)  (261, 50, 345) (1044KB, 200KB, 1380KB)
        PeakWorkingSetSize                616
        VirtualSize                       2097164 Mb
        PeakVirtualSize                   2097165 Mb
        PageFaultCount                    823
        MemoryPriority                    FOREGROUND
        BasePriority                      8
        CommitCharge                      381
    
            THREAD ffffe0007cf34880  Cid 0f34.0f1c  Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
                ffffe0008096c900  ProcessObject
            Not impersonating
    ...
    

    この例の出力は、前に記録された echoapp.exe プロセス ID を示しています。

    0: kd>  !process ffffe0008096c900
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf5dc050
        ElapsedTime                       00:00:00.048
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (681, 50, 345) (2724KB, 200KB, 1380KB)
        PeakWorkingSetSize                651
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    686
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
            IRP List:
                ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
            Not impersonating
    ...
    
  7. ここでは、2つのプロセスに関連付けられている最初のスレッドアドレスを記録します。

    Cmd.exe: ____________________________________________________

    EchoApp.exe: _________________________________________________

  8. を使用します 現在のスレッドに関する情報を表示するスレッドコマンド。

    0: kd>  !Thread
    THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    IRP List:
        ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0008096c900       Image:         echoapp.exe
    Attached Process          N/A            Image:         N/A
    ...
    

    予想どおり、現在のスレッドは echoapp.exe に関連付けられているスレッドであり、実行中の状態になります。

  9. を使用します cmd.exe プロセスに関連付けられているスレッドに関する情報を表示するスレッドコマンド。 前に記録したスレッドアドレスを指定します。

    0: kd> !Thread ffffe0007cf34880
    THREAD ffffe0007cf34880  Cid 0f34.0f1c  Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
        ffffe0008096c900  ProcessObject
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0007bbde900       Image:         cmd.exe
    Attached Process          N/A            Image:         N/A
    Wait Start TickCount      4134621        Ticks: 0
    Context Switch Count      4056           IdealProcessor: 0             
    UserTime                  00:00:00.000
    KernelTime                00:00:01.421
    Win32 Start Address 0x00007ff72e9d6e20
    Stack Init ffffd0015551dc90 Current ffffd0015551d760
    Base ffffd0015551e000 Limit ffffd00155518000 Call 0
    Priority 14 BasePriority 8 UnusualBoost 3 ForegroundBoost 2 IoPriority 2 PagePriority 5
    Child-SP          RetAddr           : Args to Child                                                           : Call Site
    ffffd001`5551d7a0 fffff801`eed184fe : fffff801`eef81180 ffffe000`7cf34880 00000000`fffffffe 00000000`fffffffe : nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109]
    ffffd001`5551d8e0 fffff801`eed17f79 : ffff03a5`ca56a3c8 000000de`b6a6e990 000000de`b6a6e990 00007ff7`d00df000 : nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347]
    ffffd001`5551d980 fffff801`eecea340 : ffffd001`5551da18 00000000`00000000 00000000`00000000 00000000`00000388 : nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619]
    ...
    

    このスレッドは cmd.exe に関連付けられており、待機状態になっています。

  10. 待機中の CMD.exe スレッドのスレッドアドレスを指定して、その待機中のスレッドにコンテキストを変更します。

    0: kd> .Thread ffffe0007cf34880
    Implicit thread is now ffffe000`7cf34880
    
  11. K コマンドを使用して、待機中のスレッドに関連付けられている呼び出し履歴を表示します。

    0: kd> k
      *** Stack trace for last set context - .thread/.cxr resets it
    # Child-SP          RetAddr           Call Site
    00 ffffd001`5551d7a0 fffff801`eed184fe nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109]
    01 ffffd001`5551d8e0 fffff801`eed17f79 nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347]
    02 ffffd001`5551d980 fffff801`eecea340 nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619]
    03 ffffd001`5551da00 fffff801`ef02e642 nt!KeWaitForSingleObject+0x2c0 [d:\9142\minkernel\ntos\ke\wait.c @ 683]
    ...
    

    KiCommitThreadWait などの呼び出し履歴要素は、このスレッドが想定どおりに実行されていないことを示します。

注:
スレッドとプロセスの詳細については、次の参照情報を参照してください。

スレッドとプロセス

コンテキストの変更

セクション 10: IRQL、登録、および WinDbg セッションの終了

保存された IRQL の表示

セクション10では、IRQL と、regsisters の内容を表示します。

<-ホストシステム上

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

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

レジスタの表示

<-ホストシステム上

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

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

または、[レジスタの 表示] を選択して、レジスタの内容を表示することもでき > ます。 詳細については、「 r (レジスタ)」を参照してください。

レジスタの内容を表示することは、アセンブリ言語コードの実行やその他のシナリオでステップ実行するときに役立ちます。 アセンブリ言語の逆アセンブリの詳細については、「 注釈付き X86 逆アセンブリ 」および「 注釈付き x64 逆アセンブル」を参照してください。

レジスタの内容の詳細については、「 X86 アーキテクチャx64 アーキテクチャ」を参照してください。

WinDbg セッションを終了しています

<-ホストシステム上

ユーザーモードのデバッグセッションを終了し、デバッガーを休止モードに戻して、ターゲットアプリケーションを再度実行するように設定するには、 qd (Quit および Detach) コマンドを入力します。

使用できるように、ターゲットコンピューターにコードを実行させるには、必ず g コマンドを使用してください。 また、 bc * を使用してブレークポイントをクリアし、対象のコンピュータが中断してホストコンピュータのデバッガーに接続しようとしないようにすることをお勧めします。

0: kd> qd

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

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

詳細については、「Windows デバッグ」を参照してください。 これらの書籍には、windows Vista などの古いバージョンの Windows を例で使用するものがありますが、ここで説明する概念は、Windows のほとんどのバージョンに適用されます。

書籍

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

  • Windows のデバッグ: Tarik Soulami による Windows®でのデバッグとトレースの方法に関する実用的なガイド

  • Windows の内部構造をマーク Russinovich、David A ソロモン、Alex Ionescu

ビデオ

デフラグツールでは、WinDbg エピソード13-29 が表示されます。 https://channel9.msdn.com/Shows/Defrag-Tools

ベンダーのトレーニング:

OSR https://www.osr.com/

関連トピック

標準的なデバッグの手法

特殊なデバッグの手法

Windows のデバッグの概要