本篇介紹Windows調試工具的基本設定和基本操作方法。這裡我們會用一個測試程式一步一步說明如何使用WinDbg開始調試工作。首先用VC建立一個名為TestDebug1的控制台項目,並產生它。
一、符號、源碼和可執行映像路徑設定
使用WinDbg開始調試工作之前,最重要的就是配置好各種環境了。這使得調試器可以正確識別偵錯目標中的各種變數、函數等等,使得我們能夠進行符號化調試或者源碼調試,而不是只能在一堆彙編代碼中轉圈。
首先來看一下未設定環境之前的樣子。使用剛才說的TestDebug1項目,為了對比更清晰,用Release進行編譯,連結選項中選中產生map檔案和調試資訊,如下:
在C/C++選項卡中設定如下:
程式碼如下:
#include "stdafx.h"
#include <stdio.h>
int main(int argc, char* argv[])
{
printf( "TestDebug1.cpp");
return 0;
}
編譯之後,將Release目錄下的TestDebug1.pdb剪下到其他目錄下(如果沒有這樣做,由於編譯出來的程式中包含了符號檔案路徑,調試器可以直接使用exe中的資訊找到pdb檔案,而不需要設定路徑)。在map檔案中可以看到像下面這樣的內容:
0001:00000000 _main 00401000 f TestDebug1.obj
說明main函數位於401000地址處。
通過WinDbg的File->Open Executeable菜單開啟TestDebug1.exe,可以在調試器命令視窗中看到下面的內容:
可以看到,調試器自動中斷下來的位置並不是程式進入點,這是由WinDbg實現造成的,這裡先不管它。
調試器命令視窗中可以看到,我們還沒有設定符號路徑,所以WinDbg目前還找不到TestDebug1.exe的任何符號檔案。如果想在main函數下斷,這時就不能使用符號,而只能直接使用main的地址。
使用命令bp 00401000在main函數設定斷點,然後F5執行就可以中斷到main的入口處了。斷點設定和基本操作我們將在後面介紹。可以在反組譯碼視窗中看到這樣的內容:
由於沒有載入任何符號,所以我們看到的都是一堆反組譯碼代碼和地址。在上一篇中已經介紹過,WinDbg不像OllyDbg這些調試器一樣擁有強大的反組譯碼分析能力,所以僅僅靠這些看起來一團亂麻的反組譯碼代碼,調試工作是很難開展下去的。
l 符號路徑的設定
要想在WinDbg中看到程式中的符號,必須通過命令或者WinDbg菜單設定符號路徑。如果還設定了Microsoft公用符號儲存的話,我們不但能夠看到自己程式中的符號,還能夠看到Windows平台代碼中的符號,這對於調試會提供很好的協助。
所謂符號路徑,就是包含了程式符號資訊的符號檔案所在的目錄路徑。通常我們接觸到的符號檔案都是以pdb作為尾碼名的。TestDebug1.exe項目如果在項目設定的Link選項中選中了產生調試資訊的話(如中的Generate debug info),那麼可以在Debug或者Release目錄中找到它的符號檔案TestDebug1.pdb。
我們通過WinDbg的File->Symbol File Path…菜單,或者命令.sympath設定符號路徑為TestDebug1.pdb所在的目錄。例如剛才我把產生的pdb檔案移動到案頭上了,所以在我的機器上就設定為:
完成之後在命令視窗輸入.reload命令,我們可以看到反組譯碼視窗的內容發生改變:
這裡就已經可以看到TestDebug1.exe中的函數、變數名這樣的符號了。而我們也可以通過bp main這樣的命令直接使用符號來操作調試器。
另外,在Local、Watch等視窗中也可以直接使用符號名查看到變數的值、在Call Stack視窗中可以看到函數名,等等。
l 源碼路徑的設定
通過上面的設定,我們可以對程式進行符號化調試。如果擁有程式的代碼,還可以通過設定源碼路徑來進行源碼級調試。
繼續上面的工作,我們通過WinDbg的File->Source File Path…菜單或者.srcpath命令設定原始碼儲存的路徑,比如我的機器上是這樣:
確定之後,如果當前指令指標在源檔案的代碼範圍內,就會自動跳出源檔案視窗。如果沒有跳出,那麼可以通過File->Open Source File…菜單手動開啟源檔案。由於剛才設定的斷點還沒有刪除,所以在源碼視窗也能口看到設斷的行被高亮了:
之後就基本上可以完全通過源碼視窗進行設定斷點、查看變數、跟蹤代碼等操作。比只有符號的時候方便了很多。
l 可執行映像路徑的設定
可執行映像路徑一般在調試dump檔案時才用得上。需要將這個路徑設定成要調試的exe、dll、sys等可執行檔的路徑。可以通過File->Image File Path…菜單或者.exepath命令設定。
l 使用微軟公用符號儲存
除了使用自己程式的符號之外,調試時還可以使用微軟提供的Windows系統代碼的符號。這需要修改一下我們設定的符號路徑。最方便的辦法是使用.symfix命令。
現在我們來看一下kernel32.dll中的代碼,在反組譯碼視窗的Offset欄中填入kernel32!OpenProcess,在我的機器上代碼如下:
注意位於764e8ccf處的那個call,現在只能看到調用了kernel32某個位移處的地址。
使用命令.symfix+ d:/Symbols命令,注意加號要緊靠前面的文本。d:/Symbols是用來儲存下載的符號檔案的目錄,可以修改成自己需要的路徑。再來開啟符號路徑視窗,我們可以看到調試器自動添加了一些內容:
自己在源碼路徑中加入這些新的內容也可以實現相同的效果。詳細的原理請參考WinDbg協助文檔關於符號伺服器設定的部分內容。
接下來再次使用.reload命令重新載入符號,第一次使用到的符號檔案會從網上自動下載下來,所以可能有時候會等待一會。完成之後,可以看到反組譯碼視窗中出現了新的符號內容:
764e8cd8處指令中可以看到這是調用了kernel32匯入的函數NtOpenProcess。
微軟提供的Windows符號是我們研究Windows實現的必備利器。首先,符號化的名字有助於調試過程中的記憶和對各種資訊的識別;其次,通過名字就常常可以猜測出來函數或變數的作用,很大的方便調試。在各種調試應用中,都強烈建議添加微軟公用符號的引用。
l 設定環境變數
上面介紹的各種路徑都可以通過環境變數來進行設定。將一些常用的路徑儲存在環境變數中,就可以避免每次在新的工作空間中進行調試時都要重新設定的麻煩。另外,Visual Studio 2008也共用一些環境變數的設定,這樣在使用IDE調試的時候也能方便的查看到各種符號了。常用的有下面幾個:
環境變數 |
作用 |
_NT_SOURCE_PATH = Path |
指定包含偵錯目標的原始碼的路徑。Path可以包含後跟一個冒號(:)的磁碟機符。用分號分隔多個目錄(;)。 |
_NT_SYMBOL_PATH = Path |
指定包含符號檔案的分類樹的根目錄。Path可以包含後跟一個冒號(:)的磁碟機符。用分號分隔多個目錄(;)。 |
_NT_EXECUTABLE_IMAGE_PATH = Path |
指定包含二進位可執行檔的路徑。Path可以包含後跟一個冒號(:)的磁碟機符。用分號分隔多個目錄(;)。 |
_NT_DEBUG_LOG_FILE_OPEN = Filename |
(僅CDB和KD) 指定調試器用來記錄輸出的記錄檔。 |
_NT_DEBUG_LOG_FILE_APPEND = Filename |
(僅CDB和KD) 指定調試器用來添加輸出的記錄檔。新的內容每次會添加到這個檔案末尾,而不是覆蓋整個檔案。 |
如果設定了符號路徑的環境變數的話,可能在初期使用VS 2008調試MFC這樣的有較多匯入庫的程式時會下載很多符號檔案,使得啟動調試的速度變慢。不過經過一段時間,大部分需要的符號都緩衝到本地之後速度就會快起來。
二、配置記錄檔
進行調試時,有時候調試器命令視窗會變得很雜亂,所以常常想用.cls命令清空它。但是這樣會無法再看到之前調試過程中輸出的結果。另外,有時候想儲存下整個調試過程的詳細記錄以備後面“回味”。這時,就需要用到記錄檔了。可以將調試器命令視窗中出現過的所有內容都自動記錄到記錄檔中。
建立記錄檔:
(
僅
CDB
和
KD) 啟動調試器之前,設定_NT_DEBUG_LOG_FILE_OPEN環境變數。 啟動調試器時,使用
-logo 命令列選項。 如
-logo d:/logs/mylogfile.txt使用.logopen命令。如.logopen /t d:/logs/mylogfile.txt
(
僅
WinDbg) 使用Edit->Open/Close Log File功能表命令。
將日誌添加到已有的檔案末尾:
(
僅
CDB
和
KD) 啟動調試器之前,設定_NT_DEBUG_LOG_FILE_APPEND環境變數。 啟動調試器時,使用
-loga命令列選項。如
-loga d:/logs/mylogfile.txt使用.logappend命令。 如. logappend/t d:/logs/mylogfile.txt
(
僅
WinDbg) 使用Edit->Open/Close Log File功能表命令,然後選擇
Append。
關閉記錄檔:
使用
.logclose
命令
(
僅
WinDbg) 使用Edit->Open/Close Log File功能表命令,然後選擇
Close Open Log File。
三、設定工作空間
工作空間(Workspace)是用來儲存WinDbg中工作環境的工具。例如習慣的視窗布局方式、符號路徑、異常處理的設定等等,都可以通過工作空間儲存下來,在下次調試的時候就不用再次設定了。
相關的設定都可以通過WinDbg菜單來完成,有下面幾個:
l Open Workspace:這裡只能開啟自己通過SaveAs儲存的工作空間。
l Save Workspace:按預設的方式儲存當前的工作空間。下次再開啟相同的偵錯目標時,就會自動開啟這個Workspace。
l Save Workspace As:可以自己設定工作空間的名字,這樣就能通過Open Workspace來手動開啟。
l Clear Workspace:可以選擇儲存工作空間時要儲存哪些設定。
l Delete Workspace:刪除當前儲存的工作空間。這裡可以查看到所有預設儲存和另存新檔的工作空間,用來進行清理是很方便的。
l Save Worlspace in File和Open Workspace in File:將工作空間儲存到檔案或者從檔案開啟。可以把自己的工作空間儲存下來,這樣通過隨身碟之類的就能在多台機器之間方便的使用相同的設定了。
在沒有偵錯目標的時候調整WinDbg的視窗布局等等設定的話,會儲存為預設的工作空間。下一次開啟新目標的時候,就會使用這個設定。通常我們可以設定一個預設的工作空間,然後為各個單獨的任務儲存另外的設定。