覆蓋測(cè)試中高效代碼插樁技術(shù)的研究
2.1 CodeTest 工具的插樁技術(shù)分析
Codetest 的插樁過(guò)程簡(jiǎn)單來(lái)說(shuō)分為兩步:
(1)對(duì)源代碼進(jìn)行預(yù)編譯;被測(cè)程序首先會(huì)通過(guò)CodeTest 的編譯驅(qū)動(dòng)器調(diào)用程序的原編譯器進(jìn)行預(yù)編譯,通常是進(jìn)行宏替換。
(2)對(duì)預(yù)編譯后的文件進(jìn)行插樁,生成插樁后的.C 文件和.IDB 的插樁符號(hào)數(shù)據(jù)庫(kù)文件;預(yù)編譯完成后,CodeTest的插裝器(即源代碼分析程序)據(jù)不同的參數(shù)對(duì)預(yù)編譯后的源代碼進(jìn)行相應(yīng)方式的自動(dòng)插樁,即在需要插樁的位置寫(xiě)入一條賦值語(yǔ)句(如:amc_ctrl=0x74100010),并把插入的標(biāo)記送入數(shù)據(jù)庫(kù)文件中生成一個(gè)符號(hào)數(shù)據(jù)庫(kù)暫存起來(lái),為以后的分析時(shí)調(diào)用。然后,CodeTest的編譯驅(qū)動(dòng)器會(huì)調(diào)用原編譯器對(duì)插樁后的代碼進(jìn)行編譯生成可執(zhí)行目標(biāo)代碼送到目標(biāo)板上運(yùn)行。當(dāng)程序在目標(biāo)系統(tǒng)運(yùn)行到插樁點(diǎn)的位置時(shí),目標(biāo)板的控制總線(xiàn)和地址總線(xiàn)上會(huì)出現(xiàn)相應(yīng)的控制信號(hào)和地址信號(hào)。當(dāng) CodeTest的輔助硬件(信號(hào)捕獲探頭)從控制總線(xiàn)和地址總線(xiàn)上監(jiān)視到符合以上條件的信號(hào)時(shí),CodeTest會(huì)主動(dòng)地從數(shù)據(jù)總線(xiàn)上把數(shù)據(jù)捕獲回來(lái)送到CodeTest的內(nèi)存中暫存并對(duì)這些數(shù)據(jù)進(jìn)行預(yù)處理,然后將預(yù)處理后的數(shù)據(jù)通過(guò)局域網(wǎng)送到工作平臺(tái)上。通過(guò)與前面生成的符號(hào)數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行比較,我們就此得知當(dāng)前程序的運(yùn)行狀態(tài),借此完成對(duì)嵌入式軟件的性能分析,高級(jí)覆蓋率分析,內(nèi)存分析和大容量的代碼跟蹤。
CodeTest是一個(gè)硬件輔助軟件的測(cè)試與分析工具,它吸取軟件打點(diǎn)技術(shù),并對(duì)這種技術(shù)進(jìn)行了改善,純軟件工具插入的是一個(gè)函數(shù),而 CodeTest插入的是一條賦值語(yǔ)句,它在匯編級(jí)也是一條語(yǔ)句,所以它執(zhí)行的時(shí)間非常短,占用的空間也非常少,同時(shí)避免了被其它的中斷所中斷,所以它對(duì)目標(biāo)系統(tǒng)的影響非常?。?%-15%)。
2.2 程序插樁的切入點(diǎn)
CodeTest 作為一種商品,很多技術(shù)不對(duì)外公開(kāi) ,但是我們?nèi)钥梢悦靼灼洳鍢兜脑?,進(jìn)而以此為參考對(duì)插樁技術(shù)做進(jìn)一步的研究;在國(guó)內(nèi),雖有很多工具使用了插樁技術(shù),但是都不夠高效, 為了方便研究我們選擇GCC 作為插樁技術(shù)研究的平臺(tái)。
GCC 是一個(gè)高度優(yōu)化,高度可移植,且廣泛使用的編譯系統(tǒng)。它能處理多種語(yǔ)言,包括C/C++、Fortran、Java、Ada 等多種語(yǔ)言前端,而且后端幾乎支持所有的處理器結(jié)構(gòu)。同時(shí)GCC作為源碼開(kāi)放的軟件,可以自由修改和使用。
圖1 是GCC 增加插樁階段后的編譯流程。
GCC 編譯器的工作流程大致可以分為前端、中端和后端。中端Gimple 層是高版本GCC 中新增加的,是用來(lái)對(duì)經(jīng)過(guò)詞法、語(yǔ)法分析后的程序進(jìn)行優(yōu)化和整理的階段,我們這里可以暫時(shí)忽略這個(gè)階段。前端包括預(yù)處理和詞法、語(yǔ)法分析。
預(yù)處理通常是做宏替換處理。詞法、語(yǔ)法分析的輸入是預(yù)處理后的文件,輸出是AST ,AST 經(jīng)過(guò)優(yōu)化后產(chǎn)生Gimple Tree,然后交給RTL 模塊去處理。RTL(Register Transfer Language)是一種中間語(yǔ)言,作為編譯器工作的后端,是GCC內(nèi)部使用的一種能對(duì)實(shí)際體系結(jié)構(gòu)作抽象的,與硬件無(wú)關(guān)的語(yǔ)言。在GCC 中將生成的中間代碼表達(dá)式以一種雙向鏈表的形式組織起來(lái)的,在鏈表中有一些特殊的節(jié)點(diǎn),這些節(jié)點(diǎn)記錄了程序的結(jié)構(gòu)信息。
GCC 編譯器前端的工作完成后,詞法語(yǔ)法分析器已經(jīng)識(shí)別完程序的所有特征,因此將詞法、語(yǔ)法分析至Gimple 這個(gè)階段作為代碼插樁的切入點(diǎn)是完全可行的。然后,GCC 利用中間代碼生成會(huì)匯編代碼時(shí),如果掃描到RTL 中的特殊節(jié)點(diǎn)就會(huì)根據(jù)用戶(hù)的需要適當(dāng)?shù)牟迦胍恍┩瓿尚畔⒉杉δ艿膮R編代碼行,從而就可以實(shí)現(xiàn)代碼插樁。但是這種做法有兩個(gè)缺點(diǎn):一是代碼的插樁和編譯器的結(jié)合很緊密,并且在匯編代碼的生成過(guò)程中需要針對(duì)不同的CPU 生成不同的匯編代碼,與CPU 的關(guān)聯(lián)性很強(qiáng),不便于移植;而是,當(dāng)程序很大時(shí),探針的植入會(huì)造成代碼的膨脹,及進(jìn)行信息采集的代碼的插入就需要很多時(shí)間。
評(píng)論