Windows核心開發-5-(2)-核心模式除錯
普通使用者模式的除錯,採取的是給程序新增一個執行緒來掛起斷點,作為一個偵錯程式的執行緒在程序中使用。照這樣來類推,對作業系統除錯相當於新增一個程序來限制作業系統,所以作業系統是會被凍結的。這樣的話就不能直接在本機電腦上進行除錯了,不然電腦就卡住了。而且還容易出現問題。最好的辦法是建立一個虛擬機器,用一臺主力機給一臺專門用來測試的計算機除錯。
測試機和主力機必須通過一種方式來連線,選擇有很多,最好的選擇是通過網路連線,但是網路連線要求target和host至少是Win8以上,Win7就很尷尬了,但是由於這個很多搞安全的要求相容,就會很麻煩。以至於很多采用串列埠連線,這裡我們將如何建立串列埠連線。
還有需要注意的就是這個作業系統的版本和位數。你要開發什麼樣子的就用什麼樣子的作業系統。比如說:你要開發一個在Win10 64位計算機上用的東西,你就裝一個Win10 64位虛擬機器。雖然大部分都有相容的效果,比如在64位上能跑32位的程式,但是還是建議採用對應的作業系統版本。
搭建核心模式除錯環境
這裡我採用的是Win10 32位虛擬機器,和Win10 64位本機,採用串列埠連線。
下載作業系統
這個在msdn上下載你需要的對應版本的作業系統就好:
https://msdn.itellyou.cn/,安裝虛擬機器如果不清楚就自行百度一下。
新增啟動引導
給測試機新增啟動引導,需要使用管理員模式啟動命令列:
cmd管理員身份執行bcdedit
bcdedit /copy {current} /d Sna1lGo//這裡的Sna1lGo是引導名稱,自己隨意設定。
bcdedit /displayorder {xxxxx-xxxx-xxx} /addlast //這裡的xxx是你在設定了引導名稱後的一長條字串
//這裡的addlast是引導的位置,last表示是最後
bcdedit /dbgsettings SERIAL DEBUGPORT:1 BAUDRATE:115200 //設定除錯埠波特率
bcdedit /debug {xxxxx-xxxx-xxx} ON//對新加的啟動項增加除錯功能
bcdedit /timeout 20//選擇等待時長
設定完成後,再開機就有系統啟動引導了。
虛擬機器設定:
新增串列埠:(如果你的虛擬機器裡面有印表機,印表機預設會佔用一個名為//./pipe/com_1的串列埠)
命名隨意,只要是//./pipe/xxx就行,這裡我採用的是把印表機移除掉,然後命名為//./pipe/com_1。
WinDbg配置
給WinDbg配置當啟動的時候自動連線到測試機。首先根據測試機的位數選擇同樣的WinDbg,這裡我選擇32位的WinDbg,然後弄了一個快捷方式在桌面。
快捷方式這裡有一個目標,在這個目標的後面新增引數:
-k com:port=//./pipe/com_1,baud=115200,pipe
這裡的引數是和前面一一對應的,如果有問題就自己找找前面的定義。然後就可以直接執行WinDbg來除錯Windows了。
給WinDbg配置符號
符號就是說函式名稱的配置,如果不配置函式名稱不完整,大概可以先這樣理解。
在WinDbg中選擇Symbol Search Path(快捷鍵Ctrl+S):
然後輸入:
srv*D:\symbol*;srv*D:\symbol*http://msdl.microsoft.com/download/symbols
這段指令的意思是,會在D:\symbol中儲存符號表,如果沒有就到後面那個http:地址下載,然後存放到前面那個地址,這個存放的地址可以自己選擇。然後就完美了,大功告成。
開始核心除錯:
這裡採用之前在第四章寫的簡單完整驅動來除錯。
Windows核心驅動--實現修改執行緒優先順序demo - Sna1lGo - 部落格園 (cnblogs.com)這裡下載例子。
然後將生成的sys和pdb檔案一起復制到虛擬機器裡面,然後安裝驅動但是不載入驅動。參考該部落格來安裝驅動:Windows核心開發-2-開始核心開發-2-核心開發入門 - Sna1lGo - 部落格園 (cnblogs.com)
進入WinDbg後,給我們自己寫的入口函式打一個斷點:
bu prioritybooster!driverentry
這裡採用的是bu斷點:bu 命令是針對某個符號下斷點。 比如 bu MyApp!SomeFunction 。 在程式碼被修改之後, 該斷點可以隨著函式地址改變而自動更新到最新位置。 而且bu 斷點會儲存在WinDbg工作空間中, 下次啟動 Windbg 的時候該斷點會自動設定上去。另外,在模組沒有被載入的時候,bp 斷點會失敗(因為函式地址不存在),而bu 斷點則可以成功。 新版的WinDBG中 bp失敗後會自動被轉成bu 。
打下斷點後,我們在WinDbg命令列中輸入g,讓系統跑起來,然後再在系統中去載入該驅動。
如果一切順利的話會出現下面這樣:
就可以像一些平常的偵錯程式一樣來除錯東西了。
輸入k指令來檢視堆疊:
1: kd> k
# ChildEBP RetAddr
00 8985fad8 81dac709 PriorityBooster!DriverEntry [D:\ProjectSum\Driver\PriorityBooster\PriorityBooster.cpp @ 14]
01 8985fbc8 81e3552c nt!IopLoadDriver+0x443
02 8985fbe8 81aefa6a nt!IopLoadUnloadDriver+0x42
03 8985fc38 81abe0f0 nt!ExpWorkerThread+0xea
04 8985fc70 81b9a18d nt!PspSystemThreadStartup+0x4a
05 8985fc7c 00000000 nt!KiThreadStartup+0x15
如果斷點似乎無法設定,則可能是符號問題。 執行 .reload 命令重新載入符號來檢視問題是否已解決。 在使用者空間設定斷點也是可能的,但首先執行 .reload /user 來解決這個問題。
還可以在命令中新增-p來限制給某某程序打斷點,總之WinDbg非常強大,好好學習吧。
總結:
WinDbg其實就是一個偵錯程式,只不過可以除錯核心。對於除錯使用者層的程式碼來說和別的沒什麼區別只是可能更強大官方一點。而核心模式就最好還是雙機除錯。搭建核心除錯環境是非常重要的,因為除錯可以讓我們更加深入的,一步一步的看完所有程式碼非常好用。至於WinDbg的使用方法,大家多嘗試,熟練了就好了。可以看看這本書來熟悉WinDbg:http://www.windbg.info/download/doc/pdf/WinDbg_A_to_Z_bw2.pdf