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 3.0
- シリアル ("null モデム" とも呼ばれます)
速度と信頼性を確保するには、イーサネット ケーブルとローカル ネットワーク ハブを使用する必要があります。 次の図は、イーサネット ケーブルを使用してデバッグするために接続されたホスト コンピューターとターゲット コンピューターを示しています。
以前のバージョンの Windows のオプションは、シリアル ケーブルなどの直接ケーブルを使用することです。
ホスト コンピューターとターゲット コンピューターの設定方法の詳細については、「カーネルモード デバッグの手動での設定」を参照してください。
仮想マシン - VM
Hyper-V 仮想マシンへのデバッガーの接続については、「仮想マシンのネットワーク デバッグの設定 - KDNET」を参照してください。
カーネルモード デバッグ セッションを確立する
ホストとターゲット コンピューターを設定し、デバッグ ケーブルで接続したら、カーネルモードデバッグ セッションを確立できます。 セットアップで使用したものと同じトピックの手順に従います。 たとえば、イーサネット経由でデバッグするためのホスト コンピューターとターゲット コンピューターを設定する場合は、次の記事でカーネル モード デバッグ セッションを確立する手順を確認できます。
WinDbg の使用を開始する
ホスト コンピューターで WinDbg を開き、ターゲット コンピューターとのカーネルモード デバッグ セッションを確立します。
デバッガーのドキュメント CHM ファイルを開くには、[ヘルプ] メニューに移動して [コンテンツ] を選択します。 デバッガーのドキュメントは、Windows 用デバッグ ツールでオンラインでも入手できます。
カーネルモード デバッグ セッションを確立する際、WinDbg が自動的にターゲット コンピューターを中断する可能性があります。 WinDbg が中断されない場合は、[デバッグ] メニューに移動して [中断] を選択します。
[WinDbg] ウィンドウの下部にあるコマンド ラインに、次のコマンドを入力します。
出力は次の例のようになります。
Symbol search path is: srv* Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols
シンボルの検索パスにより、シンボル (PDB) ファイルを検索する場所が WinDbg に指示されます。 デバッガーには、関数名や変数名など、コード モジュールに関する情報を取得するためのシンボル ファイルが必要です。
次のコマンドを入力して、シンボル ファイルの初期検索と読み込みを行うよう WinDbg に指示します。
読み込まれたモジュールの一覧を取得するには、次のコマンドを入力します。
出力は次の例のようになります。
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) ...
ターゲット コンピューターの実行を開始するには、次のコマンドを入力します。
もう一度中断するには、[デバッグ] メニューに移動して [中断] を選択します。
次のコマンドを入力して、
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
次のコマンドを入力して、
nt
モジュール内のシンボルのいくつかを調べます。出力は次の例のようになります。
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> ...
次のコマンドを入力して、ブレークポイントを MmCreateProcessAddressSpace に設定します。
bu nt!MmCreateProcessAddressSpace
ブレークポイントが設定されていることを確認するには、次のコマンドを入力します。
出力は次の例のようになります。
0:000>0: kd> bu nt!MmCreateProcessAddressSpace 0: kd> bl 0 e fffff800`02e03904 0001 (0001) nt!MmCreateProcessAddressSpace
「g」を入力してターゲット コンピューターを実行します。
ターゲット コンピューターがデバッガーを中断しない場合は、ターゲット コンピューター上でいくつかのアクションを実行します (メモ帳を開くなど)。 MmCreateProcessAddressSpace が呼び出されると、ターゲット コンピューターはデバッガーを中断します。 スタック トレースを表示するには、次のコマンドを入力します。
出力は次の例のようになります。
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
[表示] メニューの [逆アセンブリ] をクリックします。
[デバッグ] メニューの [ステップ オーバー] を選択します (または F10 キーを押します)。 [逆アセンブル] ウィンドウを見ながら、ステップ コマンドをさらに数回入力します。
次のコマンドを入力して、ブレークポイントをクリアします。
「g」を入力してターゲット コンピューターを実行します。 もう一度中断するには、[デバッグ] メニューに移動して [中断] を選択するか、Ctrl キーを押しながら Break キーを押します。
すべてのプロセスの一覧を取得するには、次のコマンドを入力します。
出力は次の例のようになります。
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
1 つのプロセスのアドレスをコピーし、次のコマンドを入力します。
例:
!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
1 つのスレッドのアドレスをコピーし、次のコマンドを入力します。
例:
!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 ...
プラグ アンド プレイ デバイス ツリー内のデバイス ノードをすべて表示するには、次のコマンドを入力します。
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) ...
デバイス ノードとそのハードウェア リソースを表示するには、次のコマンドを入力します。
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 ...
ディスクのサービス名を持つデバイス ノードを表示するには、次のコマンドを入力します。
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) ...
!devnode 0 1 の出力には、ノードの物理デバイス オブジェクト (PDO) のアドレスが表示されます。 物理デバイス オブジェクト (PDO) のアドレスをコピーし、次のコマンドを入力します。
例:
<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
ドライバー disk.sysに関する情報を取得するには、次のコマンドを入力します。
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
!drvobj
の出力には、ディスパッチ ルーチンのアドレスが表示されます。 たとえば、CLASSPNP!ClassGlobalDispatch
のようにします。 ブレークポイントをClassGlobalDispatch
に設定して確認するには、次のコマンドを入力します。bu CLASSPNP!ClassGlobalDispatch
g
を入力してターゲット コンピューターを実行します。ターゲット コンピューターがデバッガーをすぐに中断しない場合は、ターゲット コンピューター上でいくつかのアクションを実行します (メモ帳を開いたり、ファイルを保存したりするなど)。
ClassGlobalDispatch
が呼び出されると、ターゲット コンピューターはデバッガーを中断します。 スタック トレースを表示するには、次のコマンドを入力します。出力は次の例のようになります。
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 ...
デバッグ セッションを終了するには、次のコマンドを入力します。
コマンドのまとめ
- [ヘルプ] メニューの [コンテンツ] コマンド
- .sympath (シンボル パスの設定)
- .reload (モジュールの再読み込み)
- x (シンボルの検証)
- g (実行)
- dt (型の表示)
- [デバッグ] メニューの [中断] コマンド
- lm (読み込まれたモジュールの一覧表示)
- k (スタック バックトレースの表示)
- bu (ブレークポイントの設定)
- bl (ブレークポイントの一覧)
- bc (ブレークポイントのクリア)
- [デバッグ] メニューの [ステップ イン] コマンド (F11)
- !process
- !thread
- !devnode
- !devstack
- !drvobj
- qd (終了してデタッチ)