偵錯 Windows 驅動程式逐步實驗室 (回應核心模式)

此實驗室引進 WinDbg 核心調試程式。 您可以使用 WinDbg 對回應核心模式範例驅動程式程式代碼進行偵錯。

實驗室目標

此實驗室包含介紹偵錯工具的練習、教導常見的偵錯命令、說明斷點的使用方式,以及示範如何使用偵錯延伸模組。

在此實驗室中,您會使用即時核心偵錯連線來探索下列動作:

  • 使用 Windows 調試程式命令
  • 使用標準命令 (呼叫堆疊、變數、線程、IRQL)
  • 使用進階驅動程序偵錯命令 (!commands)
  • 使用符號
  • 在即時偵錯中設定斷點
  • 檢視呼叫堆疊
  • 顯示 隨插即用 裝置樹狀結構
  • 使用線程和進程內容

使用者和核心模式偵錯

使用 Windows 調試程式時,您可以執行兩種類型的偵錯:

使用者模式 - 應用程式與子系統會在使用者模式的電腦上執行。 在使用者模式中執行的進程會在自己的虛擬位址空間內執行。 它們受限於直接存取系統的許多部分,包括系統硬體、未配置供其使用的記憶體,以及系統可能會危害系統完整性的其他部分。 由於在使用者模式中執行的進程會有效地與系統和其他使用者模式進程隔離,因此它們不會干擾這些資源。

核心模式 - 作業系統和特殊許可權程式會在核心模式中執行。 核心模式程式代碼有權存取系統的任何部分。 其不受限制,例如使用者模式程序代碼。 它可以存取在使用者模式或核心模式中執行的任何其他進程的任何部分。 大部分的核心OS功能和許多硬體設備驅動器都以核心模式執行。

本練習涵蓋使用者模式和核心模式偵錯期間經常使用的偵錯命令。 此練習也涵蓋偵錯延伸模組,有時稱為 !commands,用於內核模式偵錯。

實驗室設定

您需要下列硬體才能完成實驗室:

  • 執行 Windows 10 的膝上型電腦或桌面電腦 (主機)
  • 執行 Windows 10 的第二部膝上型電腦或桌面電腦 (目標)
  • 用來連接兩部計算機的網路中樞或路由器和網路纜線
  • 存取因特網以下載符號檔

您需要下列軟體才能完成實驗室:

  • Visual Studio
  • 適用於 Windows 10 的 Windows 軟體開發套件 (SDK)
  • 適用於 Windows 10 的 Windows 驅動程式套件 (WDK)
  • 適用於 Windows 10的範例回應驅動程式

實驗室有下列各節:

聯機到核心模式 WinDbg 工作階段

在本節中,在主機和目標系統上設定網路偵錯。

此實驗室中的計算機必須設定為使用乙太網路連線進行核心偵錯。

此實驗室使用兩部計算機。 Windows 調試程式會在 主機 系統上執行,而核心模式驅動程式架構 (KMDF) 回應驅動程式會在 目標 系統上執行。

使用網路中樞或路由器和網路纜線來連接兩部計算機。

此圖說明透過網路中樞或路由器連線的兩部計算機。

若要使用核心模式應用程式並使用 WinDbg,建議您使用透過乙太網路傳輸的 KDNET。 如需如何使用乙太網路傳輸通訊協定的資訊,請參閱開始使用 WinDbg (核心模式) 。 如需設定目標計算機的詳細資訊,請參閱 準備計算機以進行手動驅動程式部署自動設定 KDNET 網路核心偵錯

使用乙太網路設定核心模式偵錯

若要在目標系統上啟用核心模式偵錯:

  1. 在主機系統上,開啟 [命令提示字元] 視窗,然後輸入 ipconfig 以判斷其IP位址。

    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 . . . . . . . . . :
    
  2. 記錄主機系統的 IP 位址:______________________________________

  3. 在目標系統上,開啟 [命令提示字元] 視窗,並使用 ping 命令來確認兩個系統之間的網路連線能力。

    ping 169.182.1.1
    

    使用您記錄的主機系統實際IP位址,而不是範例輸出中顯示的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 變更開機資訊之前,您可能需要暫時暫停 Windows 安全性功能,例如測試電腦上的 BitLocker 和安全開機。 測試完成時重新啟用這些安全性功能。 當安全性功能停用時,請適當地管理測試計算機。

  1. 在目標電腦上,以系統管理員身分開啟命令提示字元視窗。 輸入此指令以開啟偵錯:

    bcdedit /set {default} DEBUG YES
    
  2. 輸入此指令以啟用測試簽署:

    bcdedit /set TESTSIGNING ON 
    
  3. 輸入此命令以設定主機系統的IP位址。 使用您稍早記錄的主機系統的IP位址,而不是顯示的IP位址。

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

    警告

    若要提高連線的安全性,並降低隨機用戶端調試程式連線要求的風險,請使用自動產生的隨機密鑰。 如需詳細資訊,請參閱 自動設定 KDNET 網路核心偵錯

  4. 輸入此指令以確認 dbgsettings 的值已正確設定:

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

    注意

    如果您收到來自防火牆的訊息,而且您想要使用調試程式,請選取這三個方塊。

    Windows 安全性 警示對話框的螢幕快照,指出 Windows 防火牆封鎖了應用程式的一些功能。

  5. 在主電腦上,以系統管理員身分開啟命令提示字元視窗。 此實驗室使用 Windows 驅動程式套件 (WDK) 安裝的 x64 版本 WinDbg.exe 。 變更為預設 WinDbg 目錄,預設位置如下所示。

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

    此實驗室假設這兩部計算機在目標和主機上執行64位版本的Windows。 如果不是這種情況,最佳方法是在目標執行的主機上執行相同 的工具。 例如,如果目標執行 32 位 Windows,請在主機上執行 32 位版本的調試程式。 如需詳細資訊,請參閱 選擇 32 位或 64 位偵錯工具

  6. 使用下列命令,以遠端使用者偵錯開啟 WinDbg。 機碼和埠的值符合您在目標電腦上稍早使用 BCDEdit 設定的值。

    WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  7. 重新啟動目標系統。

  8. 在一或兩分鐘內,偵錯輸出應該會顯示在主機系統上。

    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 中的主要偵錯資訊視窗。 您可以輸入除錯程式命令,並在此視窗中檢視命令輸出。

調試程式命令視窗分成兩個窗格。 在較小的窗格中輸入命令,這是視窗底部的命令輸入窗格,並在視窗頂端的較大窗格中檢視命令輸出。

在命令輸入窗格中,使用向上鍵和向下鍵來捲動命令歷程記錄。 當命令出現時,您可以編輯命令,或按 Enter 來執行命令。

核心模式偵錯命令和技術

在本節中,使用偵錯命令來顯示目標系統的相關信息。

某些偵錯命令會使用調試程式標記語言 (DML) 顯示文字,您可以選取以快速收集詳細資訊。

  1. 在主機系統上,使用 WinDBg 中的 Ctrl+Scroll Lock 來中斷目標系統上執行的程式代碼。 目標系統可能需要一些時間才能回應。

    調試程式中的主畫面,顯示即時核心連線的命令窗口輸出。

  2. 在 [除錯程式指令] 視窗中輸入下列命令以啟用 DML:

    0: kd> .prefer_dml 1
    DML versions of commands on by default
    
  3. 您可以使用 命令來存取參考命令說明 .hh 。 輸入下列命令以檢視 的 .prefer_dml命令參考說明:

    0: kd> .hh .prefer_dml
    

    調試程序說明檔會顯示命令的說明 .prefer_dml

    調試程序說明應用程式的螢幕快照,其中顯示 .prefer-dml 命令的說明。

  4. 若要在目標系統上顯示詳細的版本資訊,請在 [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
    
  5. 若要確認您使用正確的核心模式程式,請在 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
    ...
    

    省略的輸出會以 “...” 表示在此實驗室中。

  6. 若要要求特定模組的詳細資訊,請使用 v (詳細資訊) 選項:

    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
    

    沒有設定的符號路徑和已載入的符號,因此調試程式中有有限的資訊可用。

下載並建置 KMDF 回應驅動程式

在本節中,下載並建置 KMDF 回應驅動程式。

一般而言,當您使用 WinDbg 時,您會使用自己的驅動程式程式代碼。 為了熟悉 WinDbg 作業,此實驗室會使用 KMDF 範本 「Echo」 範例驅動程式。 原始程式碼可用來協助瞭解 WinDbg 中顯示的資訊。 此範例也可用來說明如何逐步執行原生核心模式程序代碼。 這項技術對於偵錯複雜的核心模式程式代碼問題相當重要。

若要下載並建置 Echo 範例音訊驅動程式:

  1. 從 GitHub 下載並擷取 KMDF Echo 範例。

    KMDF Echo 範例位於 一般 資料夾中。

    GitHub windows-driver-samples 頁面的螢幕快照,其中醒目提示一般資料夾和下載 zip 按鈕。

    1. 在一個 zip 檔案中下載驅動程式範例: 驅動程式範例

    2. 將 zip 檔案下載到您的本機硬碟。

    3. 選取並按住或以滑鼠右鍵按兩下 zip 檔案,然後選取[ 全部解壓縮]。 指定新的資料夾,或瀏覽至現有的資料夾來儲存解壓縮的檔案。 例如,您可以將 C:\DriverSamples\ 指定為要擷取檔案的新資料夾。

    4. 解壓縮檔案之後,請移至下列子資料夾: C:\DriverSamples\general\echo\kmdf

  2. 在 Microsoft Visual Studio 中,選取 [ 檔案>開啟>專案/方案... ],然後移至包含解壓縮檔案的資料夾,例如 C:\DriverSamples\general\echo\kmdf。 按兩下 kmdfecho 方案檔案以開啟它。

    在 Visual Studio 中,找出 方案總管。 如果尚未開啟此視窗,請從 [檢視] 功能選取 [方案總管]。 在 方案總管 中,您可以看到一個有三個項目的解決方案。

    Visual Studio 的螢幕快照,其中顯示從 kmdfecho 專案載入的 device.c 檔案。

  3. 設定範例的組態和平臺。 在 方案總管 中,選取並按住或以滑鼠右鍵按兩下 [方案 'kmdfecho' (3 個專案) ,然後選取 [Configuration Manager]。 請確定這三個專案的組態和平台設定都相同。 根據預設,組態會設定為 Win10 Debug,而平臺會設定為 所有專案的 Win64 。 如果您對一個項目進行任何設定或平台變更,請對其餘三個項目進行相同的變更。

  4. 驅動程式範例必須修改,才能使用不會與現有驅動程式重疊的值。 請參閱 從範例程式代碼到生產驅動程式 - 範例中要變更的內容 ,瞭解如何建立唯一驅動程式範例,以與 Windows 中已安裝的現有實際驅動程式共存。

  5. 設定運行時間連結庫。 開啟 echo 驅動程式屬性頁,並找出 C/C++>Code Generation。 將運行時間連結庫變更為多線程偵錯 (/MTd) 。 如需組建選項的詳細資訊,請參閱 /MD、/MT、/LD (使用 Run-Time 連結庫)

    Visual Studio 中響應屬性頁的螢幕快照,其中醒目提示運行時間連結庫設定。

  6. 在驅動程式屬性中,確定 [驅動程式簽署簽署>模式 ] 設定為 [測試簽署]。

    Visual Studio 中響應屬性頁的螢幕快照,其中醒目提示簽署模式設定。

  7. 在 Visual Studio 中,選取 [建>置建置方案]。

    建置視窗應該會顯示一則訊息,指出這三個專案的建置成功。

提示

如果您遇到組建錯誤訊息,請使用組建錯誤號碼來判斷修正。 例如, MSBuild 錯誤MSB8040 說明如何使用spectre緩和的連結庫。

  1. 在 檔案總管 中,移至包含範例所解壓縮檔案的資料夾。 例如,如果這是您稍早指定的資料夾,請移至 C:\DriverSamples\general\echo\kmdf。 在該資料夾中,已編譯驅動程式檔案的位置會根據您在 Configuration Manager 中選取的組態和平台設定而有所不同。 如果您將預設設定保留不變,則編譯的驅動程式檔案會儲存至名為 \x64\Debug 的資料夾,以供 64 位偵錯組建使用。

    移至包含 Autosync 驅動程式建置檔案的資料夾: C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug

    資料夾應該包含下列檔案:

    檔案 描述
    Echo.sys 驅動程式檔案。
    Echo.inf 資訊 (INF) 檔案,其中包含安裝驅動程式所需的資訊。

    此外,已建置 echoapp.exe 檔案,它應該位於此處: C:\DriverSamples\general\echo\kmdf\exe\x64\Debug

    檔案 描述
    EchoApp.exe 與 echo.sys 驅動程式通訊的命令提示字元可執行檔。
  2. 找出 USB 指紋磁碟驅動器或設定網路共用,以將建置的驅動程式檔案和測試 EchoApp 從主機複製到目標系統。

在下一節中,將程式代碼複製到目標系統,然後安裝和測試驅動程式。

在目標系統上安裝 KMDF echo 驅動程式範例

在本節中,使用 DevCon 工具來安裝回應範例驅動程式。

安裝驅動程式的計算機稱為 目標計算機測試計算機。 一般而言,此計算機與您開發及建置驅動程式套件的計算機不同。 您開發和建置驅動程式的計算機稱為 主計算機

將驅動程式套件移至目標計算機並安裝驅動程式的程式稱為 部署 驅動程式。

部署測試簽署驅動程式之前,請先啟用測試簽署來準備目標計算機。 您也需要在 WDK 安裝中找到 DevCon 工具,並將此工具複製到目標系統。

若要在目標系統上安裝驅動程式,請執行下列步驟。

在目標系統上,啟用測試簽署的驅動程式:

  1. 開啟 Windows 設定

  2. [更新和安全性] 中,選取 [ 復原]。

  3. 在 [ 進階啟動] 底下,選取 [ 立即重新啟動]。

  4. 當電腦重新啟動時,請選取 [ 啟動選項]。 在 [Windows 10] 中,選取 [針對進階選項>啟動設定進行疑難解答>],然後選取 [重新啟動]。

  5. 按下 F7 鍵來選取 [ 停用驅動程序簽章強制執行 ]。

  6. 重新啟動目標電腦。

在主機系統上,移至 WDK 安裝中的 [工具 ] 資料夾,然後找出 DevCon 工具。 例如,請查看下列資料夾: C:\Program Files (x86) \Windows Kits\10\Tools\x64\devcon.exe

在建置驅動程式套件的目標上建立資料夾,例如 C:\EchoDriver 將devcon.exe 複製到目標系統。 在主機系統上找出 .cer 憑證。 它位於包含所建置驅動程式檔案之資料夾中主電腦上的相同資料夾中。 從先前在主計算機上描述的建置驅動程式複製所有檔案,並將它們儲存到您在目標計算機上建立的相同資料夾。

在目標計算機上,選取並按住或以滑鼠右鍵單擊憑證檔案,然後選取 [ 安裝],然後遵循提示來安裝測試憑證。

如果您需要設定目標計算機的詳細指示,請參閱 準備計算機以進行手動驅動程式部署

下列指示說明如何安裝和測試範例驅動程式。 以下是用來安裝驅動程式之 devcon 工具的一般語法:

devcon install <INF file> <hardware ID>

安裝此驅動程式所需的 INF 檔案是 echo.inf。 inf 檔案包含安裝 echo.sys的硬體識別碼。 針對回應範例,硬體標識碼為 root\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 以開啟 裝置管理員。 在 [裝置管理員] 的 [檢視] 功能表上,依類型選擇 [裝置]。在裝置樹狀目錄中,找出 [範例裝置] 節點中的 [範例 WDF Echo 驅動程式]。

醒目提示範例 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

使用 WinDbg 顯示驅動程式的相關信息

在本節中,設定符號路徑,並使用核心調試程式命令來顯示 KMDF 回應範例驅動程式的相關信息。

若要檢視驅動程序的相關信息:

  1. 在主機系統上,如果您關閉調試程式,請使用系統管理員命令提示字元視窗中的下列命令再次開啟它。

    WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. 使用 Ctrl+Break (捲動鎖定) 來中斷目標系統上執行的程式代碼。

  3. 若要在 WinDbg 環境中設定 Microsoft 符號伺服器的符號路徑,請使用 .symfix 命令。

    0: kd> .symfix
    
  4. 若要新增您的本機符號位置以使用您的本機符號,請使用 和 來.reload /f新增路徑.sympath+

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

    .reload具有 force 選項的/f命令會刪除指定模組的所有符號資訊,並重載符號。 在某些情況下,此命令也會重載或卸除模組本身。

您必須載入適當的符號,才能使用 WinDbg 提供的進階功能。 如果您沒有正確設定符號,當您嘗試使用相依於符號的功能時,您會收到訊息,指出符號無法使用。

0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.

有許多方法可用來處理符號。 在許多情況下,您可以將計算機設定為從 Microsoft 在需要時提供的符號伺服器存取符號。 此實驗室會使用該方法。 如果環境中的符號位於不同的位置,請修改步驟以使用該位置。 如需詳細資訊,請參閱 Windows 調試程式的符號路徑

若要執行來源偵錯,您必須建置已核取 (二進位檔版本的偵錯) 版本。 編譯程式會) (.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 此實驗室,所以輸出的某些元素是您可以選取的熱連結。 選取偵錯輸出中的 [流覽所有全域符號 ] 連結,以顯示以字母 “a” 開頭的專案符號相關信息。

    0: kd> x /D Echo!a*
    
  3. 回應範例不包含以字母 「a」 開頭的任何符號,因此請輸入 x ECHO!Echo* ,以顯示與以 「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
    

顯示 隨插即用 裝置樹狀結構資訊

在本節中,顯示回應範例設備驅動器的相關信息,以及其位於 隨插即用 裝置樹狀結構中的位置。

隨插即用 裝置樹狀目錄中設備驅動器的相關信息,有助於進行疑難解答。 例如,如果設備驅動器不在裝置樹狀結構中,則安裝設備驅動器可能會發生問題。

如需裝置節點偵錯延伸模組的詳細資訊,請參閱 !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 在產生的輸出中搜尋,以尋找設備驅動器的名稱、 回應

    在 WinDbg 中搜尋 'echo' 一詞的 [尋找] 對話框螢幕快照。

  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>輸入 命令以顯示與回應設備驅動器相關聯的 隨插即用 資訊。 使用在計算機上顯示的 PDO 位址,而不是此處顯示的位址 !devnode

    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>輸入 命令以顯示與設備驅動器相關聯的 隨插即用 資訊。 使用在計算機上顯示的 PDO 位址,而不是此範例中顯示的位址 !devnode

    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"
    

輸出會顯示您有相當簡單的設備驅動器堆疊。 Echo 驅動程式是 PnPManager 節點的子系。 PnPManager 是根節點。

\Driver\ECHO
\Driver\PnpManager

下圖顯示更複雜的裝置節點樹狀結構。

說明包含大約20個節點之裝置節點樹狀結構的圖表。

如需更多複雜驅動程式堆疊的詳細資訊,請參閱 驅動程式堆疊裝置節點和裝置堆疊

使用斷點和原始程式碼

在本節中,設定斷點,並逐步執行內核模式原始程式碼。

若要能夠逐步執行程式碼並即時檢查變數的值,請啟用斷點並設定原始碼的路徑。

斷點會在特定程式代碼行停止程式代碼執行。 從該程式代碼中逐步執行,以偵錯該程序代碼的特定區段。

若要使用偵錯命令設定斷點,請使用下列 b 其中一個命令。

命令 描述
bp 設定作用中的斷點,直到卸除其所在的模塊為止。
bu 設定卸除模組時無法解析的斷點,並在模組重載時重新啟用。
bm 設定符號的斷點。 此命令會使用 或適當地使用 bubp 允許通配符 (*) ,以在符合的每個符號上設定斷點,就像類別中的所有方法一樣。

如需詳細資訊,請參閱 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使用 命令來檢查與 echo 驅動程式相關聯的符號,以判斷要用於斷點的函式名稱。 您可以使用通配符或 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 watch 正在載入的驅動程式。

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

    您可以將不同的語法與設定變數搭配使用,例如<module>!<symbol><class>::<method>'<file.cpp>:<line number>'或略過多次 <condition> <#>。 如需詳細資訊,請參閱 WinDbg 和其他 Windows 調試程式中的條件斷點

  6. 列出目前的斷點,以確認已輸入 bl 命令來確認已設定斷點:

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

    此處所示輸出中的 「e」 表示已啟用觸發斷點數位 1。

  7. 輸入 g (go) 命令,以重新啟動目標系統上的程式碼執行。

  8. 在目標系統上,在 Windows 中,使用圖示或輸入 mmc devmgmt.msc 開啟 裝置管理員。 在 裝置管理員 中,展開 [範例] 節點。

  9. 選取並按住或以滑鼠右鍵按下 KMDF 回應驅動程式項目,然後從功能表中選取 [ 停用 ]。

  10. 再次選取並按住或以滑鼠右鍵按下 KMDF 回應驅動程式項目,然後從功能表中選取 [ 啟用 ]。

  11. 在主機系統上,啟用驅動程式時,應該引發 AddDevice 偵錯斷點。 目標系統上的驅動程式程式代碼執行應該會停止。 叫用斷點時,應該在 AddDevice 例程的開頭停止執行。 偵錯指令輸出會顯示 Breakpoint 1 hit

    顯示範例程式代碼局部變數和命令視窗的 WinDbg 螢幕快照。

  12. 輸入 命令或按 F10 逐行逐步 p 執行程式代碼行,直到您到達 AddDevice 例程的下列結尾為止。 醒目提示大括號字元 (}) ,如下所示。

    程式代碼視窗的螢幕快照,其中醒目提示 AddDevice 例程開頭的大括號字元。

在下一節中,檢查 DeviceAdd 程式代碼執行之後變數的狀態。

您可以使用下列命令來修改現有的斷點:

命令 描述
bl 清單 斷點。
bc 從清單中清除斷點。 用來 bc * 清除所有斷點。
bd 停用斷點。 使用 bd * 停用所有斷點。
be 啟用斷點。 使用 be * 來啟用所有斷點。

或者,您也可以修改 WinDbg UI 中的斷點。

您也可以設定在存取記憶體位置時引發的斷點。 ba 使用存取) 命令上的 (中斷,語法如下:

ba <access> <size> <address> {options}
選項 Description
e execute:當 CPU 從位址擷取指令時
r 讀取/寫入:當 CPU 讀取或寫入位址時
w write:當 CPU 寫入位址時

您隨時只能設定四個數據斷點。 您必須確定您已正確對齊數據,以觸發斷點。 單字必須以 2 分隔的地址結尾,dword 必須以 4 分隔,而四個字則以 0 或 8 為單位。

例如,若要在特定記憶體位址上設定讀取/寫入斷點,您可以使用類似此範例的命令。

ba r 4 0x0003f7bf0

您可以使用下列命令來逐步執行程序代碼,並搭配括弧中顯示的相關鍵盤簡短剪下。

  • (Ctrl+Break) 中斷。 只要系統正在執行且與 WinDbg 通訊,此命令會中斷系統。 核心調試程式中的序列為 Ctrl+C。
  • 執行至游標 (F7 或 Ctrl+F10) 。 將游標放在您想要執行中斷的來源或反組譯碼視窗中,然後按 F7。 程式代碼執行會執行到該點。 如果程式代碼執行流程未到達數據指標所指示的點,WinDbg 就不會中斷。 如果未執行 IF 語句,就會發生這種情況。
  • 執行 F5 () 。 執行直到遇到斷點或發生錯誤檢查之類的事件為止。
  • 逐步執行 F10 () 。 此命令會讓程式代碼執行一次繼續一個語句或一個指令。 如果遇到呼叫,程式代碼執行會通過呼叫,而不需要輸入呼叫例程。 如果程式設計語言為 C 或 C++ 且 WinDbg 處於來源模式,則可以使用>偵錯來源模式來開啟或關閉來源模式
  • (F11) 中的步驟。 此命令就像逐步執行,不同之處在於呼叫的執行會進入呼叫例程。
  • 跳 (Shift+F11) 。 此命令會使執行在呼叫堆疊中的目前例程或目前位置執行和結束。 如果您已經看過足夠的例程,此命令會很有用。

如需詳細資訊,請參閱 WinDbg 中的原始程式碼偵錯

檢視變數和呼叫堆疊

在本節中,顯示變數和呼叫堆疊的相關信息。

此實驗室假設您使用稍早所述的程式,在 AddDevice 例程停止。 若要檢視此處顯示的輸出,請視需要重複先前所述的步驟。

在主系統上,若要顯示變數,請使用 檢視>本機 功能表項來顯示局部變數。

顯示局部變數視窗的 WinDbg 螢幕快照。

若要尋找全域變數位址的位置,請輸入 ? <variable name>

  • 跳出 (Shift+F11) – 此命令會導致執行執行,並在呼叫堆疊) (目前的位置執行和結束。 如果您已經看過足夠的例程,這會很有用。

如需詳細資訊,請參閱偵錯參考檔中 的 WinDbg (傳統) 原始程式碼偵錯。

第8節:檢視變數和呼叫堆疊

在第 8 節中,您將顯示變數和呼叫堆疊的相關信息。

此實驗室假設您使用稍早所述的程式,在 AddDevice 例程停止。 若要檢視此處顯示的輸出,請視需要重複先前所述的步驟。

<- 在主機系統上

顯示變數

使用 檢視>本機 功能表項來顯示局部變數。

顯示局部變數視窗的 WinDbg 螢幕快照。

全域變數

您可以輸入 來尋找全域變數位址的位置 ? <變數名稱>

區域變數

您可以輸入 dv 命令,以顯示指定框架之所有局部變數的名稱和值。 若要顯示特定框架之所有局部變數的名稱和值,請輸入 dv 命令:

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

呼叫堆疊是導致程式計數器目前位置的函數調用鏈結。 呼叫堆疊上的頂端函式是目前的函式,下一個函式是呼叫目前函式的函式,依此類故。

若要顯示呼叫堆疊,請使用 k* 命令。

命令 描述
kb 顯示堆疊和前三個參數。
kp 顯示堆疊和參數的完整清單。
kn 可讓您查看堆疊旁的框架資訊。
  1. 在主機系統上,如果您想要讓呼叫堆疊保持可用,請選取 [檢視呼叫堆疊] 加以檢視>。 選取視窗頂端的數據行,以切換顯示其他資訊。

    顯示呼叫堆疊視窗的 WinDbg 螢幕快照。

  2. 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) 呼叫驅動程式架構程式代碼, (WDF) 稍後呼叫 echo 驅動程式函DeviceAdd式。

顯示進程和線程

在本節中,顯示在核心模式中執行之進程和線程的相關信息。

程序

您可以使用 !process 調試程式延伸模組來顯示或設定行程資訊。 設定斷點以檢查播放音效時所使用的程式。

  1. 在主機系統上,輸入 dv 命令以檢查與例程相關聯的 EchoEvtIo 地區設定變數:

    0: kd> dv ECHO!EchoEvtIo*
    ECHO!EchoEvtIoQueueContextDestroy
    ECHO!EchoEvtIoWrite
    ECHO!EchoEvtIoRead         
    
  2. 使用 bc *清除先前的斷點:

    0: kd> bc *  
    
  3. 使用下列命令在 EchoEvtIo 例程上設定符號斷點:

    0: kd> bm ECHO!EchoEvtIo*
      2: aade5490          @!”ECHO!EchoEvtIoQueueContextDestroy”
      3: aade55d0          @!”ECHO!EchoEvtIoWrite”
      4: aade54c0          @!”ECHO!EchoEvtIoRead”
    
  4. 列出斷點,以確認已正確設定斷點:

    0: kd> bl
    1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197]    0001 (0001) ECHO!EchoEvtIoQueueContextDestroy
    ...
    
  5. 輸入 g 重新啟動程式代碼執行:

    0: kd> g
    
  6. 在目標系統上,於 EchoApp.exe 目標系統上執行驅動程式測試程式。

  7. 在主機系統上,當測試應用程式執行時,會呼叫驅動程式中的 I/O 例程。 此呼叫會導致觸發斷點,並在目標系統上執行驅動程式程式代碼會停止。

    Breakpoint 2 hit
    ECHO!EchoEvtIoWrite:
    fffff801`0bf95810 4c89442418      mov     qword ptr [rsp+18h],r8
    
  8. !process使用 命令來顯示與執行 echoapp.exe相關的目前進程:

    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

  9. 使用 來 !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
    
    ...
    
  10. 記錄與 echoapp.exe 相關聯的進程標識符,以便稍後在此實驗室中使用。 您也可以使用 Ctrl+C 將位址複製到複製緩衝區,以供稍後使用。

    _____________________________________________________ (echoapp.exe 行程位址)

  11. 在調試程式中視需要輸入 g ,以向前執行程序代碼 ,直到echoapp.exe 完成執行為止。 它會多次叫用讀取和寫入事件的斷點。 當echoapp.exe 完成時,請按 Ctrl+ScrLk (Ctrl+Break) 來中斷調試程式。

  12. !process使用 命令來確認您正在執行不同的進程。 在此顯示的輸出中, 具有 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 正在執行。

  13. !process使用 命令嘗試查看先前記錄之echoapp.exe 相關聯的進程標識碼。 提供您稍早記錄 的echoapp.exe 行程位址,而不是此範例中顯示的範例進程位址。

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

    進程物件已無法使用,因為 echoapp.exe 進程已不再執行。

執行緒

用來檢視和設定線程的命令類似於進程的命令。 使用 !thread 命令來檢視線程。 使用 .thread 來設定目前的線程。

  1. 在主機系統上,輸入 g 調試程式,以重新啟動目標系統上的程式碼執行。

  2. 在目標系統上,執行 EchoApp.exe 驅動程式測試程式。

  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的映像名稱。 這表示您正在查看與測試應用程式相關聯的線程。

  5. !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
    
  6. !process 0 0使用 命令來找出兩個相關進程的進程位址,並在這裏記錄這些進程位址。

    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 來搜尋輸出。

  7. !process使用 命令來列出執行電腦之兩個進程的進程資訊。 提供 !process 0 0 來自輸出的進程位址,而不是此範例中顯示的位址。

    此範例輸出適用於先前記錄 cmd.exe 進程標識碼。 此行程識別碼的映像名稱 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 進程標識碼。

    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
    ...
    
  8. 在此記錄與兩個進程相關聯的第一個線程位址。

    Cmd.exe:____________________________________________________

    EchoApp.exe:_________________________________________________

  9. !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
    Attached Process          N/A            Image:         N/A
    ...
    

    如預期般,目前的線程是與 echoapp.exe 相關聯的線程,而且處於執行中狀態。

  10. !Thread使用 命令來顯示與 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 相關聯,且處於等候狀態。

  11. 提供等候 CMD.exe 線程的線程位址,將內容變更為該等候線程。

    0: kd> .Thread ffffe0007cf34880
    Implicit thread is now ffffe000`7cf34880
    
  12. 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 表示此線程未如預期般執行。

如需線程和進程的詳細資訊,請參閱下列參考:

IRQL、註冊和結束 WinDbg 工作階段

在本節中,顯示 IRQL) 和緩存器內容的中斷要求層級 (。

檢視已儲存的 IRQL

IRQL 可用來管理中斷服務的優先順序。 每個處理器都有一個 IRQL 設定,線程可以提高或降低。 在處理器 IRQL 設定下方發生的中斷會遮罩,而且不會干擾目前的作業。 處理器 IRQL 設定上方發生的中斷優先順序高於目前的作業。

在主機系統上, !irql 延伸模組會在發生調試程序中斷之前,在目標計算機的目前處理器上顯示 IRQL。 當目標計算機中斷調試程式時,IRQL 會變更,但在儲存調試程式中斷之前生效的 IRQL,而且會顯示 。!irql

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

檢視快取器

在主機系統上,使用 r (Registers) 命令,在目前處理器上顯示目前線程的緩存器內容。

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 (Registers)

在逐步執行元件語言程式代碼執行和其他案例時,檢視緩存器的內容可能會很有説明。 如需元件語言反組譯碼的詳細資訊,請參閱 批注 x86 反 組譯碼和 批註 x64 反組譯碼

如需快取器內容的相關信息,請參閱 x86 架構x64 架構

結束 WinDbg 工作階段

如果您想要讓調試程式保持附加,但想要在目標上運作,請使用 清除任何斷點 bc *,讓目標計算機不會嘗試連線到主計算機調試程式。 g然後使用 命令讓目標計算機再次執行。

若要結束偵錯會話,請在主機系統上中斷調試程式,然後輸入 qd (Quit and Detach) 命令,或從功能表中選取 [ 停止偵 錯]。

0: kd> qd

如需詳細資訊,請參閱 在 WinDbg 中結束偵錯會話

Windows 偵錯資源

如需詳細資訊,請參閱 Windows 偵錯。 其中有些書籍在其範例中使用舊版 Windows,例如 Windows Vista,但討論的概念適用於大部分的 Windows 版本。

另請參閱