カーネルモード デバッガで UMDF ドライバをライブデバッグする

UMDF ドライバをデバッグする際に、ユーザーモード デバッガでWUDFHost.exe にアタッチしてライブデバッグするだけではデバッグしきれなくて困ったことはありませんか?

 

例えば、OS のシャットダウン中の処理をデバッグしたい場合、ユーザーモード デバッガを操作している画面がシャットダウン中になるため、デバッガをその画面から操作できなくなります。

 

そこで、今回は、カーネルモード デバッガ(windbg.exe) でUMDF ドライバをデバッグする方法をご紹介します。カーネルモード デバッガからであれば、画面がシャットダウン中であっても、UMDF ドライバのブレークポイントで止めて、ライブデバッグすることができます。

 

具体的には、以下の手順で進めます。

 

    1. ターゲットPC へのUMDF2 ドライバのインストール
    2. ターゲットPC へのWDFVerifier.exe のコピー
    3. カーネルモードデバッガをターゲットPC にアタッチ
    4. WDFVerifier.exe によるターゲット PC の設定
    5. 動作確認

 

今回は、例として、デバッガのホスト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 をインストールする

https://blogs.msdn.microsoft.com/jpwdkblog/2016/11/28/umdf-version-2-%e3%81%ae-toaster-sample-%e3%82%92%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%99%e3%82%8b/

 

ビルドすると、\umdf2\func\featured\Debug\wdffeaturedum フォルダに以下の 3 つのファイルが生成されます。

 

wdffeaturedum.dll

wdffeaturedum.inf

wudf.cat

 

ターゲットPC にC:\umdf2toaster というフォルダを作り、上記3 つのファイルをすべてコピーします。また、開発用PC のC:\Program Files (x86)\Windows Kits\10\Tools\x86 にあるdevcon.exe も、ターゲットPC の同じC:\umdf2toaster フォルダにコピーします。

 

管理者権限でコマンドプロンプトを起動します。cd コマンドでC:\umdf2toaster フォルダに移動し、以下を実行します。

 

devcon install wdffeaturedum.inf root\toaster

 

ドライバーをインストールするかどうか確認するダイアログが表示されたら、そのままインストールしてください。以下が表示されたら成功です。

 

Device node created. Install is complete when drivers are installed…Updating drivers for root\toaster from C:\umdf2toaster\wdffeaturedum.inf.Drivers installed successfully.

 

デバイスマネージャでも確認しておきます。

 

[スタート] を右クリックし、[デバイス マネージャー] を起動しますと、以下のように[Toaster] のノードに[Sample UMDF Toaster Driver –featured] と表示されていることが確認できます。

 

clip_image001

 

 

2. ターゲットPCへのWDFVerifier.exe のコピー

 

WDK 10 がインストールされた開発側のPC には、以下のパスにwdfverifier.exe があります。

 

C:\Program Files (x86)\Windows Kits\10\Tools\x86

 

これをターゲットPC の任意のフォルダにコピーします。今回は、C:\umdf2toaster にコピーすることにします。

 

 

3. カーネルモード デバッガをターゲットPC にアタッチ

 

ホストPC 上にインストールしたカーネルモードデバッガ(windbg.exe) をターゲットPC にアタッチします。

 

Windbg.exe のインストールは以下のブログエントリをご参照ください。

 

デバッガ(WinDbg) をインストールする

https://blogs.msdn.microsoft.com/jpwdkblog/2016/03/07/%e3%83%87%e3%83%90%e3%83%83%e3%82%ac-windbg-%e3%82%92%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%99%e3%82%8b/

 

カーネルデバッガの接続方法は、以下のブログエントリからご自身の環境にあったものをご参照ください。

 

Kernel Debugger 接続インターフェース

https://blogs.msdn.microsoft.com/jpwdkblog/2016/02/24/kernel-debugger/

 

シリアルケーブルでのカーネルモードデバッグ設定手順

https://blogs.msdn.microsoft.com/jpwdkblog/2016/03/15/%e3%82%b7%e3%83%aa%e3%82%a2%e3%83%ab%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab%e3%81%a7%e3%81%ae%e3%82%ab%e3%83%bc%e3%83%8d%e3%83%ab%e3%83%a2%e3%83%bc%e3%83%89%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e8%a8%ad/

 

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 にします。

 

clip_image002

 

[OK] を押して、以下の画面で[Yes] を押します。

 

clip_image003

 

カーネルモード デバッガのCommand ウィンドウに以下のように表示されます。

 

UMDF: Breaking on load of module wdffeaturedum.dllUMDF: 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 の\umdf2\func\featured\Debug のフォルダにあるので、シンボルパスにそれを追加します。シンボルパスの設定については、以下のブログエントリの「4. シンボルファイルの設定」をご参照ください。

 

メモリダンプに!analyze -v するまで・後編~ ダンプを開く~

https://blogs.msdn.microsoft.com/jpwdkblog/2009/06/11/analyze-v/

 

以下のコマンドで、wdffeaturedum.dll のロード時とシャットダウン時のwdffeaturedum.dll の処理でブレークインできるようにブレークポイントを貼り、g でターゲットPC の動作を再開します。

 

bp wdffeaturedum!DriverEntrybp wdffeaturedum!ToasterEvtDeviceD0Exit

 

wdffeaturedum!DriverEntry でブレークインします。

 

kd> gBreakpoint 0 hitwdffeaturedum!DriverEntry:001b:6c951460 55              push    ebpkd> knL# ChildEBP RetAddr00 02eff090 6c95215e wdffeaturedum!DriverEntry01 02eff0b0 001448c0 wdffeaturedum!FxDriverEntryUmWorker+0x12702 02eff108 00144f22 WUDFHost!InitializeFlatCApiDriver+0x8703 02eff1fc 001455f4 WUDFHost!CWudfModuleTable::LoadComponentAndCreateInstance+0x53104 02eff22c 00145692 WUDFHost!CWudfModuleTable::LoadComponentAndCreateInstanceEx+0x6305 02eff258 0013fb63 WUDFHost!CWudfModuleTable::LoadFrameworkAndDriver+0x6606 02eff310 0012e484 WUDFHost!CWudfDeviceStack::LoadDrivers+0x13e07 02eff4cc 6fe8edcc WUDFHost!CLpcNotification::Message+0x33408 02eff534 6fe8f33f WUDFPlatform!WdfLpcPort::ProcessMessage+0x2cc09 02eff55c 6fe8f42d WUDFPlatform!WdfLpcCommPort::ProcessMessage+0x1ff0a 02eff5a0 6fe8f57c WUDFPlatform!WdfLpcConnPort::ProcessMessage+0xcd0b 02eff680 00130a86 WUDFPlatform!WdfLpc::RetrieveMessage+0xdc0c 02eff694 00130a41 WUDFHost!MessageAvailableThunk+0x260d 02eff6a8 0013261d WUDFHost!CThreadpool::WorkerThread+0x510e 02eff6b0 7795cf0f WUDFHost!ThreadPoolWorkerThunk+0xd0f 02eff6dc 7795ce30 ntdll!TppExecuteWaitCallback+0x8810 02eff6f8 7794244f ntdll!TppWaitCompletion+0x8011 02eff8b0 75a19ba4 ntdll!TppWorkerThread+0x58f12 02eff8c4 7797ac9b KERNEL32!BaseThreadInitThunk+0x2413 02eff90c 7797ac6f ntdll!__RtlUserThreadStart+0x2b14 02eff91c 00000000 ntdll!_RtlUserThreadStart+0x1b

 

OS をシャットダウンすると、wdffeaturedum!ToasterEvtDeviceD0Exit でブレークインします。

 

kd> gBreakpoint 1 hitwdffeaturedum!ToasterEvtDeviceD0Exit:001b:6c951370 55              push    ebpkd> knL# ChildEBP RetAddr00 02efef04 6c7a7fdb wdffeaturedum!ToasterEvtDeviceD0Exit01 02efef20 6c7a3c62 WUDFx02000!FxPnpDeviceD0Exit::InvokeClient+0x2b02 02efef3c 6c7a9e59 WUDFx02000!FxPrePostCallback::InvokeStateless+0x3903 (Inline) -------- WUDFx02000!FxPnpDeviceD0Exit::Invoke+0xf04 02efef5c 6c7a9c8d WUDFx02000!FxPkgPnp::PowerGotoDxIoStopped+0x10105 02efef64 6c7a9a6c WUDFx02000!FxPkgPnp::PowerGotoDNotZeroIoStopped+0xd06 02efefb4 6c7aa899 WUDFx02000!FxPkgPnp::PowerEnterNewState+0x14107 02efefd8 6c7aa6c2 WUDFx02000!FxPkgPnp::PowerProcessEventInner+0x1a608 02eff000 6c7ac849 WUDFx02000!FxPkgPnp::PowerProcessEvent+0x16009 (Inline) -------- WUDFx02000!FxPkgFdo::LowerDevicePower+0xf0a 02eff01c 6c7acbe3 WUDFx02000!FxPkgFdo::DispatchDeviceSetPower+0xc60b 02eff028 6c79f9a0 WUDFx02000!FxPkgFdo::_DispatchSetPower+0x230c 02eff054 6c76c6b5 WUDFx02000!FxPkgPnp::Dispatch+0x2e00d 02eff07c 6c79150c WUDFx02000!DispatchWorker+0x6a0e (Inline) -------- WUDFx02000!FxDevice::Dispatch+0x1f0f 02eff0a0 6c78e450 WUDFx02000!FxDevice::DispatchWithLock+0xba10 02eff0a8 6c7945c9 WUDFx02000!FxDevice::DispatchWithLockUm+0x1011 02eff0d0 0014044d WUDFx02000!FxMessageDispatch::DispatchPnP+0xa912 02eff20c 00137d01 WUDFHost!CWudfDeviceStack::OnDispatchPnp+0x1d313 02eff21c 00134275 WUDFHost!CWudfPnpIrp::Dispatch+0x1114 02eff248 0013aca4 WUDFHost!CWudfDeviceStack::Forward+0x686515 02eff268 0013afea WUDFHost!CLpcNotification::UnloadSafeDispatchIrp+0x3a16 02eff2dc 0013a655 WUDFHost!CLpcNotification::WudfPnpHandler+0x20a17 02eff304 0012fe0a WUDFHost!CLpcNotification::ProcessPnpPowerIrp+0xd518 02eff4cc 6fe8edcc WUDFHost!CLpcNotification::Message+0x1cba19 02eff534 6fe8f33f WUDFPlatform!WdfLpcPort::ProcessMessage+0x2cc1a 02eff55c 6fe8f42d WUDFPlatform!WdfLpcCommPort::ProcessMessage+0x1ff1b 02eff5a0 6fe8f57c WUDFPlatform!WdfLpcConnPort::ProcessMessage+0xcd1c 02eff680 00130a86 WUDFPlatform!WdfLpc::RetrieveMessage+0xdc1d 02eff694 00130a41 WUDFHost!MessageAvailableThunk+0x261e 02eff6a8 0013261d WUDFHost!CThreadpool::WorkerThread+0x511f 02eff6b0 7795cf0f WUDFHost!ThreadPoolWorkerThunk+0xd20 02eff6dc 7795ce30 ntdll!TppExecuteWaitCallback+0x8821 02eff6f8 7794244f ntdll!TppWaitCompletion+0x8022 02eff8b0 75a19ba4 ntdll!TppWorkerThread+0x58f23 02eff8c4 7797ac9b KERNEL32!BaseThreadInitThunk+0x2424 02eff90c 7797ac6f ntdll!__RtlUserThreadStart+0x2b25 02eff91c 00000000 ntdll!_RtlUserThreadStart+0x1b

 

 

< 参考文献>

・How to Enable Debugging of a UMDF Driver

/ja-jp/windows-hardware/drivers/wdf/enabling-a-debugger

 

・WDF Verifier Control Application

  /ja-jp/windows-hardware/drivers/devtest/wdf-verifier-control-application

 

 

以上の内容がお役に立ちましたら幸いです。

 

WDK サポートチーム 津田