UMDF ドライバをデバッグする際に、ユーザーモード デバッガでWUDFHost.exe にアタッチしてライブデバッグするだけではデバッグしきれなくて困ったことはありませんか?
例えば、OS のシャットダウン中の処理をデバッグしたい場合、ユーザーモード デバッガを操作している画面がシャットダウン中になるため、デバッガをその画面から操作できなくなります。
そこで、今回は、カーネルモード デバッガ(windbg.exe) でUMDF ドライバをデバッグする方法をご紹介します。カーネルモード デバッガからであれば、画面がシャットダウン中であっても、UMDF ドライバのブレークポイントで止めて、ライブデバッグすることができます。
具体的には、以下の手順で進めます。
- ターゲットPC へのUMDF2 ドライバのインストール
- ターゲットPC へのWDFVerifier.exe のコピー
- カーネルモードデバッガをターゲットPC にアタッチ
- WDFVerifier.exe によるターゲット PC の設定
- 動作確認
今回は、例として、デバッガのホストPC、ターゲットPC ともにWindows 10 (1703) x86 で行います。また、サンプルドライバをビルドする開発用PC はデバッガのホストPC と同一とします。
1.ターゲットPCへのUMDF2 ドライバのインストール
ターゲットPC にUMDF2 ドライバをインストールします。今回は、例として、UMDF2 のToaster Sample のwdffeaturedum.dll を使用します。
サンプルの入手とビルド方法は、以下のエントリの「1. サンプルの入手」と「2. サンプルのビルド」をご参照ください。
UMDF Version 2 のToaster Sample をインストールする
ビルドすると、umdf2funcfeaturedDebugwdffeaturedum フォルダに以下の 3 つのファイルが生成されます。
wdffeaturedum.dll
wdffeaturedum.inf
wudf.cat
ターゲットPC にC:umdf2toaster というフォルダを作り、上記3 つのファイルをすべてコピーします。また、開発用PC のC:Program Files (x86)Windows Kits10Toolsx86 にあるdevcon.exe も、ターゲットPC の同じC:umdf2toaster フォルダにコピーします。
管理者権限でコマンドプロンプトを起動します。cd コマンドでC:umdf2toaster フォルダに移動し、以下を実行します。
devcon install wdffeaturedum.inf roottoaster |
ドライバーをインストールするかどうか確認するダイアログが表示されたら、そのままインストールしてください。以下が表示されたら成功です。
Device node created. Install is complete when drivers are installed…
Updating drivers for roottoaster from C:umdf2toasterwdffeaturedum.inf. Drivers installed successfully. |
デバイスマネージャでも確認しておきます。
[スタート] を右クリックし、[デバイス マネージャー] を起動しますと、以下のように[Toaster] のノードに[Sample UMDF Toaster Driver –featured] と表示されていることが確認できます。
2.ターゲットPCへのWDFVerifier.exe のコピー
WDK 10 がインストールされた開発側のPC には、以下のパスにwdfverifier.exe があります。
C:Program Files (x86)Windows Kits10Toolsx86
これをターゲットPC の任意のフォルダにコピーします。今回は、C:umdf2toaster にコピーすることにします。
3.カーネルモード デバッガをターゲットPC にアタッチ
ホストPC 上にインストールしたカーネルモードデバッガ(windbg.exe) をターゲットPC にアタッチします。
Windbg.exe のインストールは以下のブログエントリをご参照ください。
デバッガ(WinDbg) をインストールする
カーネルデバッガの接続方法は、以下のブログエントリからご自身の環境にあったものをご参照ください。
Kernel Debugger 接続インターフェース
https://blogs.msdn.microsoft.com/jpwdkblog/2016/02/24/kernel-debugger/
シリアルケーブルでのカーネルモードデバッグ設定手順
Hyper-V 第二世代仮想マシンのGuest OS へのwindbg 接続方法
https://blogs.msdn.microsoft.com/jpwdkblog/2014/02/27/hyper-v-guest-os-windbg/
Hyper-Vなどの仮想OSにwindbgをアタッチする方法
https://blogs.msdn.microsoft.com/jpwdkblog/2009/03/18/hyper-voswindbg/
4.WDFVerifier.exe によるターゲット PC の設定
ターゲットPC 上で、WDFVerifier.exe を管理者権限で実行し、[Global WDF Settings] タブを開きます。
下部の[Global User Mode Verifier Settings] の中の[Attempt to attach to kernel debugger if no user-mode debugger attaches at this time.] のチェックボックスをON にします。
[OK] を押して、以下の画面で[Yes] を押します。
カーネルモード デバッガのCommand ウィンドウに以下のように表示されます。
UMDF: Breaking on load of module wdffeaturedum.dll
UMDF: Waiting 0 seconds for debugger to attach. UMDF: No user-mode debugger found. Breaking into kernel debugger. Break instruction exception – code 80000003 (first chance) 001b:778e4160 cc int 3 |
そのままg をCommand ウィンドウの kd> に入力してEnter を押し、ターゲットPC の動作を再開します。
ターゲットPC を再起動します。
5.動作確認
ターゲットPC を再起動すると、上記と同じように、wdffeaturedm.dll のロード時にカーネルモード デバッガにブレークインしてくれます。
Wdffeaturedum.dll のシンボルファイル(wdffeaturedum.pdb) が、開発用PC のumdf2funcfeaturedDebug のフォルダにあるので、シンボルパスにそれを追加します。シンボルパスの設定については、以下のブログエントリの「4. シンボルファイルの設定」をご参照ください。
メモリダンプに!analyze -v するまで・後編~ ダンプを開く~
https://blogs.msdn.microsoft.com/jpwdkblog/2009/06/11/analyze-v/
以下のコマンドで、wdffeaturedum.dll のロード時とシャットダウン時のwdffeaturedum.dll の処理でブレークインできるようにブレークポイントを貼り、g でターゲットPC の動作を再開します。
bp wdffeaturedum!DriverEntry
bp wdffeaturedum!ToasterEvtDeviceD0Exit |
wdffeaturedum!DriverEntry でブレークインします。
kd> g
Breakpoint 0 hit wdffeaturedum!DriverEntry: 001b:6c951460 55 push ebp kd> knL # ChildEBP RetAddr 00 02eff090 6c95215e wdffeaturedum!DriverEntry 01 02eff0b0 001448c0 wdffeaturedum!FxDriverEntryUmWorker+0x127 02 02eff108 00144f22 WUDFHost!InitializeFlatCApiDriver+0x87 03 02eff1fc 001455f4 WUDFHost!CWudfModuleTable::LoadComponentAndCreateInstance+0x531 04 02eff22c 00145692 WUDFHost!CWudfModuleTable::LoadComponentAndCreateInstanceEx+0x63 05 02eff258 0013fb63 WUDFHost!CWudfModuleTable::LoadFrameworkAndDriver+0x66 06 02eff310 0012e484 WUDFHost!CWudfDeviceStack::LoadDrivers+0x13e 07 02eff4cc 6fe8edcc WUDFHost!CLpcNotification::Message+0x334 08 02eff534 6fe8f33f WUDFPlatform!WdfLpcPort::ProcessMessage+0x2cc 09 02eff55c 6fe8f42d WUDFPlatform!WdfLpcCommPort::ProcessMessage+0x1ff 0a 02eff5a0 6fe8f57c WUDFPlatform!WdfLpcConnPort::ProcessMessage+0xcd 0b 02eff680 00130a86 WUDFPlatform!WdfLpc::RetrieveMessage+0xdc 0c 02eff694 00130a41 WUDFHost!MessageAvailableThunk+0x26 0d 02eff6a8 0013261d WUDFHost!CThreadpool::WorkerThread+0x51 0e 02eff6b0 7795cf0f WUDFHost!ThreadPoolWorkerThunk+0xd 0f 02eff6dc 7795ce30 ntdll!TppExecuteWaitCallback+0x88 10 02eff6f8 7794244f ntdll!TppWaitCompletion+0x80 11 02eff8b0 75a19ba4 ntdll!TppWorkerThread+0x58f 12 02eff8c4 7797ac9b KERNEL32!BaseThreadInitThunk+0x24 13 02eff90c 7797ac6f ntdll!__RtlUserThreadStart+0x2b 14 02eff91c 00000000 ntdll!_RtlUserThreadStart+0x1b |
OS をシャットダウンすると、wdffeaturedum!ToasterEvtDeviceD0Exit でブレークインします。
kd> g
Breakpoint 1 hit wdffeaturedum!ToasterEvtDeviceD0Exit: 001b:6c951370 55 push ebp kd> knL # ChildEBP RetAddr 00 02efef04 6c7a7fdb wdffeaturedum!ToasterEvtDeviceD0Exit 01 02efef20 6c7a3c62 WUDFx02000!FxPnpDeviceD0Exit::InvokeClient+0x2b 02 02efef3c 6c7a9e59 WUDFx02000!FxPrePostCallback::InvokeStateless+0x39 03 (Inline) ——– WUDFx02000!FxPnpDeviceD0Exit::Invoke+0xf 04 02efef5c 6c7a9c8d WUDFx02000!FxPkgPnp::PowerGotoDxIoStopped+0x101 05 02efef64 6c7a9a6c WUDFx02000!FxPkgPnp::PowerGotoDNotZeroIoStopped+0xd 06 02efefb4 6c7aa899 WUDFx02000!FxPkgPnp::PowerEnterNewState+0x141 07 02efefd8 6c7aa6c2 WUDFx02000!FxPkgPnp::PowerProcessEventInner+0x1a6 08 02eff000 6c7ac849 WUDFx02000!FxPkgPnp::PowerProcessEvent+0x160 09 (Inline) ——– WUDFx02000!FxPkgFdo::LowerDevicePower+0xf 0a 02eff01c 6c7acbe3 WUDFx02000!FxPkgFdo::DispatchDeviceSetPower+0xc6 0b 02eff028 6c79f9a0 WUDFx02000!FxPkgFdo::_DispatchSetPower+0x23 0c 02eff054 6c76c6b5 WUDFx02000!FxPkgPnp::Dispatch+0x2e0 0d 02eff07c 6c79150c WUDFx02000!DispatchWorker+0x6a 0e (Inline) ——– WUDFx02000!FxDevice::Dispatch+0x1f 0f 02eff0a0 6c78e450 WUDFx02000!FxDevice::DispatchWithLock+0xba 10 02eff0a8 6c7945c9 WUDFx02000!FxDevice::DispatchWithLockUm+0x10 11 02eff0d0 0014044d WUDFx02000!FxMessageDispatch::DispatchPnP+0xa9 12 02eff20c 00137d01 WUDFHost!CWudfDeviceStack::OnDispatchPnp+0x1d3 13 02eff21c 00134275 WUDFHost!CWudfPnpIrp::Dispatch+0x11 14 02eff248 0013aca4 WUDFHost!CWudfDeviceStack::Forward+0x6865 15 02eff268 0013afea WUDFHost!CLpcNotification::UnloadSafeDispatchIrp+0x3a 16 02eff2dc 0013a655 WUDFHost!CLpcNotification::WudfPnpHandler+0x20a 17 02eff304 0012fe0a WUDFHost!CLpcNotification::ProcessPnpPowerIrp+0xd5 18 02eff4cc 6fe8edcc WUDFHost!CLpcNotification::Message+0x1cba 19 02eff534 6fe8f33f WUDFPlatform!WdfLpcPort::ProcessMessage+0x2cc 1a 02eff55c 6fe8f42d WUDFPlatform!WdfLpcCommPort::ProcessMessage+0x1ff 1b 02eff5a0 6fe8f57c WUDFPlatform!WdfLpcConnPort::ProcessMessage+0xcd 1c 02eff680 00130a86 WUDFPlatform!WdfLpc::RetrieveMessage+0xdc 1d 02eff694 00130a41 WUDFHost!MessageAvailableThunk+0x26 1e 02eff6a8 0013261d WUDFHost!CThreadpool::WorkerThread+0x51 1f 02eff6b0 7795cf0f WUDFHost!ThreadPoolWorkerThunk+0xd 20 02eff6dc 7795ce30 ntdll!TppExecuteWaitCallback+0x88 21 02eff6f8 7794244f ntdll!TppWaitCompletion+0x80 22 02eff8b0 75a19ba4 ntdll!TppWorkerThread+0x58f 23 02eff8c4 7797ac9b KERNEL32!BaseThreadInitThunk+0x24 24 02eff90c 7797ac6f ntdll!__RtlUserThreadStart+0x2b 25 02eff91c 00000000 ntdll!_RtlUserThreadStart+0x1b |
<参考文献>
・How to Enable Debugging of a UMDF Driver
https://docs.microsoft.com/ja-jp/windows-hardware/drivers/wdf/enabling-a-debugger
・WDF Verifier Control Application
https://docs.microsoft.com/ja-jp/windows-hardware/drivers/devtest/wdf-verifier-control-application
以上の内容がお役に立ちましたら幸いです。
WDK サポートチーム 津田