偵錯 Windows 驅動程式逐步實驗室 (回應核心模式)
此實驗室介紹 WinDbg 核心調試程式。 您可以使用 WinDbg 來偵錯回應核心模式範例驅動程式程式代碼。
實驗室目標
此實驗室包含介紹偵錯工具的練習、教授常見的偵錯命令、說明斷點的使用,以及示範如何使用偵錯延伸模組。
在此實驗室中,您會使用即時核心偵錯連線來探索下列動作:
- 使用 Windows 調試程式命令
- 使用標準指令(呼叫堆疊、變數、線程、IRQL)
- 使用進階驅動程式偵錯指令 (!commands)
- 使用符號
- 在即時偵錯中設定斷點
- 檢視呼叫堆疊
- 顯示 隨插即用 裝置樹狀結構
- 使用線程和進程內容
使用者和核心模式偵錯
使用 Windows 調試程式時,您可以執行兩種類型的偵錯:
使用者模式 - 應用程式與子系統會在使用者模式的電腦上執行。 在使用者模式中執行的進程會在自己的虛擬位址空間內執行。 它們受限於直接存取系統的許多部分,包括系統硬體、未配置供其使用的記憶體,以及可能會危害系統完整性的系統其他部分。 由於在使用者模式中執行的進程會有效地與系統和其他使用者模式進程隔離,因此它們不會干擾這些資源。
核心模式 - 作業系統和特殊許可權程式會在核心模式中執行。 內核模式程式代碼有權存取系統的任何部分。 它不受限制,例如使用者模式程序代碼。 它可以存取在使用者模式或核心模式中執行的任何其他進程的任何部分。 大部分的核心OS功能和許多硬體設備驅動器都會以核心模式執行。
本練習涵蓋使用者模式和內核模式偵錯期間經常使用的偵錯命令。 此練習也涵蓋偵錯延伸模組,有時稱為 「bang」 !命令,用於內核模式偵錯。
實驗室設定
您需要下列硬體才能完成實驗室:
- 執行 Windows 10 的膝上型電腦或桌面電腦(主機)
- 執行 Windows 10 的第二部膝上型電腦或桌面電腦 (目標)
- 用來連接兩部計算機的網路中樞或路由器和網路纜線
- 存取因特網以下載符號檔
您需要下列軟體才能完成實驗室:
- Visual Studio
- 適用於 Windows 10 的 Windows 軟體開發工具套件 (SDK)
- 適用於 Windows 10 的 Windows 驅動程式套件 (WDK)
- 適用於 Windows 10 的響應驅動程式範例
實驗室有下列各節:
- 聯機到內核模式 WinDbg 工作階段
- 內核模式偵錯命令和技術
- 下載並建置 KMDF 回應驅動程式
- 在目標系統上安裝echo驅動程式範例
- 使用 WinDbg 來顯示驅動程式的相關信息
- 顯示 隨插即用 裝置樹狀結構資訊
- 使用斷點和原始程式碼
- 檢視變數和呼叫堆疊
- 顯示進程和線程
- IRQL、註冊和結束 WinDbg 工作階段
- Windows 偵錯資源
聯機到內核模式 WinDbg 工作階段
在本節中,設定主機和目標系統上的網路偵錯。
此實驗室中的計算機必須設定為使用乙太網路連線進行核心偵錯。
此實驗室使用兩部計算機。 Windows 調試程式會在 主機 系統上執行,而核心模式驅動程式架構 (KMDF) 回應驅動程式會在 目標 系統上執行。
使用網路中樞或路由器和網路纜線來連接兩部計算機。
若要使用內核模式應用程式並使用 WinDbg,建議您使用透過乙太網路傳輸的 KDNET。 如需如何使用乙太網路傳輸通訊協定的資訊,請參閱 開始使用 WinDbg (核心模式) 。 如需設定目標計算機的詳細資訊,請參閱 準備計算機以進行手動驅動程式部署 和 自動設定 KDNET 網路核心偵錯。
使用乙太網路設定內核模式偵錯
若要在目標系統上啟用內核模式偵錯:
在主機系統上,開啟 [命令提示字元] 視窗,然後輸入 ipconfig 以判斷其 IPv4 位址。
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 . . . . . . . . . :
記錄主機系統的 IP 位址:______________________________________
在目標系統上,開啟 [命令提示字元] 視窗,並使用
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 和安全開機。 測試完成時重新啟用這些安全性功能。 在停用安全性功能時,適當地管理測試計算機。 安全開機通常會在 UEFI 中停用。 若要存取 UEFI 設定,請使用系統、復原、進階啟動。 重新啟動時,選取 [疑難解答]、[進階選項]、[UEFI 韌體設定]。 請小心,因為未正確設定 UEFI 選項或停用 BitLocker,可能會使系統無法運作。
在目標電腦上,以系統管理員身分開啟命令提示字元視窗。 輸入此指令以開啟偵錯:
bcdedit /set {default} DEBUG YES
輸入此指令以啟用測試簽署:
bcdedit /set TESTSIGNING ON
輸入此命令以設定主機系統的IP位址。 使用您稍早記錄之主機系統的IP位址,而不是顯示的IP位址。
bcdedit /dbgsettings net hostip:192.168.1.1 port:50000 key:2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
警告
若要提高連線的安全性,並降低隨機用戶端調試程式連線要求的風險,請使用自動產生的隨機密鑰。 如需詳細資訊,請參閱 自動設定 KDNET 網路核心偵錯。
輸入此指令以確認
dbgsettings
的值已正確設定:bcdedit /dbgsettings
key 2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p debugtype NET hostip 169.168.1.1 port 50000 dhcp Yes The operation completed successfully.
注意
如果您收到來自防火牆的訊息,而且您想要使用調試程式,請選取這三個方塊。
在主電腦上,以系統管理員身分開啟命令提示字元視窗。 此實驗室使用 Windows 驅動程式套件 (WDK) 中安裝的 x64 版本 WinDbg.exe ,作為 Windows 套件安裝的一部分。 變更為預設 WinDbg 目錄,預設位置如下所示。
cd C:\Program Files(x86)\Windows Kits\10\Debuggers\x64
此實驗室假設這兩部計算機在目標和主機上都執行64位版本的Windows。 如果情況並非如此,最好的方法是在目標執行所在的主機上執行相同的 工具位 。 例如,如果目標執行 32 位 Windows,請在主機上執行 32 位版本的調試程式。 如需詳細資訊,請參閱 選擇 32 位或 64 位偵錯工具。
使用下列命令以遠端使用者偵錯開啟 WinDbg。 索引鍵和埠的值符合您稍早在目標計算機上使用 BCDEdit 所設定的值。
WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
重新啟動目標系統。
在一兩分鐘內,偵錯輸出應該會顯示在主機系統上。
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) 顯示文字,您可以選取以快速收集詳細資訊。
在主機系統上,使用 WinDBg 中的 Ctrl+Scroll Lock 來中斷在目標系統上執行的程式代碼。 目標系統可能需要一些時間才能回應。
在 [除錯程式指令] 視窗中輸入下列命令以啟用 DML:
0: kd> .prefer_dml 1 DML versions of commands on by default
您可以使用 命令存取參考命令說明
.hh
。 輸入下列命令以檢視 的.prefer_dml
命令參考說明:0: kd> .hh .prefer_dml
調試程序說明檔會顯示命令的說明
.prefer_dml
。若要在目標系統上顯示詳細的版本資訊,請在 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
若要確認您使用的是正確的內核模式程式,請在 WinDbg 視窗中輸入 lm (List Loaded Modules) 命令,以顯示載入的模組:
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 ...
省略的輸出會以 “...”在此實驗室中。
若要要求特定模組的詳細資訊,請使用
v
(verbose) 選項: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 範例驅動程式:
首先,從 GitHub 下載並擷取 KMDF 回應範例。
KMDF Echo 範例位於 一般 資料夾中。
在一個 zip 檔案中下載驅動程式範例: 驅動程式範例
將 zip 檔案下載到本機硬碟。
選取並按住或以滑鼠右鍵按兩下 zip 檔案,然後選取[ 全部解壓縮]。 指定新的資料夾,或瀏覽至現有的資料夾來儲存解壓縮的檔案。 例如,您可以將 C:\DriverSamples\ 指定為要在其中擷取檔案的新資料夾。
擷取檔案之後,請移至下列子資料夾: C:\DriverSamples\general\echo\kmdf
在 Microsoft Visual Studio 中,選取 [檔案>開啟>專案/方案...],然後移至包含解壓縮文件的資料夾,例如 C:\DriverSamples\general\echo\kmdf。 按兩下 kmdfecho 方案檔案加以開啟。
在 Visual Studio 中,找出 方案總管。 如果此視窗尚未開啟,請從 [檢視] 功能選取 [方案總管]。 在 方案總管 中,您可以看到一個有三個項目的解決方案。
設定範例的組態和平臺。 在 方案總管 中,選取並按住或以滑鼠右鍵按兩下 [方案 'kmdfecho' [3 個專案],然後選取 [Configuration Manager]。 請確定這三個專案的組態和平台設定都相同。 根據預設,組態會設定為 Win10 Debug,而平臺會針對所有項目設定為 Win64 。 如果您對一個項目進行任何組態或平台變更,請對其餘三個項目進行相同的變更。
驅動程式範例必須修改,才能使用未與現有驅動程式重疊的值。 請參閱從範例程式代碼到生產驅動程式 - 範例中要變更的內容,瞭解如何建立唯一的驅動程式範例,以與 Windows 中已安裝的現有實際驅動程式共存。
設定運行時間連結庫。 開啟 echo 驅動程式屬性頁,並找出 C/C++>Code 產生。 將運行時間連結庫變更為多線程偵錯 (/MTd)。 如需組建選項的詳細資訊,請參閱 /MD、/MT、/LD(使用運行時間連結庫)。
在驅動程式屬性中,確定 [驅動程式簽署簽署>模式] 已設定為 [測試簽署]。
在 Visual Studio 中,選取 [組建]>[組建解決方案]。
建置視窗應該會顯示訊息,指出這三個項目的組建都成功。
提示
如果您遇到組建錯誤訊息,請使用組建錯誤編號來判斷修正。 例如, MSBuild 錯誤MSB8040 描述如何使用可降低規格的連結庫。
在 檔案總管 中,移至包含範例解壓縮檔案的資料夾。 例如,如果這是您稍早指定的資料夾,請移至 C:\DriverSamples\general\echo\kmdf。 在該資料夾中,已編譯驅動程式檔案的位置會根據您在 Configuration Manager 中選取的組態和平台設定而有所不同。 如果您保留預設設定不變,則編譯的驅動程式檔案會儲存至名為 \x64\Debug 的資料夾,以供 64 位偵錯組建使用。
移至包含自動同步驅動程式建置檔案的資料夾: 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驅動程式通訊的命令提示字元可執行檔。 找出 USB 拇指磁碟驅動器,或設定網路共用,將建置的驅動程式檔案和測試 EchoApp 從主機複製到目標系統。
在下一節中,將程式代碼複製到目標系統,然後安裝及測試驅動程式。
在目標系統上安裝 KMDF 回應驅動程式範例
在本節中,使用 DevCon 工具來安裝回應範例驅動程式。
您安裝驅動程式的電腦稱為 目標電腦 或 測試計算機。 一般而言,這部計算機與您開發及建置驅動程式套件的計算機不同。 您開發和建置驅動程式的計算機稱為 主計算機。
將驅動程式套件移至目標計算機並安裝驅動程式的程式稱為 部署 驅動程式。
部署測試簽署驅動程式之前,請先啟用測試簽署來準備目標計算機。 您也需要在 WDK 安裝中找到 DevCon 工具,並將此工具複製到目標系統。
若要在目標系統上安裝驅動程式,請執行下列步驟。
在目標系統上,啟用測試簽署的驅動程式:
開啟 [Windows 設定]。
在 [更新和安全性] 中,選取 [復原]。
在 [進階啟動] 底下,選取 [立即重新啟動]。
當電腦重新啟動時,請選取 [ 啟動選項]。 在 Windows 10 中,選取 [疑難解答>進階選項>啟動設定],然後選取 [重新啟動]。
按 F7 鍵選取 [停用驅動程序簽章強制執行]。
重新啟動目標電腦。
在主機系統上,移至 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
此時會出現一個對話框,指出測試驅動程式是未簽署的驅動程式。 請選取 [ 無論如何 安裝此驅動程式] 繼續進行。
提示
如果您有安裝任何問題,請檢查下列檔案以取得詳細資訊。 %windir%\inf\setupapi.dev.log
成功安裝範例驅動程序之後,您就可以進行測試。
在目標計算機上,在 [命令提示字元] 視窗中,輸入 devmgmt 以開啟 裝置管理員。 在 [裝置管理員] 的 [檢視] 功能表上,依類型選擇 [裝置]。在裝置樹狀目錄中,於 [範例裝置] 節點中找到 [範例 WDF Echo Driver]。
輸入 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 回應範例驅動程式的相關信息。
若要檢視驅動程序的相關信息:
在主機系統上,如果您關閉調試程式,請在系統管理員命令提示字元視窗中使用下列命令再次開啟它。
WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
使用 Ctrl+Break (Scroll Lock) 來中斷在目標系統上執行的程序代碼。
若要在 WinDbg 環境中將符號路徑設定為Microsoft符號伺服器,請使用
.symfix
命令。0: kd> .symfix
若要新增本機符號位置以使用本機符號,請使用 和 新增
.sympath+
路徑.reload /f
。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
在調試程式的命令區域中輸入下列命令,以顯示響應驅動程式的相關信息:
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。
由於此實驗室稍早設定
prefer_dml
,因此輸出的某些元素是您可以選取的熱門連結。 選取偵錯輸出中的 [ 流覽所有全域符號 ] 連結,以顯示以字母 “a” 開頭的專案符號相關信息。0: kd> x /D Echo!a*
回應範例不包含以字母 「a」 開頭的任何符號,因此輸入
x 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(檢查符號)。
延伸
!lmi
模組會顯示模組的詳細資訊。 輸入!lmi echo
。 您的輸出應該類似此範例所示的文字:0: kd> !lmi echo Loaded Module Info: [echo] Module: ECHO Base Address: fffff8010bf94000 Image Name: ECHO.sys …
!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 ...
輸入下列命令來變更預設偵錯位掩碼,讓來自目標系統的所有偵錯訊息都會顯示在調試程式中:
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。
在主機系統上,若要查看 隨插即用 裝置樹狀目錄中的所有裝置節點,請輸入
!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… …
使用 Ctrl+F 在產生的輸出中搜尋,以尋找設備驅動器的名稱回應。
應載入回應裝置驅動程式。
!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) …
上一個命令中顯示的輸出包含與驅動程式執行中實例相關聯的 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.
命令中顯示的
!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"
輸出會顯示您有相當簡單的設備驅動器堆疊。 響應驅動程式是 PnPManager 節點的子系。 PnPManager 是根節點。
\Driver\ECHO
\Driver\PnpManager
此圖顯示更複雜的裝置節點樹狀結構。
如需更多複雜驅動程式堆疊的詳細資訊,請參閱 驅動程式堆疊 和 裝置節點和裝置堆疊。
使用斷點和原始程式碼
在本節中,設定斷點,並透過內核模式原始程式碼進行單一步驟。
若要能夠逐步執行程式碼並即時檢查變數的值,請啟用斷點並設定原始碼的路徑。
斷點會在特定程式代碼行停止程式代碼執行。 從該點往前逐步執行程序代碼,以偵錯該程式代碼的特定區段。
若要使用偵錯命令設定斷點,請使用下列 b
其中一個命令。
Command | 說明 |
---|---|
bp |
設定作用中的斷點,直到卸除其位於 的模組為止。 |
bu |
設定在卸除模組時無法解析的斷點,並在模組重載時重新啟用。 |
bm |
設定符號的斷點。 此命令會使用 bu 或 bp 適當地,並允許使用通配符 (* ) 在符合的每個符號上設定斷點,就像類別中的所有方法一樣。 |
如需詳細資訊,請參閱 WinDbg 中的原始程式碼偵錯。
在主機系統上,使用 WinDbg UI 確認>目前 WinDbg 工作階段中已啟用偵錯來源模式。
輸入下列命令,將本機程式代碼位置新增至來源路徑:
.srcpath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
輸入下列命令,將本機符號位置新增至符號路徑:
.sympath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
x
使用 命令來檢查與響應驅動程式相關聯的符號,以判斷要用於斷點的函式名稱。 您可以使用通配符或 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
。或者,請檢閱原始程式碼,以尋找斷點的函式名稱。
使用驅動程式的名稱設定斷點
bm
,後面接著函式名稱,例如AddDevice
,您想要設定斷點,並以驚嘆號分隔。 此實驗室會使用AddDevice
來監看載入的驅動程式。0: kd> bm ECHO!EchoEvtDeviceAdd 1: fffff801`0bf9b1c0 @!"ECHO!EchoEvtDeviceAdd"
您可以搭配使用不同的語法來設定 、、 或 等變數
<module>!<symbol>
,或略過多次<class>::<method>
。'<file.cpp>:<line number>'
<condition> <#>
如需詳細資訊,請參閱 WinDbg 和其他 Windows 調試程式中的條件式斷點。列出目前的斷點,藉由輸入
bl
命令來確認已設定斷點:0: kd> bl 1 e fffff801`0bf9b1c0 0001 (0001) ECHO!EchoEvtDeviceAdd
此處所示輸出中的 「e」 表示已啟用斷點數位 1 來引發。
輸入
g
(go) 命令,以重新啟動目標系統上的程式碼執行。在目標系統上,在 Windows 中,使用圖示開啟 裝置管理員,或輸入 mmc devmgmt.msc。 在 裝置管理員 中,展開 [範例] 節點。
選取並按住或以滑鼠右鍵按下 KMDF 回應驅動程式項目,然後從功能表中選取 [ 停用 ]。
再次選取並按住或以滑鼠右鍵按下 KMDF 回應驅動程式項目,然後從功能表中選取 [ 啟用 ]。
在主機系統上,啟用驅動程式時, 應該引發 AddDevice 偵錯斷點。 目標系統上的驅動程式程式代碼執行應該會停止。 叫用斷點時,應該在 AddDevice 例程的開頭停止執行。 偵錯指令輸出會顯示
Breakpoint 1 hit
。輸入 命令或按 F10 逐行
p
逐步執行程式代碼行,直到您到達 AddDevice 例程的下列結尾為止。 大括號字元 (}
) 會反白顯示,如下所示。
在下一節中,檢查 DeviceAdd 程式代碼執行之後變數的狀態。
您可以使用下列命令來修改現有的斷點:
Command | 說明 |
---|---|
bl |
列出斷點。 |
bc |
從清單中清除斷點。 使用 bc * 來清除所有斷點。 |
bd |
停用斷點。 使用 bd * 停用所有斷點。 |
be |
啟用斷點。 使用 be * 來啟用所有斷點。 |
或者,您也可以修改 WinDbg UI 中的斷點。
您也可以設定在存取記憶體位置時引發的斷點。 使用 [ ba
存取中斷] 命令,語法如下:
ba <access> <size> <address> {options}
選項 | 說明 |
---|---|
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 例程停止。 若要檢視此處顯示的輸出,請視需要重複先前所述的步驟。
在主系統上,若要顯示變數,請使用檢視>本機功能表項來顯示局部變數。
若要尋找全域變數位址的位置,請輸入 ? <variable name>
。
- 跳出 (Shift+F11) - 此命令會執行到目前的例程,並從目前的例程結束(呼叫堆棧中的目前位置)。 如果您已經看到足夠的例程,這會很有用。
如需詳細資訊,請參閱 偵錯參考檔中的 WinDbg (傳統) 原始程式碼偵錯。
第8節:檢視變數和呼叫堆疊
在第 8 節中,您將顯示變數和呼叫堆疊的相關信息。
此實驗室假設您已使用稍早所述的程式,在 AddDevice 例程上停止。 若要檢視此處顯示的輸出,請視需要重複先前所述的步驟。
<- 在主機系統上
顯示變數
使用檢視>功能表項來顯示局部變數。
全域變數
您可以輸入 來尋找全域變數位址的位置? <變數名稱>。
局部變數
您可以輸入 dv 命令,顯示指定框架之所有局部變數的名稱和值。
若要顯示特定框架之所有局部變數的名稱和值,請輸入 dv
命令:
0: kd> dv
Driver = 0x00001fff`7ff9c838
DeviceInit = 0xffffd001`51978190
status = 0n0
呼叫堆疊是導致程式計數器目前位置的函式呼叫鏈結。 呼叫堆疊上的頂端函式是目前的函式,而下一個函式是呼叫目前函式的函式,依此命名。
若要顯示呼叫堆疊,請使用 k*
命令。
Command | 說明 |
---|---|
kb |
顯示堆疊和前三個參數。 |
kp |
顯示堆疊和參數的完整清單。 |
kn |
可讓您查看堆疊,其中包含其旁的框架資訊。 |
在主機系統上,如果您想要保留可用的呼叫堆疊,請選取檢視>呼叫堆疊以檢視它。 選取視窗頂端的數據行,以切換顯示其他資訊。
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] ...
呼叫堆疊會顯示呼叫至 隨插即用 程式代碼 (PnP) 的核心 (nt),該程式代碼稱為驅動程式架構程式代碼 (WDF),稍後會呼叫 echo 驅動程式函DeviceAdd
式。
顯示進程和線程
在本節中,顯示核心模式中執行之進程和線程的相關信息。
程序
您可以使用 !process 調試程式延伸模組來顯示或設定行程資訊。 設定斷點來檢查播放音效時所使用的程式。
在主機系統上,輸入
dv
命令來檢查與EchoEvtIo
例程相關聯的地區設定變數:0: kd> dv ECHO!EchoEvtIo* ECHO!EchoEvtIoQueueContextDestroy ECHO!EchoEvtIoWrite ECHO!EchoEvtIoRead
使用
bc *
清除先前的斷點:0: kd> bc *
使用下列命令在
EchoEvtIo
例程上設定符號斷點:0: kd> bm ECHO!EchoEvtIo* 2: aade5490 @!”ECHO!EchoEvtIoQueueContextDestroy” 3: aade55d0 @!”ECHO!EchoEvtIoWrite” 4: aade54c0 @!”ECHO!EchoEvtIoRead”
列出斷點,以確認斷點已正確設定:
0: kd> bl 1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197] 0001 (0001) ECHO!EchoEvtIoQueueContextDestroy ...
輸入
g
重新啟動程式代碼執行:0: kd> g
在目標系統上,在
EchoApp.exe
目標系統上執行驅動程式測試程式。在主機系統上,當測試應用程式執行時,會呼叫驅動程式中的 I/O 例程。 此呼叫會導致斷點引發,並在目標系統上執行驅動程式程式代碼會停止。
Breakpoint 2 hit ECHO!EchoEvtIoWrite: fffff801`0bf95810 4c89442418 mov qword ptr [rsp+18h],r8
!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。
!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 ...
記錄與 echoapp.exe 相關聯的進程標識符,以供本實驗室稍後使用。 您也可以使用 Ctrl+C 將位址複製到複製緩衝區,以供稍後使用。
_____________________________________________________(echoapp.exe行程位址)
在調試程式中視需要輸入
g
,以向前執行程序代碼,直到 echoapp.exe 完成執行為止。 它會多次叫用讀取和寫入事件中的斷點。 當echoapp.exe完成時,請按 Ctrl+ScrLk (Ctrl+Break) 以進入調試程式。!process
使用 命令來確認您正在執行不同的進程。 在此顯示的輸出中,系統影像值的程式與 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 正在執行。
!process
使用 命令嘗試查看與您先前記錄echoapp.exe相關聯的進程標識碼。 提供您稍早記錄的echoapp.exe進程位址,而不是此範例中顯示的範例進程位址。0: kd> !process ffffe0007e6a7780 TYPE mismatch for process object at 82a9acc0
進程物件已無法使用,因為 echoapp.exe 進程不再執行。
執行緒
用來檢視和設定線程的命令類似於進程的命令。 使用 !thread 命令來檢視線程。 使用 .thread 來設定目前的線程。
在主機系統上,輸入
g
調試程式以重新啟動目標系統上的程式代碼執行。在目標系統上,執行EchoApp.exe驅動程式測試程式。
在主機系統上,會叫用斷點並停止程式代碼執行。
Breakpoint 4 hit ECHO!EchoEvtIoRead: aade54c0 55 push ebp
若要檢視正在執行的線程,請輸入 !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的影像名稱。 這表示您正在查看與測試應用程式相關聯的線程。
!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
!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 來搜尋輸出。!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 ...
在此記錄與兩個進程相關聯的第一個線程位址。
Cmd.exe:____________________________________________________
EchoApp.exe:_________________________________________________
!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 相關聯的線程,且處於執行中狀態。
!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相關聯, 且處於等候狀態。
提供等候 CMD.exe 線程的線程位址,以將內容變更為該等候線程。
0: kd> .Thread ffffe0007cf34880 Implicit thread is now ffffe000`7cf34880
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。
書籍
- Mario Hewardt 和 Daniel Pravat 的進階 Windows 偵錯
- Windows 偵錯內部:Tarik Soulami 在 Windows® 中偵錯和追蹤策略的實用指南
- 帕維爾·約西夫維奇、亞歷克斯·伊內斯庫、馬克·魯西諾維奇和大衛·所羅門的 Windows 內部
影片
訓練廠商