WinDbg の概要 (カーネルモード)

WinDbg は、Windows 用デバッグ ツールに含まれているカーネルモードおよびユーザーモードのデバッガーです。 この記事では、カーネルモード デバッガーとして WinDbg の使用を開始するのに役立つ演習について説明します。

Windows 用デバッグ ツールを入手する方法については、「WinDbg Windows デバッガーをダウンロードしてインストールする」を参照してください。 デバッグ ツールをインストールしたら、64 ビット (x64) および 32 ビット (x86) バージョンのツールのインストール ディレクトリを検索します。 次に例を示します。

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

カーネル ]モードのデバッグを設定する

カーネルモード デバッグ環境には、ホスト コンピューターターゲット コンピューターの 2 台のコンピューターが通常あります。 デバッガーはホスト コンピューター上で実行され、デバッグ対象のコードはターゲット コンピューター上で実行されます。 ホストとターゲットはデバッグ ケーブルで接続されます。

Windows デバッガーでは、次の種類のケーブルがサポートされています。

  • イーサネット
  • USB 2.0/USB 3.0
  • シリアル ("null モデム" とも呼ばれます)

速度と信頼性を確保するには、イーサネット ケーブルとローカル ネットワーク ハブを使用する必要があります。 次の図は、イーサネット ケーブルを使用してデバッグするために接続されたホスト コンピューターとターゲット コンピューターを示しています。

Diagram showing host and target computers connected via Ethernet for debugging.

古いバージョンの Windows には、USB やシリアル ケーブルなどの直接ケーブルを使用するというオプションがあります。

Diagram illustrating host and target computers connected using a debug cable for debugging.

ホスト コンピューターとターゲット コンピューターの設定方法の詳細については、「カーネルモード デバッグの手動での設定」を参照してください。

仮想マシン - VM

Hyper-V 仮想マシンへのデバッガーの接続については、「仮想マシンのネットワーク デバッグの設定 - KDNET」を参照してください。

カーネルモード デバッグ セッションを確立する

ホストとターゲット コンピューターを設定し、デバッグ ケーブルで接続したら、カーネルモードデバッグ セッションを確立できます。 セットアップで使用したものと同じトピックの手順に従います。 たとえば、イーサネット経由でデバッグするためのホスト コンピューターとターゲット コンピューターを設定する場合は、次の記事でカーネル モード デバッグ セッションを確立する手順を確認できます。

WinDbg の使用を開始する

  1. ホスト コンピューターで WinDbg を開き、ターゲット コンピューターとのカーネルモード デバッグ セッションを確立します。

  2. デバッガーのドキュメント CHM ファイルを開くには、[ヘルプ] メニューに移動して [コンテンツ] を選択します。 デバッガーのドキュメントは、Windows 用デバッグ ツールでオンラインでも入手できます。

  3. カーネルモード デバッグ セッションを確立する際、WinDbg が自動的にターゲット コンピューターを中断する可能性があります。 WinDbg が中断されない場合は、[デバッグ] メニューに移動して [中断] を選択します。

  4. [WinDbg] ウィンドウの下部にあるコマンド ラインに、次のコマンドを入力します。

    .sympath srv*

    出力は次の例のようになります。

    Symbol search path is: srv*
    Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols
    

    シンボルの検索パスにより、シンボル (PDB) ファイルを検索する場所が WinDbg に指示されます。 デバッガーには、関数名や変数名など、コード モジュールに関する情報を取得するためのシンボル ファイルが必要です。

    次のコマンドを入力して、シンボル ファイルの初期検索と読み込みを行うよう WinDbg に指示します。

    .reload

  5. 読み込まれたモジュールの一覧を取得するには、次のコマンドを入力します。

    lm

    出力は次の例のようになります。

    0:000>3: kd> lm
    start             end                 module name
    fffff800`00000000 fffff800`00088000   CI         (deferred)
    ...
    fffff800`01143000 fffff800`01151000   BasicRender   (deferred)
    fffff800`01151000 fffff800`01163000   BasicDisplay  (deferred)
    ...
    fffff800`02a0e000 fffff800`03191000   nt  (pdb symbols) C:\...\ntkrnlmp.pdb
    fffff800`03191000 fffff800`03200000   hal (deferred)
    ...
    
  6. ターゲット コンピューターの実行を開始するには、次のコマンドを入力します。

    g

  7. もう一度中断するには、[デバッグ] メニューに移動して [中断] を選択します。

  8. 次のコマンドを入力して、nt モジュール内の _FILE_OBJECT データ型を調べます。

    dt nt!_FILE_OBJECT

    出力は次の例のようになります。

    0:000>0: kd> dt nt!_FILE_OBJECT
       +0x000 Type             : Int2B
       +0x002 Size             : Int2B
       +0x008 DeviceObject     : Ptr64 _DEVICE_OBJECT
       +0x010 Vpb              : Ptr64 _VPB
       ...
       +0x0c0 IrpList          : _LIST_ENTRY
       +0x0d0 FileObjectExtension : Ptr64 Void
    
  9. 次のコマンドを入力して、nt モジュール内のシンボルのいくつかを調べます。

    x nt!*CreateProcess*

    出力は次の例のようになります。

    0:000>0: kd> x nt!*CreateProcess*
    fffff800`030821cc nt!ViCreateProcessCallbackInternal (<no parameter info>)
    ...
    fffff800`02e03904 nt!MmCreateProcessAddressSpace (<no parameter info>)
    fffff800`02cece00 nt!PspCreateProcessNotifyRoutine = <no type information>
    ...
    
  10. 次のコマンドを入力して、ブレークポイントを MmCreateProcessAddressSpace に設定します。

    bu nt!MmCreateProcessAddressSpace

    ブレークポイントが設定されていることを確認するには、次のコマンドを入力します。

    bl

    出力は次の例のようになります。

    0:000>0: kd> bu nt!MmCreateProcessAddressSpace
    0: kd> bl
    0 e fffff800`02e03904     0001 (0001) nt!MmCreateProcessAddressSpace
    

    g」を入力してターゲット コンピューターを実行します。

  11. ターゲット コンピューターがデバッガーを中断しない場合は、ターゲット コンピューター上でいくつかのアクションを実行します (メモ帳を開くなど)。 MmCreateProcessAddressSpace が呼び出されると、ターゲット コンピューターはデバッガーを中断します。 スタック トレースを表示するには、次のコマンドを入力します。

    .reload

    k

    出力は次の例のようになります。

    0:000>2: kd> k
    Child-SP          RetAddr           Call Site
    ffffd000`224b4c88 fffff800`02d96834 nt!MmCreateProcessAddressSpace
    ffffd000`224b4c90 fffff800`02dfef17 nt!PspAllocateProcess+0x5d4
    ffffd000`224b5060 fffff800`02b698b3 nt!NtCreateUserProcess+0x55b
    ...
    000000d7`4167fbb0 00007ffd`14b064ad KERNEL32!BaseThreadInitThunk+0xd
    000000d7`4167fbe0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
    
  12. [表示] メニューの [逆アセンブリ] をクリックします。

    [デバッグ] メニューの [ステップ オーバー] を選択します (または F10 キーを押します)。 [逆アセンブル] ウィンドウを見ながら、ステップ コマンドをさらに数回入力します。

  13. 次のコマンドを入力して、ブレークポイントをクリアします。

    bc *

    g」を入力してターゲット コンピューターを実行します。 もう一度中断するには、[デバッグ] メニューに移動して [中断] を選択するか、Ctrl キーを押しながら Break キーを押します。

  14. すべてのプロセスの一覧を取得するには、次のコマンドを入力します。

    !process 0 0

    出力は次の例のようになります。

    0:000>0: kd> !process 0 0
    **** NT ACTIVE PROCESS DUMP ****
    PROCESS ffffe000002287c0
        SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
        DirBase: 001aa000  ObjectTable: ffffc00000003000  HandleCount: <Data Not Accessible>
        Image: System
    
    PROCESS ffffe00001e5a900
        SessionId: none  Cid: 0124    Peb: 7ff7809df000  ParentCid: 0004
        DirBase: 100595000  ObjectTable: ffffc000002c5680  HandleCount: <Data Not Accessible>
        Image: smss.exe
    ...
    PROCESS ffffe00000d52900
        SessionId: 1  Cid: 0910    Peb: 7ff669b8e000  ParentCid: 0a98
        DirBase: 3fdba000  ObjectTable: ffffc00007bfd540  HandleCount: <Data Not Accessible>
        Image: explorer.exe
    
  15. 1 つのプロセスのアドレスをコピーし、次のコマンドを入力します。

    !process Address 2

    例: !process ffffe00000d5290 2

    出力は、プロセス内のスレッドを示します。

    0:000>0:000>0: kd> !process ffffe00000d52900 2
    PROCESS ffffe00000d52900
        SessionId: 1  Cid: 0910    Peb: 7ff669b8e000  ParentCid: 0a98
        DirBase: 3fdba000  ObjectTable: ffffc00007bfd540  HandleCount:
        Image: explorer.exe
    
            THREAD ffffe00000a0d880  Cid 0910.090c  Teb: 00007ff669b8c000
                ffffe00000d57700  SynchronizationEvent
    
            THREAD ffffe00000e48880  Cid 0910.0ad8  Teb: 00007ff669b8a000
                ffffe00000d8e230  NotificationEvent
                ffffe00000cf6870  Semaphore Limit 0xffff
                ffffe000039c48c0  SynchronizationEvent
            ...
            THREAD ffffe00000e6d080  Cid 0910.0cc0  Teb: 00007ff669a10000
                ffffe0000089a300  QueueObject
    
  16. 1 つのスレッドのアドレスをコピーし、次のコマンドを入力します。

    !thread Address

    例: !thread ffffe00000e6d080

    出力は、個々のスレッドに関する情報を示します。

    0: kd> !thread ffffe00000e6d080
    THREAD ffffe00000e6d080  Cid 0910.0cc0  Teb: 00007ff669a10000 Win32Thread: 0000000000000000 WAIT: ...
        ffffe0000089a300  QueueObject
    Not impersonating
    DeviceMap                 ffffc000034e7840
    Owning Process            ffffe00000d52900       Image:         explorer.exe
    Attached Process          N/A            Image:         N/A
    Wait Start TickCount      13777          Ticks: 2 (0:00:00:00.031)
    Context Switch Count      2              IdealProcessor: 1
    UserTime                  00:00:00.000
    KernelTime                00:00:00.000
    Win32 Start Address ntdll!TppWorkerThread (0x00007ffd14ab2850)
    Stack Init ffffd00021bf1dd0 Current ffffd00021bf1580
    Base ffffd00021bf2000 Limit ffffd00021bec000 Call 0
    Priority 13 BasePriority 13 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
    ...
    
  17. プラグ アンド プレイ デバイス ツリー内のデバイス ノードをすべて表示するには、次のコマンドを入力します。

    !devnode 0 1

    0:000>0: kd> !devnode 0 1
    Dumping IopRootDeviceNode (= 0xffffe000002dbd30)
    DevNode 0xffffe000002dbd30 for PDO 0xffffe000002dc9e0
      InstancePath is "HTREE\ROOT\0"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe000002d9d30 for PDO 0xffffe000002daa40
        InstancePath is "ROOT\volmgr\0000"
        ServiceName is "volmgr"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeEnumerateCompletion (0x30d)
        DevNode 0xffffe00001d49290 for PDO 0xffffe000002a9a90
          InstancePath is "STORAGE\Volume\{3007dfd3-df8d-11e3-824c-806e6f6e6963}#0000000000100000"
          ServiceName is "volsnap"
          TargetDeviceNotify List - f 0xffffc0000031b520  b 0xffffc0000008d0f0
          State = DeviceNodeStarted (0x308)
          Previous State = DeviceNodeStartPostWork (0x307)
    ...
    
  18. デバイス ノードとそのハードウェア リソースを表示するには、次のコマンドを入力します。

    !devnode 0 9

    0:000>...
            DevNode 0xffffe000010fa770 for PDO 0xffffe000010c2060
              InstancePath is "PCI\VEN_8086&DEV_2937&SUBSYS_2819103C&REV_02\3&33fd14ca&0&D0"
              ServiceName is "usbuhci"
              State = DeviceNodeStarted (0x308)
              Previous State = DeviceNodeEnumerateCompletion (0x30d)
              TranslatedResourceList at 0xffffc00003c78b00  Version 1.1  Interface 0x5  Bus #0
                Entry 0 - Port (0x1) Device Exclusive (0x1)
                  Flags (0x131) - PORT_MEMORY PORT_IO 16_BIT_DECODE POSITIVE_DECODE
                  Range starts at 0x3120 for 0x20 bytes
                Entry 1 - DevicePrivate (0x81) Device Exclusive (0x1)
                  Flags (0000) -
                  Data - {0x00000001, 0x00000004, 0000000000}
                Entry 2 - Interrupt (0x2) Shared (0x3)
                  Flags (0000) - LEVEL_SENSITIVE
                  Level 0x8, Vector 0x81, Group 0, Affinity 0xf
    ...
    
  19. ディスクのサービス名を持つデバイス ノードを表示するには、次のコマンドを入力します。

    !devnode 0 1 disk

    0: kd> !devnode 0 1 disk
    Dumping IopRootDeviceNode (= 0xffffe000002dbd30)
    DevNode 0xffffe0000114fd30 for PDO 0xffffe00001159610
      InstancePath is "IDE\DiskST3250820AS_____________________________3.CHL___\5&14544e82&0&0.0.0"
      ServiceName is "disk"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
    ...
    
  20. !devnode 0 1 の出力には、ノードの物理デバイス オブジェクト (PDO) のアドレスが表示されます。 物理デバイス オブジェクト (PDO) のアドレスをコピーし、次のコマンドを入力します。

    !devstack PdoAddress

    例: <PdoAddress>!devstack 0xffffe00001159610

    0:000>0: kd> !devstack 0xffffe00001159610
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe00001d50040  \Driver\partmgr    ffffe00001d50190  
      ffffe00001d51450  \Driver\disk       ffffe00001d515a0  DR0
      ffffe00001156e50  \Driver\ACPI       ffffe000010d8bf0  
    
  21. ドライバー disk.sysに関する情報を取得するには、次のコマンドを入力します。

    !drvobj disk 2

    0:000>0: kd> !drvobj disk 2
    Driver object (ffffe00001d52680) is for:
     \Driver\disk
    DriverEntry:   fffff800006b1270 disk!GsDriverEntry
    DriverStartIo: 00000000
    DriverUnload:  fffff800010b0b5c CLASSPNP!ClassUnload
    AddDevice:     fffff800010aa110 CLASSPNP!ClassAddDevice
    
    Dispatch routines:
    [00] IRP_MJ_CREATE                      fffff8000106d160    CLASSPNP!ClassGlobalDispatch
    [01] IRP_MJ_CREATE_NAMED_PIPE           fffff80002b0ab24    nt!IopInvalidDeviceRequest
    [02] IRP_MJ_CLOSE                       fffff8000106d160    CLASSPNP!ClassGlobalDispatch
    [03] IRP_MJ_READ                        fffff8000106d160    CLASSPNP!ClassGlobalDispatch
    ...
    [1b] IRP_MJ_PNP                         fffff8000106d160    CLASSPNP!ClassGlobalDispatch
    
  22. !drvobj の出力には、ディスパッチ ルーチンのアドレスが表示されます。 たとえば、CLASSPNP!ClassGlobalDispatch のようにします。 ブレークポイントを ClassGlobalDispatch に設定して確認するには、次のコマンドを入力します。

    bu CLASSPNP!ClassGlobalDispatch

    bl

    g を入力してターゲット コンピューターを実行します。

    ターゲット コンピューターがデバッガーをすぐに中断しない場合は、ターゲット コンピューター上でいくつかのアクションを実行します (メモ帳を開いたり、ファイルを保存したりするなど)。 ClassGlobalDispatch が呼び出されると、ターゲット コンピューターはデバッガーを中断します。 スタック トレースを表示するには、次のコマンドを入力します。

    .reload

    k

    出力は次の例のようになります。

    2: kd> k
    Child-SP          RetAddr           Call Site
    ffffd000`21d06cf8 fffff800`0056c14e CLASSPNP!ClassGlobalDispatch
    ffffd000`21d06d00 fffff800`00f2c31d volmgr!VmReadWrite+0x13e
    ffffd000`21d06d40 fffff800`0064515d fvevol!FveFilterRundownReadWrite+0x28d
    ffffd000`21d06e20 fffff800`0064578b rdyboost!SmdProcessReadWrite+0x14d
    ffffd000`21d06ef0 fffff800`00fb06ad rdyboost!SmdDispatchReadWrite+0x8b
    ffffd000`21d06f20 fffff800`0085cef5 volsnap!VolSnapReadFilter+0x5d
    ffffd000`21d06f50 fffff800`02b619f7 Ntfs!NtfsStorageDriverCallout+0x16
    ...
    
  23. デバッグ セッションを終了するには、次のコマンドを入力します。

    qd

コマンドのまとめ

関連項目