你可以從微軟網(wǎng)站上下載到的調(diào)試器:
· KD-內(nèi)核調(diào)試器。你可以用它來調(diào)試藍(lán)屏一類的系統(tǒng)問題。如果是開發(fā)設(shè)備驅(qū)動程序是少不了它的。
· CDB-命令行調(diào)試器。這是一個命令行程序
· NTSD-NT調(diào)試器。這是一個用戶模式調(diào)試器,可以用來調(diào)試用戶模式應(yīng)用程序。它實際上是一個CDB的windows UI增強。
· WinDbg-用一個漂亮的UI包裝了KD和NTSD。WinDbg即可以調(diào)試內(nèi)核模式,也可以調(diào)試用戶模式程序。
· VS, VS.net-使用同KD和NTSD相同的調(diào)試引擎,并且相比于同樣用于調(diào)試目的的WinDbg,提供了功能更豐富的界面。
WinDbg實際上包裝了NTSD和KD并且提供了一個更好用的用戶界面。它也提供了命令行開關(guān),比如最小化啟動(-m),附加到一PID指定的進(jìn)程(-p)以及自動打開崩潰文件(-z)。它支持三種類型的命令。
· Regular commands(比如: k) 用來調(diào)試進(jìn)程
· Dot commands(比如:.sympath)用來控制調(diào)試器
· Extension commands(比如: !handle)-這些命令屬于可以用來添加到WinDbg的自定義命令;它們用擴(kuò)展DLL的輸出函數(shù)來實現(xiàn)。
PDB文件
PDB文件, 是鏈接器生成程序數(shù)據(jù)庫文件(Program database files)。私有的PDB文件包括私有以及公有符號,源代碼行號,類型,局部以及全局變量。公有的PDB文件不包含類型,局部變量以及源代碼行號信息。
配置WinDbg
運行WinDbg->菜單->File->Symbol File Path->按照下面的方法設(shè)置_NT_SYMBOL_PATH變量:
在彈出的框中輸入“C:\MyCodesSymbols; SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols”(按照這樣設(shè)置,WinDbg將先從本地文件夾C:\MyCodesSymbols中查找Symbol,如果找不到,則自動從MS的Symbol Server上下載Symbols)。另一種做法是從這個Symbol下載地址中http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx,下載相應(yīng)操作系統(tǒng)所需要的完整的Symbol安裝包,并進(jìn)行安裝,例如我將其安裝在D:\WINDOWS\Symbols,在該框中輸入“D:\WINDOWS\Symbols”。(這里要注意下載的Symbols的版本一定要正確,在我的Win2003+Sp1上,我曾經(jīng)以為安裝Win2003+Sp2的Symbols可能會牛×點,但結(jié)果證明我錯了,用WinDbg打開可執(zhí)行文件時,提示“PDB symbol for mscorwks.dll not loaded;Defaulted to export symbols for ntdll.dll”的錯誤,我有重新裝上Win2003+Sp1的Symbols, 現(xiàn)在一切運行正常^_^)
set _NT_SYMBOL_PATH=srv*C:\MySymbols*http://msdl.microsoft.com/download/symbols
WINDBG命令
調(diào)試前的必備工作
在開始調(diào)試前首先要做的工作是設(shè)置好符號(Symbols)路徑。沒有符號,你看到的調(diào)用堆棧基本上毫無意義。Microsoft的操作系統(tǒng)符號文件(PDB)是對外公開的。另外請注意在編譯你自己的程序選擇生成PDB文件的選項。如果設(shè)置好符號路徑后,調(diào)用堆棧看起來還是不對。可以使用lm, !sym noisy, !reload 等命令來驗證符號路徑是否正確。
Windbg也支持源碼級的調(diào)試。在開始源碼調(diào)試前,你需要用.srcpath設(shè)置源代碼路徑。如果你是在生成所執(zhí)行代碼的機器上進(jìn)行調(diào)試,符號文件中的源碼路徑會指向正確的位置,所以不需要設(shè)置源代碼路徑。如果所執(zhí)行代碼是在另一臺機器上生成的,你可以將所用的源碼拷貝(保持原有的目錄結(jié)構(gòu))的一個可以訪問的文件夾(可以是網(wǎng)絡(luò)路徑)并將源代碼路徑設(shè)為該文件夾的路徑。注意如果是遠(yuǎn)程調(diào)試,你需要使用.lsrcpath來設(shè)置源碼路徑。
2)啟動Debugger
Windbg可以用于如下三種調(diào)試:
(1)遠(yuǎn)程調(diào)試:你可以從機器A上調(diào)試在機器B上執(zhí)行的程序。具體步驟如下:
在機器B上啟動一個調(diào)試窗口(Debug Session)。你可以直接在Windbg下運行一個程序或者將Windbg附加(Attach)到一個進(jìn)程。
在機器B的Windbg命令窗口上啟動一個遠(yuǎn)程調(diào)試接口(remote):
.server npipe:pipe=PIPE_NAME
PIPE_NAME是該接口的名字。
在機器A上運行:
windbg –remote npipe:server=SERVER_NAME,pipe=PIPE_NAME
SERVER_NAME是機器B的名字。
Dump文件調(diào)試:如果在你的客戶的機器上出現(xiàn)問題,你可能不能使用遠(yuǎn)程調(diào)試來解決問題。你可以要求你的用戶將Windbg附加到出現(xiàn)問題的進(jìn)程上,然后在命令窗口中輸入:
.dump /ma File Name
創(chuàng)建一個Dump文件。在得到Dump文件后,使用如下的命令來打開它:
windbg –z DUMP_FILE_NAME
(2)本地進(jìn)程調(diào)試:你可以在Windbg下直接運行一個程序:
Windbg “path to executable” arguments
也可以將Windbg附加到一個正在運行的程序:
Windbg –p “process id”
Windbg –pn “process name”
注意有一種非侵入(Noninvasive)模式可以用來檢查一個進(jìn)程的狀態(tài)并不進(jìn)程的執(zhí)行。當(dāng)然在這種模式下無法控制被調(diào)試程序的執(zhí)行。這種模式也可以用于查看一個已經(jīng)在Debugger控制下運行的進(jìn)程。具體命令如下:
Windbg –pv –p “process id”
Windbg –pv –pn “process name”
(3)調(diào)試多個進(jìn)程和線程
如果你想控制一個進(jìn)程以及它的子進(jìn)程的執(zhí)行,在Windbg的命令行上加上-o選項。Windbg中還有一個新的命令.childdbg 可以用來控制子進(jìn)程的調(diào)試。如果你同時調(diào)試幾個進(jìn)程,可以使用 | 命令來顯示并切換到不同的進(jìn)程。
在同一個進(jìn)程中可能有多個線程。~命令可以用來顯示和切換線程。
.hh keyword 如何得到幫助
靜態(tài)命令:
顯示調(diào)用堆棧:在連接到一個調(diào)試窗口后,首先要知道的就是程序當(dāng)前的執(zhí)行情況k* 命令顯示當(dāng)前線程的堆棧。~*kb會顯示所有線程的調(diào)用堆棧。如果堆棧太長,Windbg只會顯示堆棧的一部分。.kframes可以用來設(shè)置缺省顯示框架數(shù)。
顯示局部變量:接下來要做通常是用dv顯示局部變量的信息。CTRL+ALT+V可以切換到更詳細(xì)的顯示模式。關(guān)于dv要注意的是在優(yōu)化過的代碼中dv的輸出極有可能是不準(zhǔn)確的。這時后你能做的就是閱讀匯編代碼來發(fā)現(xiàn)你感興趣的值是否存儲在寄存器中或堆棧上。有時后當(dāng)前的框架(Frame)上可能找不到你想知道的數(shù)據(jù)。如果該數(shù)據(jù)是作為參數(shù)傳到當(dāng)前的方法中的,可以讀一讀上一個或幾個框架的匯編代碼,有可能該數(shù)據(jù)還在堆棧的某個地址上。靜態(tài)變量是儲存在固定地址中的,所以找出靜態(tài)變量的值較為容易。.Frame(或者在調(diào)用堆棧窗口中雙擊)可以用來切換當(dāng)前的框架。注意dv命令顯示的是當(dāng)前框架的內(nèi)容。你也可在watch窗口中觀察局部變量的值。
顯示類和鏈表: dt可以顯示數(shù)據(jù)結(jié)構(gòu)。比如dt PEB 會顯示操作系統(tǒng)進(jìn)程結(jié)構(gòu)。在后面跟上一個進(jìn)程結(jié)構(gòu)的地址會顯示該結(jié)構(gòu)的詳細(xì)信息:dt PEB 7ffdf000。
Dl命令可以顯示一些特定的鏈表結(jié)構(gòu)。
顯示當(dāng)前線程的錯誤值:!gle會顯示當(dāng)前線程的上一個錯誤值和狀態(tài)值。!error命令可以解碼HRESULT。
搜索或修改內(nèi)存:使用s 命令來搜索字節(jié),字或雙字,QWORD或字符串。使用e命令來修改內(nèi)存。
計算表達(dá)式:?命令可以用來進(jìn)行計算。關(guān)于表達(dá)式的格式請參照幫助文檔。使用n命令來切換輸入數(shù)字的進(jìn)制。
顯示當(dāng)前線程,進(jìn)程和模塊信息:!teb顯示當(dāng)前線程的環(huán)境信息。最常見的用途是查看當(dāng)前線程堆棧的起始地址,然后在堆棧中搜索值。!peb顯示當(dāng)前進(jìn)程的環(huán)境信息,比如執(zhí)行文件的路徑等等。lm顯示進(jìn)程中加載的模塊信息。
顯示寄存器的值:r命令可以顯示和修改寄存器的值。如果要在表達(dá)式中使用寄存器的值,在寄存器名前加@符號(比如@eax)。
顯示最相近的符號:ln Address。如果你有一個C++對象的指針,可以用來ln來查看該對象類型。
查找符號:x命令可以用來查找全局變量的地址或過程的地址。x命令支持匹配符號。x kernel32!*顯示Kernel32.dll中的所有可見變量,數(shù)據(jù)結(jié)構(gòu)和過程。
查看lock:!locks顯示各線程的鎖資源使用情況。對調(diào)試死鎖很有用。
查看handle:!handle顯示句柄信息。如果一段代碼導(dǎo)致句柄泄漏,你只需要在代碼執(zhí)行前后使用!handle命令并比較兩次輸出的區(qū)別。有一個命令!htrace對調(diào)試與句柄有關(guān)的Bug非常有用。在開始調(diào)試前輸入:
!htrace –enable
然后在調(diào)試過程中使用!htrace handle_value 來顯示所有與該句柄有關(guān)的調(diào)用堆棧。
顯示匯編代碼:u。
程序執(zhí)行控制命令:
設(shè)置代碼斷點:bp/bu/bm 可以用來設(shè)置代碼斷點。你可以指定斷點被跳過的次數(shù)。假設(shè)一段代碼KERNEL32!SetLastError在運行很多次后會出錯,你可以設(shè)置如下斷點:
bp KERNEL32!SetLastError 0x100.
在出錯后使用bl 來顯示斷點信息(注意粗體顯示的值):
0 e 77e7a3b0 004f (0100) 0:*** KERNEL32!SetLastError
重新啟動調(diào)試(.restart命令)并設(shè)置如下的斷點:
bp Kernel32!SetLastError 0x100-0x4f
Debugger會停在出錯前最后一次調(diào)用該過程的地方。
你可以指定斷點被激活時Debugger應(yīng)當(dāng)執(zhí)行的命令串。在該命令串中使用J命令可以用來設(shè)置條件斷點:
bp `mysource.cpp:143` "j (poi(MyVar)”0n20) ''; 'g' "
上面的斷點只在MyVar的值大于32時被激活(g命令
條件斷點的用途極為廣泛。你可以指定一個斷點只在特殊的情況下被激活,比如傳入的參數(shù)滿足一定的條件,調(diào)用者是某個特殊的過程,某個全局變量被設(shè)為特殊的值等等。
設(shè)置內(nèi)存斷點:ba可以用來設(shè)置內(nèi)存斷點。調(diào)試過程中一個常見的問題是跟蹤某些數(shù)據(jù)的變化。如下的斷點:
ba w4 0x40000000 "kb; g"
可以打印出所有修改0x40000000的調(diào)用堆棧。
控制程序執(zhí)行:p, pa,t, ta等命令可以用來控制程序的執(zhí)行。
控制異常和事件處理:Debugger的缺省設(shè)置是跳過首次異常(first chance expcetion),在二次異常(second chance exception)時中斷程序的執(zhí)行。sx命令顯示Debugger的設(shè)置。sxe和sxd可以改變Debugger的設(shè)置。
sxe clr
可以控制Debugger在托管異常發(fā)生時中斷程序的執(zhí)行。常用的Debugger事件有:
av 訪問異常
eh C++異常
clr 托管異常
ld 模塊加載
-c 選項可以用來指定在事件發(fā)生時執(zhí)行的調(diào)試命令。
堆棧顯示指令kb , kp, kP , kv
反匯編指令 u,uf
跟蹤指令 T,TA,TB,TC
執(zhí)行相關(guān)指令 P,PA,PC
跟蹤查看指令 WT
----------------------------------------------------------------------------
堆棧顯示指令
k [b|p|P|v]
在內(nèi)核調(diào)試的時候,k命令用來顯示內(nèi)核棧的內(nèi)容
先說說內(nèi)核棧用來干嘛的 看了些資料個人理解是這樣的
比如我們的代碼運行時,肯定會有函數(shù)函數(shù)然后還會調(diào)用函數(shù) 但是系統(tǒng)如何記錄是哪個父函數(shù)調(diào)用了這個子函數(shù),在子函數(shù)調(diào)用之前整個狀態(tài)又是怎樣的,其實系統(tǒng)是利用了堆棧記錄的 棧這個東西好阿 先進(jìn)后出 最近調(diào)用的函數(shù)記錄在最頂層 函數(shù)執(zhí)行完后就從棧內(nèi)彈出之前記錄的參數(shù),如果調(diào)用函數(shù) 一樣的把函數(shù)壓進(jìn)棧內(nèi)就好了 這樣一來 一旦子函數(shù)執(zhí)行完,從棧內(nèi)彈出的第一個函數(shù)肯定是該子函數(shù)的老爹 我們可以看上層堆棧的狀態(tài)等等 功能大家慢慢去體會吧我也沒用過 呵呵 不好說什么 下面說些細(xì)節(jié)的東西
b
顯示傳給函數(shù)的前三個參數(shù)
p
顯示傳給函數(shù)的全部參數(shù)
P( 大寫)
跟上面那個一樣 只不過是顯示形式不同而已
V
外加顯示一些額外的信息
----------------------------------------------------------------------------
u [f]
反匯編指令,嘿嘿 超級有用的指令喲雖然說內(nèi)核很多東西很復(fù)雜 認(rèn)識偶爾小小反下也是可以的
u
反匯編當(dāng)前寄存器指向的代碼
uf 函數(shù)名(比如nt!ZwCreateFile)
反匯編指定的函數(shù)
----------------------------------------------------------------------------
t [r]
單步跟蹤
r 打開指顯示寄存器的詳細(xì)信息,狀態(tài)的開關(guān)(下面指令一樣有效,在用1次就會關(guān)閉哦~)
ta 地址
讓程序執(zhí)行到指定地址
tb
讓程序運行到分支語句時停止
tc
讓程序運行到下一個函數(shù)調(diào)用停止
----------------------------------------------------------------------------
p [r]
單步執(zhí)行一跳指令
r 打開指顯示寄存器的詳細(xì)信息,狀態(tài)的開關(guān)(下面指令一樣有效,在用1次就會關(guān)閉哦~)
pa
讓程序執(zhí)行到指定地址
pc
讓程序執(zhí)行到函數(shù)調(diào)用就停止
----------------------------------------------------------------------------
wt
在想查看指定函數(shù)的信息而又不想單步通過該函數(shù)時很有用。可以到函數(shù)的起始地址并執(zhí)行 wt 命令。(摘自翻譯文檔)
這個感覺用處不是很大.不細(xì)細(xì)研究了
----------------------------------------------------------------------------
Ps: 很多人不清楚到底p指令和t指令有什么區(qū)別 其實很簡單 p指令執(zhí)行到函數(shù)時把這個當(dāng)做一個指令來執(zhí)行也就是說不會進(jìn)入函數(shù)執(zhí)行,但是t指令會進(jìn)入到函數(shù)里面執(zhí)行 就這么簡單~~呵呵
遠(yuǎn)程調(diào)試
使用WinDbg進(jìn)行遠(yuǎn)程調(diào)試是很容易的,而且有很多種可行的方法。在下文中,’調(diào)試服務(wù)器’指的是運行在你所要調(diào)試的遠(yuǎn)程機器上的調(diào)試器。’調(diào)試客戶端’指的是控制當(dāng)前會話的調(diào)試器。
· 使用調(diào)試器:你需要CDB, NTSD或者WinDbg已經(jīng)安裝在遠(yuǎn)程機器上。WinDbg客戶端可以連接到CDB, NTSD或者WinDbg中的任何一個作為服務(wù)器,反之亦然。在客戶端和服務(wù)器直接可以選擇TCP或者命名管道作為通訊協(xié)議。
o 在服務(wù)器端的啟動過程:
§ WinDbg –server npipe:pipe=pipename(注:可以允許多個客戶端連接)
§ 從WinDbg內(nèi)部: .server npipe:pipe=pipename(注,連接單個客戶端)
你可以用多種協(xié)議開啟不同的服務(wù)會話。并且可用密碼來保護(hù)一個會話。
o 從客戶端連接:
§ WinDbg -remote npipe:server=Server, pipe=PipeName[,password=Password]
§ 從WinDbg內(nèi)部: File->Connect to Remote Session: for connection string, enter npipe:server=Server, pipe=PipeName [,password=Password]
· 使用Remote.exe: Remote.exe使用命名管道作為通訊的方式。如果你使用的是一個命令行接口的程序,比如KD,CDB或者NTSD。你可以使用remote.exe來遠(yuǎn)程調(diào)試。注意:使用@q(不是q)來退出客戶端,不用關(guān)掉服務(wù)端。
o 要啟動一個服務(wù)端:
§ Remote.exe /s “cdp –p <pid>” test1
o 從客戶端連接:
§ Remote.exe /c <machinename> test1
上面的test1是我們所選擇的命名管道的名字。
服務(wù)端會顯示那個客戶端從那個服務(wù)器連接以及執(zhí)行過的命令。你可以使用‘qq’命令來退出服務(wù)端;或者使用File->Exit來退出客戶端。另外,如果要進(jìn)行遠(yuǎn)程調(diào)試,你必須屬于遠(yuǎn)程機器的”Debugger User”組并且服務(wù)器必須允許遠(yuǎn)程連接。
即時調(diào)試
在WinDbg的文檔的”Enabling Postmorten Debugging”部分對此有很詳細(xì)的討論。簡而言之,你可以把WinDbg設(shè)置成默認(rèn)的即時調(diào)試器,命令就是:Windbg –I。這個命令實際上是把注冊表中 HKLM\Software\Microsoft\Windows NT\CurrentVersion\AeDebug的鍵值設(shè)置成WinDbg。如果要把WinDbg設(shè)置成為默認(rèn)的托管調(diào)試器,你需要顯示設(shè)置如下的注冊表鍵值:
HKLM\Software\Microsoft\.NETFramework\DbgJITDebugLaunchSetting 設(shè)置成 2
HKLM\Software\Microsoft\.NETFramework\DbgManagedDebugger 設(shè)置成Windbg.(注意其中的啟動參數(shù)設(shè)置)
通過JIT的設(shè)置,當(dāng)一個應(yīng)用程序在不是調(diào)試的狀態(tài)下拋出了未處理的異常之時,WinDbg就會被啟動。
64位調(diào)試
所有這些調(diào)試器均支持在AMD64和IA64上的64位調(diào)試環(huán)境。
托管應(yīng)用程序的調(diào)試
WinDbg 6.3以后的版本支持在Widbey(VS2005和.net 2.0的內(nèi)部開發(fā)代號) .net CLR托管調(diào)試。在文檔中針對托管調(diào)試有很好的討論。需要注意的是,對于托管程序來說,沒有剛才所說的PDB(譯注:托管代碼實際上也是有PDB的,但是這個PDB實際上記錄了C#代碼和IL代碼的對應(yīng)關(guān)系以及相關(guān)的一些信息)的概念,因為所有的程序都是編譯成為ILASM。調(diào)試器通過CLR來查詢所需的附加信息。
有幾點需要注意:
你只能在托段函數(shù)的代碼被執(zhí)行過至少一次之后才能設(shè)置斷點。只有這樣它才能被編譯成匯編代碼。記住以下的幾點:
· 關(guān)于函數(shù)的地址的復(fù)雜化以及對應(yīng)的斷點設(shè)置:
o CLR有可能丟棄已經(jīng)編譯好的代碼,所以函數(shù)的入口地址有可能改變。
o 同樣的代碼有可能被多次編譯,如果多個應(yīng)用程序域沒有共享這段代碼的話。如果你設(shè)置了一個斷點,它就會被設(shè)置在當(dāng)前線程(譯注:CLR的邏輯線程)所在的應(yīng)用程序域內(nèi)。
o 泛型的特殊實例可能導(dǎo)致同一個函數(shù)有不同的地址。.
· 數(shù)據(jù)存儲布局的復(fù)雜化以及對應(yīng)的數(shù)據(jù)檢查:
CLR可能會在運行的時候任意改變數(shù)據(jù)的存儲布局,所以一個結(jié)構(gòu)體成員的偏移量可能會被改變掉. (譯注:實際上是在一個類型被加載的時候決定的數(shù)據(jù)布局,之后是不會改變的。)
一個類型的信息是在第一次使用的時候被加載,所以你可能不能夠查看一個數(shù)據(jù)成員如果它還沒有被使用過.
· 調(diào)試器命令的復(fù)雜化
o 當(dāng)跟蹤托管代碼的時候,你會需要穿越大段的CLR自己的代碼比如JIT編譯器的代碼,原因可能是你第一次進(jìn)入一個函數(shù),或者是你在托管和非托管代碼之間進(jìn)行切換。
調(diào)試Windows服務(wù)
使用WinDbg,你可以像調(diào)試其它應(yīng)用程序那樣調(diào)試Windows服務(wù)程序。即可以通過附加進(jìn)程的方法啟動Windows服務(wù),也可以把WinDbg當(dāng)作一個即時調(diào)試器,并且在代碼中調(diào)用DbgBreakPoint 或者 DebugBreak,或者在x86機器上加入一條int 3匯編指令。
調(diào)試異常
一個調(diào)試器會得到兩次的異常通知-第一次在應(yīng)用程序有機會處理異常之前(‘first chance exception’);如果應(yīng)用程序沒有處理這個異常,這時候調(diào)試器就會有機會來處理異常(‘second-chance exception’)。如果調(diào)試器沒有處理二次機會的異常,應(yīng)用程序就會退出。
.lastevent或者,!analyze –v命令會給你顯示異常的記錄以及異常拋出所在函數(shù)的堆棧跟蹤信息。
你也可以使用 .exr, .cxr以及 .ecxr命令來顯示異常和上下文記錄。同時需要注意的是,你也可以改變first-chance的處理選項。對應(yīng)的命令就是: sxe, sxd, sxn和sxi。
虛擬機調(diào)試驅(qū)動
1)
將 WinDbg 發(fā)送一個快捷方式,并修改在快捷方式上右鍵=>"屬性"
將"目標(biāo)"中的 WinDbg 文件名后添加 "-k com:port=\\.\pipe\com_1,baud=115200,pipe" , 如下:
"C:\Program Files\Debugging Tools for Windows\windbg.exe" -k com:port=\\.\pipe\com_1,baud=115200,pipe
2)
打開虛擬機中的 c:\boot.ini 文件(之前去掉"只讀"屬性),復(fù)制一行
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Enterprise" /fastdetect
即添加了一個啟動選項,并修改為:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Enterprise[Debug]" /fastdetect /debug /debugport=com1 /baudrate=115200
即添加了調(diào)試選項,調(diào)試端口以及串口的速率.
保存.
3)
關(guān)閉虛擬機里的目標(biāo)windows系統(tǒng)(必須,否則在"Settings..."里的"Add..."將為灰色,不可選狀態(tài)),
選擇目標(biāo)windows系統(tǒng)的"Settings..."選項,在"Hardware"選項中,點擊下面的"Add..."按鈕.
選擇"Serial Port"點擊"Next",再選擇"Output to named pipe","Next",
這一向?qū)е?前兩項不修改,最后一項修改為"The other end is an application.",
如果這里存在"高級"選項,則在其中選擇"Yield CPU on poll"[注:有些虛擬機在這里并沒有"高級"選項,則在"Finish"后,選擇"Serial Port",再勾選右下角的"Yield CPU on poll"],
"Finish".
"OK",完成"Virtual Maching Setting".
4)
打開虛擬機中的目標(biāo)Windows系統(tǒng),選擇"Windows Server 2003, Enterprise[Debug]"后,立即打開之前創(chuàng)建的WinDbg快捷方式(若先打開WinDbg,則會報找不到'com:port=....'等信息).
5)
連接上虛擬機中的目標(biāo)windows系統(tǒng)后,立即發(fā)送一個WinDbg中的"Debug"=>"Break"來中斷它.
6)
設(shè)置"Symbol"路徑,"Source"路徑和"ImagePath"路徑(若有多個,則用";"號隔開).
如:
"File"=>"Symbol" 里設(shè)置:"G:\虛擬機共享文件\Win2003Symbols;G:\虛擬機共享文件\GiveIO",勾選"Reload","OK". (第一個是Windows的符號[這里要注意,符號應(yīng)該是虛擬機內(nèi)Windows系統(tǒng)對應(yīng)的],第二個是要調(diào)試的驅(qū)動的符號)
"File"=>"Source" 里設(shè)置:"G:\虛擬機共享文件\GiveIO", "OK". (要調(diào)試的驅(qū)動的源碼我放在了此目錄中)
"File"=>"Image File Path" 里設(shè)置: "G:\虛擬機共享文件\GiveIO", "Reload", "OK". (我把要調(diào)試的驅(qū)動程序放在了此目錄中)
"File"=>"Open Source File", 打開驅(qū)動源文件.
7)
在要調(diào)試的驅(qū)動程序上下斷點(這里我調(diào)試的驅(qū)動模塊名為"GiveIO",后面是在"DriverEntry"入口點下斷點[bu設(shè)置的是延遲斷點]):
bu GiveIO!DriverEntry
按"F5"(或在命令行中用"g"命令),即可讓虛擬機中的目標(biāo)Windows順利啟動.
8)
在虛擬機中運行要調(diào)試的驅(qū)動程序,即可運行到斷點處.
9)
一些說明:
在已運行的Windows目標(biāo)系統(tǒng)中調(diào)試指定驅(qū)動:
首先應(yīng)使WinDbg產(chǎn)生一個斷點,使用WinDbg中的"Debug"=>"Break",此時目標(biāo)Windows系統(tǒng)就會中斷.
此時使用:
bu GiveIO!DriverEntry
命令,在指定驅(qū)動的模塊名的入口點下斷點(GiveIO為此處的驅(qū)動模塊名).
運行驅(qū)動后,即會在驅(qū)動的DriverEntry處斷下來,此時就可以進(jìn)行跟蹤調(diào)試了.
bl命令可以查看已下的斷點
bc清除斷點,如果后面跟"*",則清除所有斷點