国产chinesehdxxxx野外,国产av无码专区亚洲av琪琪,播放男人添女人下边视频,成人国产精品一区二区免费看,chinese丰满人妻videos

卷2:第4章 GDB

2018-02-24 15:55 更新

原文鏈接:http://www.aosabook.org/en/gdb.html

作者:Stan Shebs

GDB, 即GNU調(diào)試器(GNU Debugger)。它誕生自開源軟件基金會(huì)(Free Software Foundation)成立之初的第一批程序,并一直是免費(fèi)和開源軟件系統(tǒng)中的主要成員。最初GDB只是Unix系統(tǒng)上一個(gè)簡(jiǎn)單的源碼層次的調(diào)試器,代碼量不過(guò)數(shù)千行C代碼,后來(lái)逐步發(fā)展壯大,拓展到包括嵌入式系統(tǒng)在內(nèi)多個(gè)平臺(tái),代碼量也達(dá)到了上百萬(wàn)行。

GDB在發(fā)展,不斷地滿足著新的用戶需求并增加新的功能。這一章將我們將介紹GDB的整體內(nèi)部結(jié)構(gòu),探討一下GDB是如何做到這一點(diǎn)的。

4.1 目標(biāo)

GDB的設(shè)計(jì)目標(biāo)是一個(gè)針對(duì)使用命令式(imperative)語(yǔ)言(例如C,C++,Ada,Fortran等)編寫的程序的符號(hào)調(diào)試器。使用GDB原始命令行界面的一個(gè)示例如下:

% gdb myprog
[...]
(gdb) break buggy_function
Breakpoint 1 at 0x12345678: file myprog.c, line 232.
(gdb) run 45 92
Starting program: myprog
Breakpoint 1, buggy_function (arg1=45, arg2=92) at myprog.c:232
232     result = positive_variable * arg1 + arg2;
(gdb) print positive_variable
$$1 = -34
(gdb)

GDB能顯示程序中的錯(cuò)誤,開發(fā)者據(jù)此判斷錯(cuò)誤的類型并找到解決的方案。

設(shè)計(jì)GDB最需要考慮的是調(diào)試工具的交互性,因?yàn)橛脩粼谡{(diào)試時(shí)提交的請(qǐng)求是不可預(yù)測(cè)的。此外,GDB還需要深入到系統(tǒng)最底層,因?yàn)榫幾g器會(huì)充分利用硬件的各種選項(xiàng)來(lái)優(yōu)化程序的性能。

GDB還要求能夠調(diào)試不同編譯器編譯的程序(不僅僅是GNU C編譯器),能夠調(diào)試過(guò)時(shí)編譯器編譯的程序,能夠調(diào)試符號(hào)信息丟失、過(guò)時(shí)或錯(cuò)誤的程序。所以,另外一個(gè)設(shè)計(jì)要求是,即使程序中的數(shù)據(jù)丟失、損壞或干脆無(wú)法理解,GDB也能夠繼續(xù)工作并發(fā)揮作用。

接下來(lái)的幾章假定讀者熟悉GDB基本的命令行使用方法。如果你還是新手,建議先用一用GDB并細(xì)讀一下手冊(cè)[SPS+00]

4.2 GDB的起源

GDB程序歷史悠久,早在1985年就已經(jīng)存在。它的作者是Richard Stallman,這個(gè)人還編寫了GCC,GNU Emacs和其它一些早期的GNU軟件。(由于當(dāng)時(shí)并沒有軟件倉(cāng)庫(kù),GDB開發(fā)過(guò)程的細(xì)節(jié)已不為人所知。)

GDB的最早的穩(wěn)定版本在1988年發(fā)布,但在今天的GDB源碼中已經(jīng)找不到多少相似的地方了,GDB被完全重寫過(guò)至少一次。 令人驚訝的是,早期的GDB并沒有太大的野心,后來(lái)的平臺(tái)移植和功能擴(kuò)展并沒有包括在GDB最初的計(jì)劃之中。

4.3 GDB結(jié)構(gòu)框圖

set print elements 80"使用了3個(gè)表格,第一個(gè)是包含了所有命令的表格,第二個(gè)是包含了set選項(xiàng)的表格,第三個(gè)是print選項(xiàng)的表格,其中elements選項(xiàng)用于控制打印一個(gè)集合體(如字符串或數(shù)組)中輸出對(duì)象的個(gè)數(shù)。最后瀑布型表格將控制權(quán)交給一個(gè)實(shí)際的命令處理函數(shù),命令的參數(shù)將傳遞給這個(gè)函數(shù)來(lái)解析。一些命令, 比如run, 處理參數(shù)的方式和傳統(tǒng)C語(yǔ)言的argc/argv標(biāo)準(zhǔn)類似, 而其它一些命令, 比如print, 則假定參數(shù)是一個(gè)程序表達(dá)式, 并將其完整傳遞給源碼解析器。

機(jī)器界面

一種GUI調(diào)試器方案是將GDB作為圖形用戶界面程序的后端,將鼠標(biāo)點(diǎn)擊翻譯成GDB命令,然后將打印的結(jié)果顯示在窗口中。這種方案已經(jīng)在一些軟件中實(shí)現(xiàn),比如KDbg和DDD(Data Display Debugger)。但這個(gè)方法仍然不理想,因?yàn)橛袝r(shí)候顯示結(jié)果時(shí)為了可讀性會(huì)省略掉一些細(xì)節(jié),前端提供上下文的能力也會(huì)影響到結(jié)果的顯示。

為解決這個(gè)問(wèn)題,GDB提供了一個(gè)被稱為機(jī)器界面(Machine Interface,MI)的接口。本質(zhì)上MI仍然是一個(gè)命令行界面,但是命令和結(jié)果都增加了額外的語(yǔ)法,使得其意義更為顯然:每個(gè)參數(shù)都使用了引號(hào),復(fù)雜輸出則使用定界符來(lái)分組,使用參數(shù)名來(lái)分塊。此外, MI的命令還可以加上順序標(biāo)識(shí)符作為前綴, 并在結(jié)果中返回,保證了結(jié)果和命令的匹配。

為了比較兩種界面, 分別給出它們對(duì)于同一命令的使用情況。下面是正常的step命令及GDB的響應(yīng)

(gdb) step

buggy_function (arg1=45, arg2=92) at ex.c:232
232  result = positive_variable * arg1 + arg2;
With the MI, the input and output are more verbose, but easier for other software to parse accurately:

下面是MI的輸入和輸出,雖然顯得有些冗余,但更加精確,便于第三方軟件進(jìn)行解析。

4321-exec-step

4321^done,reason="end-stepping-range",
      frame={addr="0x00000000004004be",
             func="buggy_function",
             args=[{name="arg1",value="45"},
                   {name="arg2",value="92"}],
             file="ex.c",
             fullname="/home/sshebs/ex.c",
             line="232"}

Eclipse[ecl12]開發(fā)環(huán)境是最著名的使用MI的調(diào)試環(huán)境。

其它用戶界面

其它GDB前端軟件包括基于tcl/tk的GDBtk或Insight,基于文字界面的TUI(最初由Hewlett-Packard開發(fā))。GDBtk是一個(gè)傳統(tǒng)的多面板圖形用戶界面,使用tk軟件庫(kù)開發(fā),而TUI是一個(gè)在終端中使用的分屏文字界面。

4.10. 開發(fā)過(guò)程

維護(hù)者

作為一個(gè)GNU程序,GDB的開發(fā)遵循"大教堂(cathedral)"開發(fā)模型。GDB最初由Stallman編寫,隨后維護(hù)者幾易其人,每個(gè)人都是身兼設(shè)計(jì)師,補(bǔ)丁審查員,發(fā)布管理員數(shù)職,他們有權(quán)訪問(wèn)僅向少數(shù)Cygnus雇員開放的源碼倉(cāng)庫(kù)。

1999年,GDB被遷移到一個(gè)公共源碼倉(cāng)庫(kù),維護(hù)團(tuán)隊(duì)也擴(kuò)展到了幾十人,并且還有一些擁有簽入(commit)權(quán)限的個(gè)人從旁協(xié)助。這個(gè)模式顯著加速了GDB的開發(fā),從原來(lái)的每周10個(gè)簽入增加到了100個(gè)以上。

測(cè)試,測(cè)試

由于GDB高度依賴于特定平臺(tái),幾乎涵蓋全系列的計(jì)算設(shè)備,而且包含了數(shù)以百計(jì)的命令,選項(xiàng)以及使用風(fēng)格,即使是一個(gè)經(jīng)驗(yàn)豐富的GDB黑客也難以完全預(yù)料一個(gè)修改所產(chǎn)生的后果。

于是,測(cè)試套件變得舉足輕重。GDB的測(cè)試套件包含了眾多測(cè)試程序以及expect腳本,使用一個(gè)基于tcl被稱為DejaGNU的測(cè)試框架。其基本模式是, 每個(gè)腳本驅(qū)動(dòng)GDB去調(diào)試一個(gè)測(cè)試程序, 然后向其發(fā)送命令, 并使用模式匹配來(lái)判斷結(jié)果正確與否。

這個(gè)測(cè)試套件還能進(jìn)行交叉調(diào)試,既支持真實(shí)硬件也支持模擬器,它還能對(duì)于特定平臺(tái)或配置進(jìn)行測(cè)試。

到2011年底,GDB測(cè)試套件包含了大約18000個(gè)測(cè)試用例,包括了基本功能測(cè)試,語(yǔ)言特性測(cè)試,體系特性測(cè)試,和MI測(cè)試。所有這些測(cè)試都是通用的,適用于所有配置。GDB需要志愿者來(lái)測(cè)試打補(bǔ)丁后的源碼,新的功能也需要新的測(cè)試。但是,因?yàn)闆]有人能在所有平臺(tái)上測(cè)試同一修改,要實(shí)現(xiàn)測(cè)試的完全通過(guò)是不現(xiàn)實(shí)的。對(duì)于本地調(diào)試來(lái)說(shuō), 主干GDB測(cè)試時(shí)失敗10-20次左右是可以授受的, 嵌入式系統(tǒng)則更容易出錯(cuò)。

4.11. 經(jīng)驗(yàn)教訓(xùn)

開放是王道

GDB是"大教堂"開發(fā)模型的典范,在該模式下,維護(hù)者嚴(yán)密控制源碼,而外部用戶則跟蹤其進(jìn)度。補(bǔ)丁提交數(shù)目較少,封閉的開發(fā)過(guò)程實(shí)際上并不鼓勵(lì)補(bǔ)丁。自從采用開放模式之后,補(bǔ)丁數(shù)量顯著增多,而軟件質(zhì)量則一如既往,甚至更好。

制訂計(jì)劃, 但計(jì)劃趕不上變化

開源軟件開發(fā)過(guò)程實(shí)際上會(huì)比較混亂,因?yàn)殚_發(fā)者之間是松散的,流動(dòng)性很大。

但是,制訂開發(fā)計(jì)劃并發(fā)布仍然很有意義。這有助于指導(dǎo)開發(fā)者完成相關(guān)任務(wù),而且能夠吸引潛在的贊助者,另外志愿者在嘗試做出貢獻(xiàn)時(shí)也能有一定的依據(jù)。

但是不要嘗試設(shè)置截止時(shí)間,即使是每個(gè)人都熱情地朝著一個(gè)方向努力,也不要指望大家都能全身心地投入并按時(shí)完成任務(wù)。

鑒于此,不要堅(jiān)持一個(gè)已經(jīng)過(guò)時(shí)的計(jì)劃。長(zhǎng)期以來(lái),GDB都有重構(gòu)為軟件庫(kù)libgdb的計(jì)劃,這樣, 別的程序就可以通過(guò)使用libgdb來(lái)實(shí)現(xiàn)一個(gè)擁有GUI的調(diào)試器。開發(fā)人員甚至嘗試過(guò)將構(gòu)建libgdb.a作為整個(gè)構(gòu)建過(guò)程的一個(gè)中間步驟。雖然這個(gè)想法一直存在,但隨著Eclipse和MI的成功,libgdb被擱置了起來(lái),到2012年1月這個(gè)想法最終壽終正寢。

無(wú)比聰明該多好

看到曾經(jīng)提交的修改,我們也許會(huì)想:為什么一開始不這么做呢? 唉,只因?yàn)槲覀儾粔蚵斆鳌?/p>

我們本可以預(yù)料到GDB會(huì)如此流行,并且會(huì)移植到數(shù)以百計(jì)的平臺(tái)上,還支持本地和交叉調(diào)試。如果事先知道這些,說(shuō)不定一開始就會(huì)使用gdbarch對(duì)象,而不會(huì)數(shù)年來(lái)都在用陳舊的宏和全局變量,目標(biāo)向量也早該出現(xiàn)。

我們本可以預(yù)料到GDB將會(huì)被用到GUI中, 畢竟1986年Mac和X窗口系統(tǒng)已經(jīng)出現(xiàn)了2年。與其設(shè)計(jì)一個(gè)傳統(tǒng)的命令行界面,我們更應(yīng)該讓其支持異步事件處理。

然而,真正的教訓(xùn)不在于GDB開發(fā)者們有多蠢,而是我們不可能如此聰明地未卜先知。1986年, 窗口-鼠標(biāo)風(fēng)格的界面的未來(lái)還并不清晰, 我們預(yù)料不到它會(huì)像今天這樣流行,如果第一個(gè)版本的GDB就設(shè)計(jì)為在GUI下使用,我們就可以稱得上天才了,但這種好運(yùn)不是人人都能有的。相反,在一個(gè)有限的范圍內(nèi)讓GDB有所作為,我們已經(jīng)為今后的擴(kuò)展和重構(gòu)打下了用戶基礎(chǔ)。

學(xué)會(huì)接受缺陷

盡力完成過(guò)渡,但是時(shí)間總是太快,你只能接受缺陷。

在2003年的GCC峰會(huì)上, Zack Weinberg哀嘆GCC的"不完整過(guò)渡",新的底層結(jié)構(gòu)已經(jīng)引入,但是舊的卻尾大不掉。GDB有著同樣的問(wèn)題,但是我們應(yīng)該看到積極的一面,因?yàn)楫吘挂恍┻^(guò)渡已經(jīng)完成,比如目標(biāo)向量,gdbarch等等。雖然過(guò)渡需要多年來(lái)完成,調(diào)試卻要一直繼續(xù)。

謹(jǐn)防著迷于代碼

當(dāng)你遇到一個(gè)對(duì)你非常重要的項(xiàng)目,你會(huì)花費(fèi)大量時(shí)間在單個(gè)代碼上, 你會(huì)很容易沉迷其中,甚至為了迎合代碼而改變自己的想法。但是,很有可能你已經(jīng)誤入歧途,退一步說(shuō)不定海闊天空。

這樣的事情要杜絕發(fā)生。

所有代碼都源自于一系列清醒的判斷:有些來(lái)自靈感,有些則不是。1991年節(jié)省空間的小伎倆對(duì)于2011年的數(shù)個(gè)G的內(nèi)存來(lái)說(shuō)是毫無(wú)意義的。

GDB曾經(jīng)支持Gould超級(jí)計(jì)算機(jī)。當(dāng)他們?cè)?000年關(guān)閉最后一臺(tái)機(jī)器時(shí),保留對(duì)這種機(jī)器的支持已是毫無(wú)意義。那些代碼只是GDB過(guò)往歷史中的一些小小篇章,然而現(xiàn)在大部分的發(fā)行版中仍然有些"懷舊"。

事實(shí)上,很多激進(jìn)的修改已經(jīng)擺上日程或已經(jīng)開展,包括對(duì)Python腳本的支持,對(duì)并行多核平臺(tái)的支持,重編碼為C++等。這些修改可能要花費(fèi)數(shù)年,但其動(dòng)機(jī)卻來(lái)自于今天(等到它們完成時(shí)說(shuō)不定已經(jīng)過(guò)時(shí))。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)