GDB簡明指南(轉)

GDB簡明指南

GDB是一個基於傳統命令行形式實現的控制檯程序(其界面如圖2.3所示)。雖然在GDB的長期進化中,GDB接受了大量優秀的圖形用戶界面(GUI)(如圖2.4和圖2.5所示),但Turbo DebuggerTD)風格之類的交互調試目前在UNIX世界中依然不流行。這通常都是從Windows平臺移植程序的人的致命錯誤,這些人的思維方式不可避免地貼上了“M$”標籤。這裏簡單的模擬並不適用:如果TD是長凳工具,那麼GDB就是具有編程控制的車牀。你遲早都會喜歡它的。

爲了在源代碼級進行調試,程序必須在編譯時包含調試信息。在GCC中,使用命令行選項 –g 就能實現這一點。如果沒有調試信息,GDB將在反彙編級上進行調試。

被調試文件的文件名通常都是通過命令行來傳遞的,其格式如下:gdb文件名。如果要調試一個活動的進程,請在命令行中指定其進程標誌。如果要調試內核轉儲,請使用命令行選項 –core==內核名。這三個參數可以同時使用,還可以使用命令行命令target來在它們之間進行切換。命令行命令target exec切換到被調試的文件,target child切換到附加的進程,target core切換到內核轉儲。可選用的命令行參數q用於禁止顯示版權信息。

2.3  傳統的GDB界面

將應用程序加載到調試器之後,必須設置斷點。請使用break命令來設置斷點(其簡稱是b)。例如,命令b main將斷點設在C語言的main函數上,而b _start將斷點設在可執行和鏈接格式(ELF)文件的入口點(有的文件的入口點具有不同的名稱)。也可以將斷點設置在任何地址上,比如,b *0x8048424或者b *$eax。寄存器的名稱要用小寫字母,並以美元符號爲前綴。GDB理解兩種“跨平臺”的寄存器:$pc用於命令指針,而$sp用於堆棧指針。但是請記住,程序被裝載到調試器之後並不能立即看到寄存器。只有用命令run(r)啓動被調試的進程後,寄存器纔會顯示出來。

調試器執行決定應該設置軟件斷點還是硬件斷點。最好不要干涉這一過程。並非所有的調試器版本都支持強制設置硬件斷點的的命hbreak。例如,我所用的版本就不支持該命令。用於數據的斷點在GDB中稱爲觀察點。當地址addr處的數據被改變時,命令watch addr將調用調試器。當讀或寫操作訪問地址addr時,命令awatch addr將調用調試器。當讀操作訪問地址addr時,命令rwatch addr將調用調試器,但並非所有版本的調試器都支持這一命令。使用命令info break可以查看所有已設置的斷點和觀察點。命令clear刪除所有的斷點,而命令clear addr刪除所有設置在給定的函數、地址或者行號上的斷點。諸如enabledisable之類的命令用於暫時地允許和禁止斷點。還有一種常規命令的高級語法用於處理斷點,可以在文檔中找到該語法的詳細描述。命令continue(c)用於繼續執行被命令b所中斷的程序,即從斷點繼續執行。

2.4  調試器DDDGDB提供的圖形用戶界面

2.5  加在GDB上的另一種圖形用戶界面

命令next Nn N執行下面的N行代碼,會越過嵌套的函數,而命令step Ns N)會進入嵌套的函數。如果沒有指定N,則只執行一行代碼。命令nextistepi的功能與它們相似。不同的是,這兩條命令用於機器指令,而不是源代碼的行數。它們通常與命令display/i $pc(x/i $pc)一起使用,這條命令要求調試器顯示當前的機器指令。每一次會話只需調用一次該命令就足夠了。

命令jump addr將控制轉到程序的任意位置,而命令call addr/fname調用參數fname所指定的函數。即使是SoftIce也沒有提供這一命令!它是非常有用的,也是用戶常常要求提供的命令。另外幾條很有用的命令包括finish,它用於在退出當前函數之前中斷執行(它等效於SoftIce的命令P RET),以及命令until addru addr,它用於繼續執行直到到達指定的位置爲止。如果啓動命令時沒帶參數,則當下一條命令到達時停止執行(這對循環特別重要)。命令return立即取消函數的執行。

命令print expressionp expression用於輸出指定表達式(例如p 1+2)的值、指定變量的內容(p my_var)、指定寄存器的內容(p *$eax)或者內存單元的內容(p *0x8048424p *$eax)。如果需要輸出幾個單元,就使用命令x/Nh addr,其中N是要輸出的單元的數量。此時並不需要在地址前面加上星號。

命令info register(i r)輸出所有可用寄存器的值。修改內存單元和寄存器的內容可用命令set來實現。例如,set $eax = 00寫入寄存器eax命令set var may_var = $ecx將寄存器ecx的值賦給變量my_var,而命令set {unsigned char*} 0x8048424 = 0xCC將數字0xCC寫入字節地址。命令disassemble _addr_from _addr_to以反彙編清單的形式輸出內存的內容,表示的格式由命令set disassembly-flavor確定。

命令info frameinfo argsinfo local分別顯示堆棧幀,函數參數和局部變量的內容。爲了切換到父函數的幀,使用命令frame N。命令backtracebt所做的事情與Windows調試器的命令call stack相同。當研究內核轉儲時,這是不可或缺的。

GDB進行工作的一個完整過程大致如下:將程序裝入調試器,執行命令b main(如果不成功,則使用b _start),然後執行命令r。用命n或者s一步一步地調試程序。如果需要,指定x/i $pc使GDB顯示當前所執行的代碼。執行命令quitq以退出調試器。可在文檔中找到所有其他命令的詳細描述。希望這裏列出的GDB命令簡明指南能對你有所幫助,而不至於迷失在信息叢林中。

比較UNIXWindows的調試器,馬上就能發現:後者比前者落後許多,而且能夠證明Windows調試器並不是針對專業人士的。三維顯示的按鈕、可以縮放的圖標、彈出式菜單和其他過於花哨的東西,確實很好看。然而,需要不停地按<F10>鍵,你不覺得厭煩嗎?在GDB中,通過編寫宏(或者使用已有的宏)可以使事情變得方便許多,因爲可以編程實現的每一件事在此都已經實現編程,而且可以免費使用。

UNIX中的調試工具功能強大而且使用方便。除了GDB外,還有一些其他的產品。惟一缺少的東西是可以基於沒有符號信息和源代碼的二進制文件工作的高質量系統級內核調試器。有一段時期UNIX存在多個平臺,而且需要進行不同平臺之間的移植,這在UNIX中留下了一個憂鬱記號,以及實現可移植性和跨平臺支持的願望。在這種條件下,破解當然是很困難的!不過,源程序的可用性可以減少一些困難。

2.1.4  追蹤系統調用

追蹤系統調用打開了一扇真實窗口,透過它可以瞭解正被研究的程序的內幕。它可以顯示正被調用的函數的名稱,它們的參數和返回值。對於編程新手來說,有一個共同的問題是常常忘記“額外的”錯誤檢查,而調試器不是查找這類錯誤的最佳工具。可以使用truss或者ktrace類的標準工具,或者使用商業代碼分析程序的自由軟件版本。

清單2.6顯示了使用truss所獲得的日誌。該程序試圖打開名稱爲my_good_file的文件,但是找不到該文件,從而導致程序出錯。這是最簡單的案例。然而,一個著名的規則認爲全部開發時間的99%花在尋找錯誤上,而這些錯誤都是不值得查找的!

 

清單2.6  使用truss查找錯誤

2.1.5  相關鏈接

r  GDB內幕(http://gnuarm.org/pdf/gdbint.pdf):一本關於GDB內幕的極好的指南。當需要改善源程序時,它非常有用。

r ptrace追蹤進程(http://linuxgazette.net/issue81/sandeep.html):一篇關於在Linux中使用最簡單的追蹤程序中的例子來進行追蹤的論文(在FreeBSD中的情形完全不同)。

r 在源程序中修正漏洞(http://www.linux-mag.com/2004-04/code_01.html):一篇關於利用源代碼分析進行早期查錯的論文。

r 使用CTrace庫(http://ctrace.sourceforge.net):一篇關於使用該庫來調試多線程應用程序的論文。

r 內核和用戶空間調試技術(德語文章)(http://www.unfug.org/files/debugging.pdf):專門論述調試,描述少爲人知的GDB結構細節的論文集。

r ELF/INTEL系統的逆向工程(法語文章)(http://www.sstic.org/SSTIC03/arcticles/ SSTIC03-Vanegue_roy-Reverse_Intel_ELF.pdf):關於在沒有源程序時在i386平臺上研究和調試ELF文件的論文。 

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