windbg 用WinDbg探索ruby的奧秘

2021-08-30 20:07:56 字數 2951 閱讀 2951

寫這篇文章是受[url=""]從main.c開始走進ruby-登上除錯ruby之旅》[/url]的啟發,不同的是該文章用的是gdb,gdb雖然很強大,但是畢竟是命令列,在除錯的時候,可能同時需要檢視許多資訊,比如call statck,彙編**,源**等等,命令列就有點力不從心,所以續寫一篇,改gdb為同樣強大的windbg,以便更方便的探索ruby的內部奧秘。

這裡的主旨不是ruby,而是針對windbg的除錯技巧,所用的方法同樣適用於其他c/c++應用,ruby在這裡只是做實驗用的小白鼠。

[b]從編譯開始[/b]

要進行原始碼除錯,必須讓編譯器或鏈結器在構建二進位制檔案時生成符號檔案(.pdb檔案)。這些符號檔案儲存了二進位制指令和原始碼行之間的對應關係。

另外,偵錯程式必須能夠訪問原始碼檔案,因為符號檔案中並不包含實際的源**文字。

如果這些都滿足,編譯器和鏈結器還不能對**進行優化。如果**經過優化,在原始碼除錯時訪問區域性變數會變得很困難,有時候幾乎是不可能的。如果使用build 實用程式作為編譯器和鏈結器,可以將msc_optimization 巨集設定為/od /oi 來避免優化。

不同的是需要修改下ruby的makefile以便輸出debug資訊。

[code]

cflags = /od -md $(debugflags) $(optflags) $(processor_flag) /debug /zi

ldflags = $(ldflags) -manifest /debug

[/code]

指定 /zi 或 /zi 而不指定 /fd 時,vc++最終將生成兩個 pdb 檔案:

[list]

[*]vcx0.pdb (其中 x 表示 visual c++ 的版本。)該檔案儲存各個 obj 檔案的所有除錯資訊並與專案生成檔案駐留在同乙個目錄中。

[*]project.pdb 該檔案儲存 .exe 檔案的所有除錯資訊,它包含了除錯中需要用到的各種資料,例如:全域性變數、本地變數、函式名、函式型別、源**行、程式入口位址.....,這些所有的東西都叫做symbol。

[/list]

[b]pdb檔案說明[/b]

pdb檔案全稱是程式資料庫 (pdb) 檔案,它儲存著除錯和專案狀態資訊,使用這些資訊可以對程式的除錯配置進行增量鏈結。

每當建立 obj 檔案時,c/c++ 編譯器都將除錯資訊合併到 vcx0.pdb 中。插入的資訊包括型別資訊,但不包括函式定義等符號資訊。

鏈結器將建立 project.pdb,它包含專案的 exe 檔案的除錯資訊。project.pdb 檔案包含完整的除錯資訊(包括函式原型),而不僅僅是在 vcx0.pdb 中找到的型別資訊。這兩個 pdb 檔案都允許增量更新。

我們知道當應用程式被鏈結以後,**被逐一地翻譯為乙個個的位址,優化以後的**可能初看起來更是面目全非,如果除錯時,充斥著類似ntdll! 774fe4b6() ntdll! 774fe489()之類的呼叫堆疊無疑會增加除錯的難度。有了pdb檔案之後, 每當我們使用vs或者windbg等微軟的除錯工具進行除錯的時候,我們可以方便地使用變數名來檢視記憶體、可以使用函式名稱來下斷點、甚至可以指定某個檔案的某一行來下斷點。

[b]設定windbg的符號檔案[/b]

啟動windbg,選擇選單的file -> symbols file path,或者按ctrl+s 然後輸入

[code]

srv*c:\symbols*

[/code]

偵錯程式是如何來判別exe、dll等是否和乙個pdb檔案匹配呢?每次我們鏈結exe或者dll或者sys的時候,鏈結器都將產生乙個唯一的guid,然後將其寫入到pdb和可執行檔案。偵錯程式載入的時候將檢查兩者的guid,如果一致就表示他們匹配。

[img]

如果出現無法載入符號檔案的現象,通常是你的符號檔案和你除錯的二進位制不匹配。

由於鏈結器在其建立的 .exe 或 .dll 檔案中嵌入 .pdb 檔案的路徑,這裡不需要在設定ruby的符號檔案路徑。

我們只需要為windbg設定源**路徑,這樣可以很方便地檢視ruby的源**。

[b]常見的符號操作[/b]

檢視符號路徑:[b].sympath[/b]

列出載入模組: [b]lm[/b]

載入指定模組: [b]ld [/b]

列出模組詳細資訊: [b]!lmi [/b]或[b]!db [/b]

顯示模組的符號資訊: [b] x ![/b]

檢視模組的資料結構: [b] dt ![/b]

[b]啟動應用[/b]

windbg提供了兩種方式來啟動應用,這裡以ruby的irb為例:

open executable:ruby -x "\irb.bat",這時候我們可以很方便地在任何地方設定斷點,包括main函式。

也可以執行irb之後,在windbg裡選擇attach to a process, 在列出的程序中選擇ruby.exe。

[img]

要探索ruby的內部奧秘,最重要的技巧是設定斷點,而其中最經常使用的是未定斷點。

如果乙個斷點是設定在某個還未載入的函式名上,則稱為延遲、虛擬或未定斷點。 (這些術語可交替使用。) 未定斷點沒有被關聯到任何具體被載入的模組上。每當乙個新的模組被載入時,會檢查該函式名。如果這個函式出現,偵錯程式計算虛擬斷點的實際位置並啟用它。

在windbg裡設定斷點的幾個方法:

在windbg中設定斷點的格式有如下幾種:

2. 函式偏移量:如driverentry+5c.

3. 源**+行數 :`[[module!]filename][:linenumber]`

4. 可以對模組中的某個類的方法設定斷點。

[b]檢視ruby入口點[/b]

ruby是個c編寫的應用,通常入口點就是main函式,用open executable的方式啟動irb

在arguments裡填寫上 -x "\irb.bat"

[code]

bu main

g[/code]

windbg會捕獲main這個函式的呼叫,並同時顯示出main的源**:

[img]

用WinDbg探索CLR世界 2 執行緒

2 執行緒 在配置好windbg之後,我們載入乙個clr程式並執行至clr被載入,然後開始我們的clr探索之旅。首先,使用 threads命令看看當前clr中有哪些執行緒正在執行 以下為引用 0 004 threads threadcount 2 unstartedthread 0 backgrou...

用 WinDbg 診斷CPU占用高

2.安裝windbg,這個就不贅述了。需要注意的是有 windbg x64 和 windbg x86 兩個,應該按dmp檔案 的伺服器開啟。3.按 ctrl d 開啟 dmp 檔案,注意直接點那個工具欄上的開啟檔案的圖示是錯誤的。4.載入 sos.dll 檔案。這個最好是直接把 dmp 檔案 伺服器...

怎樣用windbg檢視Hashtable

how to view hashtable using windbg 由於hashtable結構比較複雜,但又比較常用,所以這次記錄一下用windbg去view hashtable的過程。先看一下我的測試 class program 然後執行該程式,接著開啟windbg attatch上這個程序。d...