全数字实时仿真平台SkyEye目标码覆盖率关键技术
1. 研究背景
1.1零插樁目標(biāo)碼覆蓋率統(tǒng)計(jì)技術(shù)
隨著武器裝備的復(fù)雜度的大幅度增加,運(yùn)行在裝備上的嵌入式系統(tǒng)也越來(lái)越復(fù)雜,功能迭代越來(lái)越多,代碼中就可能就會(huì)存在部分無(wú)用代碼,或者在執(zhí)行過(guò)程中無(wú)法測(cè)試覆蓋的分支,這可能就會(huì)給軟件帶來(lái)很大的漏洞,嚴(yán)重降低軟件的可靠性。因此,需要構(gòu)建一個(gè)能夠動(dòng)態(tài)分析代碼執(zhí)行覆蓋情況的能力,來(lái)檢測(cè)代碼中未執(zhí)行覆蓋情況。
通過(guò)覆蓋率統(tǒng)計(jì)分析,得出嵌入式軟件執(zhí)行覆蓋情況,查看軟件中有那些函數(shù)未執(zhí)行,函數(shù)中哪些分支未執(zhí)行,由此分析軟件中函數(shù)為什么沒(méi)有執(zhí)行,函數(shù)中分支為什么沒(méi)有執(zhí)行,調(diào)整測(cè)試方法使盡可能多的函數(shù)和函數(shù)分支得到測(cè)試,大大提升軟件的可靠性。
在覆蓋率分析時(shí)需要分析覆蓋率、指令函數(shù)覆蓋率、指令函數(shù)分支覆蓋率、源代碼行覆蓋率、源代碼函數(shù)覆蓋率、源代碼函數(shù)分支覆蓋率。
目前大部分覆蓋率統(tǒng)計(jì)技術(shù)都是通過(guò)在源代碼中插樁的方式來(lái)進(jìn)行統(tǒng)計(jì)覆蓋率情況,就是在函數(shù)入口,分支語(yǔ)句等地方寫(xiě)入特定標(biāo)志語(yǔ)句,執(zhí)行后統(tǒng)計(jì)標(biāo)志信息,來(lái)計(jì)算覆蓋率情況,但是這樣做會(huì)帶來(lái)很多的額外成本,如:需要修改源代碼,目標(biāo)碼文件增大等問(wèn)題。這就增加了人工成本,或者由于目標(biāo)碼過(guò)大無(wú)法下載到目標(biāo)板等等問(wèn)題。為解決這些問(wèn)題,我們需要實(shí)現(xiàn)一個(gè)不需要插樁就能統(tǒng)計(jì)覆蓋率的技術(shù)。
2. 關(guān)鍵技術(shù)
2.1零插樁目標(biāo)碼覆蓋率統(tǒng)計(jì)技術(shù)
(1)零插樁技術(shù)
零插樁統(tǒng)計(jì)覆蓋率需要分析的是嵌入式軟件的基本特性和執(zhí)行特性。在不插樁的前提下,使用反匯編工具生成嵌入式軟件目標(biāo)碼的反匯編文件,通過(guò)分析反匯編文件獲取想要的基礎(chǔ)信息,如函數(shù)指令信息,地址對(duì)應(yīng)源碼行號(hào)信息等。在與仿真驗(yàn)證工具配合獲取執(zhí)行PC地址信息,分析嵌入式軟件的執(zhí)行覆蓋情況,實(shí)現(xiàn)零插樁分析覆蓋率的目的。
(2)多架構(gòu)嵌入式軟件目標(biāo)碼分析技術(shù)
針對(duì)不同架構(gòu),如:ARM、SPARC、DSP、PPC等構(gòu)建相應(yīng)的嵌入式軟件目標(biāo)碼分析技術(shù),能夠準(zhǔn)確分析嵌入式軟件目標(biāo)碼的反匯編文件中的函數(shù)名稱、函數(shù)所有的指令地址信息、函數(shù)中分支指令的信息,分支指令的PC地址,分支指令的跳轉(zhuǎn)地址,分支指令的下一條地址等信息、PC指令地址所對(duì)應(yīng)源碼的行號(hào)信息等。通過(guò)這些基礎(chǔ)信息,與執(zhí)行信息配合實(shí)現(xiàn)統(tǒng)計(jì)覆蓋率信息。
(3)數(shù)據(jù)緩存技術(shù)
反匯編和數(shù)據(jù)分析都是一個(gè)比較耗時(shí)的階段,對(duì)于大型嵌入式軟件可能會(huì)有幾十萬(wàn)甚至上百萬(wàn)的指令數(shù)量級(jí),每次進(jìn)行分析都會(huì)耗費(fèi)一定的時(shí)間,為減少時(shí)間上的浪費(fèi),提出數(shù)據(jù)緩存技術(shù),在執(zhí)行的目標(biāo)碼不變的情況下,盡可能的存儲(chǔ)下所有固定分析數(shù)據(jù),如目標(biāo)碼的反匯編文件,反匯編文件分析結(jié)果,源碼文件分析結(jié)果等。都可以存儲(chǔ)下來(lái),但是在目標(biāo)碼文件修改后,所有緩存文件都需要進(jìn)行相應(yīng)更新。
3. 技術(shù)途徑
3.1零插樁目標(biāo)碼覆蓋率統(tǒng)計(jì)技術(shù)
(1) 零插樁技術(shù)
零插樁技術(shù)主要需要分析嵌入式軟件的目標(biāo)碼及源代碼,通過(guò)提取目標(biāo)碼及源代碼中的特征信息,獲取函數(shù)信息,及函數(shù)中的分支信息。整體流程如下:
?
(2)動(dòng)態(tài)執(zhí)行PC信息
在仿真環(huán)境中,運(yùn)行嵌入式軟件就是將嵌入式軟件編譯好的二進(jìn)制文件解析成對(duì)應(yīng)的匯編指令寫(xiě)入仿真硬件環(huán)境中,然后一條條執(zhí)行指令,模擬出嵌入式軟件在真實(shí)環(huán)境中的運(yùn)行效果。在運(yùn)行過(guò)程中將執(zhí)行的每條指令地址記錄下來(lái)就可以得到執(zhí)行信息。
記錄指令執(zhí)行信息通過(guò)創(chuàng)建一個(gè)記錄設(shè)備來(lái)完成記錄工作,每次處理器執(zhí)行一條指令時(shí)將地址信息傳給記錄設(shè)備由記錄設(shè)備存儲(chǔ)執(zhí)行地址信息。在記錄設(shè)備中,會(huì)根據(jù)收到的地址信息創(chuàng)建相應(yīng)的地址表來(lái)記錄執(zhí)行情況,當(dāng)收到地址信息后檢索當(dāng)前地址表是否有該地址如果沒(méi)有將創(chuàng)建一塊地址空間映射該地址,如果有該地址的地址表,將會(huì)在該地址表對(duì)應(yīng)位置做+1操作。在需要執(zhí)行信息的時(shí)候?qū)z索所有的地址表,將所有非0的地址輸出到文件中,達(dá)到記錄指令流的效果。
?
(3)目標(biāo)碼文件分析
在反匯編文件中會(huì)展示目標(biāo)碼中所有的指令信息,包括指令地址、指令操作數(shù)、指令名稱等信息,通過(guò)處理該反匯編文件就可以獲取統(tǒng)計(jì)目標(biāo)碼覆蓋率所需的信息。
?
經(jīng)過(guò)調(diào)研發(fā)現(xiàn)反匯編文件的格式都是固定的,都基本滿足如下格式:
?
解析反匯編文件獲取所有的函數(shù)指令地址信息。解析過(guò)程中還需要獲取跳轉(zhuǎn)指令信息,跳轉(zhuǎn)信息獲取需要獲取三個(gè)地址,跳轉(zhuǎn)指令的地址,來(lái)確定這個(gè)跳轉(zhuǎn)指令是否被執(zhí)行,跳轉(zhuǎn)的地址,來(lái)確定是否進(jìn)入True分支,跳轉(zhuǎn)指令的下一條地址,來(lái)確定是否執(zhí)行False分支。
每種架構(gòu)的指令格式都不盡相同所以需要單獨(dú)處理。
(4)源代碼文件分析
在反匯編時(shí),加入-l參數(shù)可以在反匯編信息中加入源代碼行號(hào)信息,如下圖:
?
經(jīng)調(diào)研發(fā)現(xiàn)反匯編信息中,行號(hào)信息與指令信息對(duì)應(yīng)關(guān)系是固定的,都基本滿足如下格式:
?
處理反匯編文件信息,提取文件行號(hào)與指令地址對(duì)應(yīng)信息,計(jì)算時(shí)如行號(hào)的某一條指令被執(zhí)行那么對(duì)應(yīng)源代碼的這一行也就被執(zhí)行了,但是在反匯編信息中只有產(chǎn)生指令操作的源代碼才被認(rèn)為是有效行,所以本項(xiàng)目中也只統(tǒng)計(jì)產(chǎn)生指令操作的有效行,進(jìn)行各種計(jì)算。
源代碼的分支信息需要通過(guò)分析源代碼文件獲得準(zhǔn)確的分支信息,本項(xiàng)目中采用clang工具提取源代碼文件的抽象語(yǔ)法樹(shù),通過(guò)抽象語(yǔ)法樹(shù)獲取源代碼的分支信息。獲取到抽象語(yǔ)法樹(shù)后提取語(yǔ)法數(shù)中關(guān)于for、if...else、while、switch...case...default等代碼塊的行號(hào)。
其中for、while的分支計(jì)算方法為如果執(zhí)行了該分支起始行不管有沒(méi)有執(zhí)行分支塊內(nèi)代碼也會(huì)認(rèn)為執(zhí)行該分支的False分支,如果執(zhí)行了分支塊內(nèi)代碼那也就會(huì)認(rèn)為執(zhí)行了該分支的True分支。
其中if分支有多種情況如下:
情況一:
if(xxxxxx){xxxxxxx }?
情況二:
if(xxxxxx){xxxxxxx }else{xxxxxxx }?
情況三:
if(xxxxxx){xxxxxxx }else if{xxxxxxx }else{xxxxxxx }?
在計(jì)算時(shí)遇到情況一,如果執(zhí)行到了分支起始行不管有沒(méi)有執(zhí)行分支塊內(nèi)代碼也會(huì)認(rèn)為執(zhí)行該分支的False分支,如果執(zhí)行了分支塊內(nèi)代碼那也就會(huì)也會(huì)任務(wù)執(zhí)行了該分支的True分支。遇到了情況二,如果執(zhí)行了true分支內(nèi)代碼行則認(rèn)為執(zhí)行了true分支,如果執(zhí)行了false分支內(nèi)代碼行則認(rèn)為執(zhí)行了false分支。遇到情況三,會(huì)將代碼分成兩個(gè)分支對(duì),第一個(gè)分支對(duì):if下代碼塊為true分支,else if下代碼塊為flase分支,第二個(gè)分支對(duì):else if下代碼塊為true分支,else下代碼塊為false分支,如果有更多的else if 分析方法一致。
其中switch...case...default的計(jì)算方法為有多少個(gè)case、default就有多少個(gè)分支。
(5)結(jié)果計(jì)算
獲取所需信息后,就可以通過(guò)公式計(jì)算所需覆蓋率結(jié)果。
目標(biāo)碼總語(yǔ)句覆蓋率:
?
?
目標(biāo)碼總分支覆蓋率:
?
目標(biāo)碼函數(shù)語(yǔ)句覆蓋率:
?
目標(biāo)碼單個(gè)函數(shù)分支覆蓋率:
?
源代碼總語(yǔ)句覆蓋率:
?
源代碼總分支覆蓋率:
?
源代碼函數(shù)語(yǔ)句覆蓋率:
?
源代碼單個(gè)函數(shù)分支覆蓋率:
?
3.2 多架構(gòu)嵌入式軟件目標(biāo)碼分析技術(shù)
每種架構(gòu)的嵌入式軟件目標(biāo)碼反匯編格式整體結(jié)構(gòu)基本一致,但不同架構(gòu)的指令格式都不盡相同,都有各自的特點(diǎn),如果只需要函數(shù)指令PC地址信息則不需要繼續(xù)分析,但是我們還需要統(tǒng)計(jì)函數(shù)中的分支覆蓋率情況。每種架構(gòu)的分支指令不同,格式上也不盡相同,針對(duì)不同架構(gòu)都需要構(gòu)建對(duì)應(yīng)的指令分析方式。
不同架構(gòu)的跳轉(zhuǎn)指令如下表:
| 架構(gòu) | 跳轉(zhuǎn)指令 |
| SPARC | ba,bcc,bcs,be,bg,bge,bgu,ble,bleu,bn,bne,bneg,bpos,bbc,bvs,fble,fbne,fbule,fbuge |
| MIPS | bnez,beq,bne,beqz,bteqz,btnez |
| TIC6x | bnop,b |
| TIC28x | sb,sbf |
| TIC55x | BCC |
| POWERPC | bgt,bne,ble,beq,bge,blt |
| ARM | beq,bgt,bls,bhi,bcc,bcs,ble,bne,bge,blt |
通過(guò)調(diào)研總結(jié)發(fā)現(xiàn)如下規(guī)律:
SPARC架構(gòu)跳轉(zhuǎn)指令格式:
be ?40101b9c <_longjmp+0x54>
be,a ??40101ba8 <_longjmp+0x60>
MIPS架構(gòu)跳轉(zhuǎn)指令格式:
bnez ???v0,bf001990 <myprintf+0xa68>
beq ????a0,a3,bf0018c8 <myprintf+0x9a0>
TIC6x架構(gòu)跳轉(zhuǎn)指令格式:
[b0] b .S1 10800a28 <$C$L4>
[!b0] b .S1 10802220 <__c6xabi_llshl>
|| [!b0] b .S1 10802220 <__c6xabi_llshl>
TIC28x架構(gòu)跳轉(zhuǎn)指令格式:
sb ??????????13, geq
sb ??????????fffffff2, neq
PPC架構(gòu)跳轉(zhuǎn)指令格式:
blt- ???10550c <ipnet_configure+0x1f8>
beq- ???cr7,1055b0 <ipnet_string+0x68>
ARM架構(gòu)跳轉(zhuǎn)指令格式:
beq ????12a68 <strlen+0x24>
bcs ????12b64 <__default_signal_handler+0x8c>
TIC55x架構(gòu)跳轉(zhuǎn)指令格式:
BCC __cmpd,AC2>=#0
BCC #0x0024b0,!TC1
根據(jù)以上指令格式特點(diǎn)均可提取出想要的指令信息。
3.3 數(shù)據(jù)緩存技術(shù)
在仿真驗(yàn)證工具中運(yùn)行的目標(biāo)碼修改都是通過(guò)修改源代碼實(shí)現(xiàn)的,所以在做數(shù)據(jù)緩存時(shí)主要針對(duì)這兩個(gè)地方進(jìn)行監(jiān)控,如果目標(biāo)碼文件或者源代碼文件進(jìn)行了修改那么就要更新相應(yīng)的數(shù)據(jù)文件,如目標(biāo)碼文件修改就要修改反匯編文件,反匯編文件解析數(shù)據(jù),如源碼文件修改就要修改源碼文件所對(duì)應(yīng)的函數(shù)起止行號(hào)信息、分支行號(hào)信息等。
在記錄時(shí)以記錄每個(gè)文件的md5值作為標(biāo)準(zhǔn),如果目標(biāo)碼文件或者源碼文件的md5值與記錄中的不匹配那么就證明文件做了修改,如果中間分析文件的md5值與記錄中的也不匹配那么就證明中間文件被篡改,都需要重新生成相應(yīng)的文件,以保證結(jié)果的正確性。
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的全数字实时仿真平台SkyEye目标码覆盖率关键技术的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python私有成员和保护成员,喜大普奔
- 下一篇: JAVA中增强循环中用线程_在Java中