WINDEBUGGERS 調試

#工作空間[Workspace]

工作空間被用來描述和存儲一個調試項目的屬性、參數以及調試器設置等信息,其功能類似於集成開發環境的項目文件。

具體包括:調試會話狀態(斷點、打開的源文件、用戶定義的別名等)、調試器設置(符號文件路徑、源文件路徑、可執行映像文件路徑等)和窗口布局狀態

0. 基礎工作空間 [baseworkspace]

未載入任何的調試文件時使用默認的啓動環境。存放位置:HKEY_CURRENT_USER\Software\Microsoft\Windbg\WorkspacesDefault二進制值。

1. UserKernelDumpExplicit工作空間

存放在HKEY_CURRENT_USER\Software\Microsoft\Windbg\Workspaces的各子鍵中(如下圖)

子鍵User、Kernel、Dump用來保存用戶態調試、內核態調試、調試轉儲文件時,使用【Save Workspace】方式時默認的保存路徑。

子鍵Explicit則用來記錄使用【Save Workspace as】方式保存的命名工作空間。

對於【Attach toa Process】的方式,會使用User下的Default二進制值作爲其工作空間,之後對工作空間所作的修改也會寫到該字段中。

注:有時會發現沒有某個子鍵,這是因爲windbg還沒使用過該調試方式。

2. 其他說明

(1) windbg還提供另外一種保存方式【Save WorkSpace to File】,作用跟上面兩種的方式差不多,

     只不過把工作空間以文件的形式保存到磁盤裏,那麼用戶就可以通過U盤或其它方式把工作空間的環境移植到其它機器上使用。

(2) 調試目標最後的工作空間爲:基礎工作空間其對應工作空間求並所得的環境。

(3) 用windbg打開目標可執行文件【Open Executable】,若有默認的工作空間文件(在子鍵User下),會自動打開其對應默認的的工作空間文件。

     要使用子鍵Explicit下目標文件的工作空間,必須先提前【Open WorkSpace】,然後再打開目標可執行文件。

(4) 在載入調試目標後改變了工作空間並保存,並不改變windbg的基礎工作空間,只改變調試目標對應的工作空間;

     而只有在windbg還沒載入任何調試目標時改變並保存纔會影響基礎工作空間。

#符號 [Symbol]

調試者接觸的二進制數據以及彙編代碼,如果沒有符號表文件的幫助,就無法知道這些數據代表什麼變量、函數。

符號(symbol) :函數和變量的別名,編譯器通過符號修飾(Name Decoration)和 函數簽名(FunctionSignature)來實現全局唯一性。

函數符號含有返回值,函數名,函數參數等函數所有信息;變量符號含有類型和名稱信息。

通過不同的編譯選項,編譯器可以生成兩種截然不同的信息集合:私有符號(private symbol公有符號(public symbol

私有符號(privatesymbol)包含完整的調試信息,編譯選項:/Zi或/ZI。

公共函數和變量:在多個的編譯單元(源代碼文件)中可見的函數和變量。

私有函數和變量:用於描述除公共函數和變量以外的所有函數和變量,包括靜態函數、靜態和局部變量、函數參數)。

因此,爲了能更方便讀懂二進制數據和彙編語言,需要獲取符號表文件,在windbg下使用的符號表文件一般是.PDB文件。  

客戶端軟件存在於exe/dll中,這些二進制文件會調用操作系統的dll,這兩部分二進制文件的符號表文件都需要獲取。

客戶端軟件自己的符號表文件在構建程序的過程中產生;而操作系統dll的符號表文件可以通過設置windbg,根據需要自動從微軟符號服務器上下載。

#pdbprogramDatabase

0. pdb中包含的內容

符號表

函數和變量符號到地址的映射表(map文件實際就是一個文本格式的符號表)。

源文件和代碼行信息

二進制指令到代碼源文件代碼行的映射表。

類型信息

用於存儲每一個函數和變量的類型信息。對於變量或函數參數,類型信息能夠告訴調試器是整型還是字符串類型,或是用戶自定義類型。

對於函數,類型信息記載了參數的個數、調用轉換和返回值的類型。

FPO(frame pointer omission, 幀指針省略)

 

對於做了FPO優化的函數,FPO信息保存了一些數據來幫助調試器確定函數堆棧幀的大小,

幫助調試器查找函數的參數和本地變量,甚至在幀指針無效時也能工作。

如果沒有FPO信息,調試器無法正確顯示被優化的程序的調用堆棧。

編輯和繼續執行信息

用於幫助Visual Studio在調試時實現編輯和繼續執行的功能

在過去的十年中,微軟使用了幾種不同的格式(COFF、CodeView和應用的最廣泛的PDB格式)來存放調試信息。

格式

是否有文檔

存儲

公共函數和變量

私有函數和變量

源文件和代碼行信息

類型信息

FPO信息

編輯和繼續執行信息

COFF

微軟可移植可執行和通用對象文件格式規範

可執行文件中

+

-

+

-

+

-

CodeView

部分

Microsoft Symbol and Type Information

可執行文件中

或.DBG文件中

+

+

+

+

+

-

Program Database

微軟沒有提供程序數據庫格式的文檔,只提供特殊的編程接口DbgHelp 和DIA來訪問它。
目前有兩個版本,第一版(PDB2.0)爲VC6.0所用,第二版(PDB 7.0)被VS採用。
PDB 7.0不能向上兼容,也就是說:VC6.0不能讀取PDB 7.0格式。

.PDB文件中

+

+

+

+

+

+

1. vc6下配置生成PDB文件

vc6的Debug配置,會在編譯時生成私有符號pdb文件;Release可通過如下配置來達到這一目的:

(1) 選擇Project->Setting菜單,打開工程設置對話框

(2) 在“Setting For:” 中選擇 “Win32 Release”(只設置Release版本即可,因爲Debug版本默認生成PDB文件)

(3) 選擇標籤頁 “C/C++” ,在 “Debug info” 中選擇 “LineNumbers Only”(如果選擇Program Database則包含更多的符號信息)

(4) 選擇標籤頁 “Link” ,勾選 “Generatedebug info”

(5) 在標籤頁 “Link” 中,選擇 “Category->Customize”,在這裏填寫PDB文件的生成路徑

無論是Debug還是Release配置,VC6.0Link選項需要將/pdbtype:sept改爲/pdbtype:con, 否則生成的pdb文件中將不包含如自定義結構體,類等信息

更多關於vc6和vs的pdb編譯和鏈接選項信息,請參考:Windows程序調試系列: 使用VC++生成調試信息

2. vsRelease配置生成PDB文件

(1) 配置C/C++ >General>Debug Information Format 爲 “Program Database(/Zi)”

(2) 配置C/C++ >Optimization>Optimization 爲”Disabld(/Od)”

(3) 配置Linker>Debugging>Generate Debug Info 爲”Yes/(DEBUG)”

3.windbg下使用PDB文件

啓動windbg後,選擇 【Symbol File Path】,彈出 “SymbolSearch Path” 對話框,輸入存放PDB文件的路徑。可以輸入多個路徑,路徑之間使用分號進行分隔。

如果此時正在調試程序,則對話框中的reload選擇框是可以選擇的,勾選後點擊確定

4.使用Windows符號表服務器

爲了方便調試,需要獲取Windows系統DLL的符號表文件。微軟公司提供了可以通過Internet訪問的符號表服務器。

經過設置,在調試過程中,windbg調試器會從符號表服務器自動下載調試所需的PDB文件,非常方便。

設置方法: 在 【SymbolSearch Path】 對話框中加入下面的路徑:srv*D:\SystemSymbols*http://msdl.microsoft.com/download/symbols

其中: D:\SystemSymbols爲存放符號的下載目錄

148C58F3D11e000爲對應版本dbghelp.dll的PE頭中記錄的時間日期戳和映像大小的組合(字節數)

2:6B19F261EE434AF59623D1791CE5A7D72爲對應版本dbghelp.pdb的guid

另外,也可以使用windbg提供的symchk.exe工具提前下載某個dll及某個目錄下所有dll的pdb文件到本地

"C:\ProgramFiles\Debugging Tools for Windows (x86)\symchk.exe" c:\windows\system32\user32.dll /s SRV*c:\symbols\*http://msdl.microsoft.com/download/symbols  //下載user32.dllpdbc:\symbols目錄中

"C:\Program Files\DebuggingTools for Windows (x86)\symchk.exe"c:\windows\system32\ /s SRV*c:\symbols\*http://msdl.microsoft.com/download/symbols //下載system32下所有dllpdbc:\symbols目錄中

"C:\ProgramFiles\Debugging Tools for Windows (x86)\symchk.exe" /r c:\windows\system32\ /s SRV*c:\symbols\*http://msdl.microsoft.com/download/symbols  //遞歸子目錄下載system32下所有dllpdbc:\symbols目錄中

5.建立自己的符號表服務器

通過爲產品建立自己的符號表服務器,就不需要關心複雜的版本問題。在調試過程中,windbg可以根據二進制文件(exe/dll)的哈希值,在符號表服務器上自動查找正確版本的PDB。

(1)建立一個共享文件夾,比如 “\\server\symbols” ,然後將所有的PDB文件上傳到此處

(2)使用下面的命令上傳符號表文件

symstore add /r /f D:\MyOutput\chess.exe/s \\server\symbols /t "chess" /v"exe" /c "version build"

symstore add/r /f D:\MyOutput\chess.pdb /s \\server\symbols /t"chess" /v "pdb" /c "version build"

symstore add/r /f D:\MyOutput\chess.map /s \\server\symbols /t"chess" /v "map" /c "version build"

symstore 是windbg附帶的一個exe文件,存放於windbg安裝目錄下。需包含2個文件:symstore.exe、symsrv.dll

上述命令完成的功能是:將D:\MyOutput目錄下的chess.exe、chess.pdb、chess.map上傳到\\server\symbols目錄中。

產品的名稱是"chess",版本信息是"exe"、"pdb"、"map",備註說明是"version build"。

(3)在windbg的 【SymbolSearch Path】對話框中添加新的路徑(路徑之間使用分號[;]分隔)\\server\symbols(關聯一個本地緩存目錄)

srv*D:\SystemSymbols*http://msdl.microsoft.com/download/symbols;srv*D:\ServerSymbols*\\server\symbols;f:\symbols

6. 查找函數符號名  -- 列出含CreateThread字樣的符號名

"D:\Program Files(x86)\windbg\dbh.exe" -s:srv*D:\Symbols\ms*http://msdl.microsoft.com/Download/Symbols -dC:\Windows\SysWOW64\kernel32.dll enum *CreateThread*

#使用windbg

0. Attach方式

啓動windbg,使用菜單【Attach toa Process】,可以選擇注入到現在正在運行的某個進程中。

注入到進程中後,進程被暫停執行,windbg處於可輸入命令狀態,但此時當前線程爲windbg產生的線程。

如果要觀察主線程堆棧,需要切換到主線程(0號線程)(windbg命令窗口輸入這個命令,然後回車):

~0s 

當程序出現CPU佔用100%的情況時,通常可以使用這種方式進行注入,然後切換到佔用CPU的線程,

同時根據需要使用單步跟蹤、設置斷點等手段,來判斷是何處的代碼導致CPU100%問題。

1. Open Executable方式

使用【Open Executable】方式,可以通過windbg啓動被調試程序。在這種方式下,被調試程序從啓動時刻起就在調試器的監控之下。

對於一些在程序啓動過程中產生的異常,可以使用這種方式進行調試。

2. Just in time Debugger 方式JIT

當進程產生結構化異常時,如果進程不作處理,也沒有調試器在監控這個進程,那麼windows就會調用默認的調試器來調試發生異常的進程。

通過把windbg設置爲Just intime Debugger,可以在任意進程發生異常時自動調用windbg來進行調試。

在註冊表編輯器中修改下面的註冊表項:

HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\AeDebug

HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\WindowsNT\CurrentVersion\AeDebug  // 注:64位系統上的32位程序使用該註冊表項

Debugger鍵值修改爲下面的取值 "D:\Tools\windbg.exe" -p %ld -e %ld

注:將例中windbg.exe的路徑替換爲本機windbg絕對路徑即可。

3. Dump文件

爲了分析程序發生異常的原因,還可以藉助Dump文件。

當異常發生時,把進程當前的信息保存到一個Dump文件中,再把該Dump文件發送給分析者,由分析者通過windbg進行分析。

Dump分類:

內核dump:(藍屏後,由系統生成)

1. 完全內存轉儲。這個文件比較大,和物理內存相當,包含了程序崩潰前系統及用戶模式下的所有信息。 
2. 核心內存轉儲。這個文件大小約物理內存的三分之一,主要包含崩潰前系統內核的所有信息。一般爲了分析內核錯誤,就選用這種文件。 
3. 小內存轉儲(MiniDump)。保存內存前64KB的基本空間數據,主要包含crash進程及crash線程內核上下文信息,crash線程內核模式堆棧,加載的驅動和模塊等信息。

不同信息量的minidump:

    (1)標準的minidump。包含了相對比較少的信息,適合在做在線分析:系統信息、加載的模塊(DLL)信息、進程信息和線程信息。
        .dump /m c:\stardardMini.dmp(注:不指定/m/f/m爲缺省選項

    (2) full dump。在內核模式下,生成完全內存轉儲;用戶模式下,最好不使用(/ma和/mf是更好的選擇,生成出的dump信息也更豐富一些)
        .dump /f c:\fullMini.dmp

    (3)帶有儘量多選項的minidump。包括完整的內存內容、句柄、未加載的模塊,等等。文件很大(本機和局域網環境適用)~
        .dump /ma c:\bigMini.dmp(注:/ma等價於/mfFhut;/m的子參數包括:a,A,f,F,h,u,t,i,p,w,d,c,r,R ).dump命令詳細用法

下面列出六種生成Dump文件的方法:

(1)在產品代碼中加入自動生成Dump文件功能

使用下面的函數,可以生成一個Dump文件:

BOOL MiniDumpWriteDump (

HANDLE hProcess,

DWORD ProcessId,

HANDLE hFile,

MINIDUMP_TYPE DumpType,

PMINIDUMP_EXCEPTION_INFORMATIONExceptionParam,

PMINIDUMP_USER_STREAM_INFORMATIONUserStreamParam,

PMINIDUMP_CALLBACK_INFORMATIONCallbackParam

);

這個函數定義在dbghelp.dll中,windbg安裝目錄中帶有這個dll,同時在sdk子目錄中提供了.h和.lib文件。
在進程捕捉結構化異常的地方,使用這個API生成一個Dump文件。

(2) 使用AdPlus生成Dump文件

windbg附帶了一個AdPlus的腳本,可以用於監控進程運行情況,並且可以在發生異常時把進程信息寫入到Dump文件中。
如果產品沒有自動生成Dump文件的功能,可以通過使用這個工具來彌補缺陷。

通過如下命令來使用AdPlus:

cscript D:\tools\windbg\adplus.vbs -crash -pnDebugTest.exe -o D:\CrashDumps

上述命令的意思是:監控當前運行的DebugTest.exe,如果發生了結構化異常,則生成一個Dump文件到D:\CrashDumps目錄中。
關於AdPlus更詳細的介紹請參閱:http://support.microsoft.com/kb/286350/zh-cn

(3) 使用windbg生成Dump文件

windbg可以通過命令生成mini-Dump文件:

.dump/mfh D:\CrashDumps\mydumpfile.dmp

(4) win7任務管理器 - 進程標籤頁 - 創建轉儲文件

(5) 使用vs2010以上版本生成 在調試狀態下[菜單]:調試 - 將轉儲另存爲

(6) 第三方系統工具 如:最新版本的Process Explorerproccump.exe命令行工具等

注意:

win32程序在64位操作系統上,需要生成dump時,應該生成32位的dump,否則windbg在獲取call stack時可能出錯,一些sos、psscor2等擴展無法讀取dump中的數據,一些命令在獲取dump中的信息也會受限。
對於32位dump,應該用x86版的windbg分析(無論是在32位還是64位操作系統上);64位dump,應該用在64位操作系統上使用x64版的windbg進行分析。

 

分析Dump文件

使用菜單【OpenCrash Dump】打開Dump文件,然後打開堆棧觀察窗口,此時看到的堆棧可能不是異常發生時的堆棧。

通過如下命令切換到異常發生時的堆棧:

.ecxr

爲了分析異常,可以通過下面的語句來獲取分析信息,幫助定位問題:

!analyze-v

#參考

http://www.debuginfo.com/resources.html

http://www.debuginfo.com/articles/debuginfomatch.html

http://www.debuginfo.com/articles/gendebuginfo.html

DbgHelp Functions: http://msdn.microsoft.com/en-us/library/ms679291(VS.85).aspx

利用VS2005進行dump文件調試

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章