嵌入式實(shí)時(shí)應(yīng)用的高級(jí)動(dòng)態(tài)代碼分析(ADCA)
C 和C++ 程序語(yǔ)言功能強(qiáng)大,但也容易出現(xiàn)錯(cuò)誤。其中一類(lèi)容易出現(xiàn)的是內(nèi)存訪(fǎng)問(wèn)錯(cuò)誤,例如緩沖區(qū)溢出、內(nèi)存泄漏等,其后果也可能是災(zāi)難性的。領(lǐng)先的調(diào)試器供應(yīng)商Lauterbach 希望通過(guò)一項(xiàng)名為高級(jí)動(dòng)態(tài)代碼分析(Advanced Dynamic Code Analysis ,簡(jiǎn)稱(chēng)ADCA)的新技術(shù)來(lái)幫助嵌入式開(kāi)發(fā)人員避免這類(lèi)錯(cuò)誤。
本文引用地址:http://m.butianyuan.cn/article/202309/450588.htm1 引言
軟件錯(cuò)誤的代價(jià)可能是巨大的,甚至具有災(zāi)難性后果。例如,1996 年歐洲航天局(ESA)的阿麗亞娜5 號(hào)火箭在飛行39 秒后爆炸,造成超過(guò)3.7 億美元的損失[1]。事故原因是內(nèi)部慣性參考系統(tǒng)(SRI)軟件異常,由于執(zhí)行從64 位浮點(diǎn)數(shù)到16 位有符號(hào)整數(shù)值的數(shù)據(jù)轉(zhuǎn)換時(shí),浮點(diǎn)數(shù)的值超出了16 位有符號(hào)整數(shù)所能表示的范圍,導(dǎo)致操作數(shù)錯(cuò)誤。而數(shù)據(jù)轉(zhuǎn)換指令(在A(yíng)da 代碼中)也沒(méi)有保護(hù)機(jī)制以防止操作數(shù)錯(cuò)誤。
錯(cuò)誤發(fā)生在控制捆綁式慣性平臺(tái)對(duì)準(zhǔn)的軟件部分。操作數(shù)錯(cuò)誤是由于內(nèi)部對(duì)準(zhǔn)函數(shù)結(jié)果(稱(chēng)為BH(水平偏差))的值太高引起的,該值與平臺(tái)感知的水平速度有關(guān)。雖然阿麗亞娜5 號(hào)使用的SRI 設(shè)計(jì)與阿麗亞娜4號(hào)幾乎相同,但由于阿麗亞娜5 號(hào)早期軌跡與阿麗亞娜4 號(hào)不同,導(dǎo)致水平速度值顯著增加,使BH 值比預(yù)期高得多。這類(lèi)錯(cuò)誤不僅在火箭這一類(lèi)的項(xiàng)目中可能造成災(zāi)難性后果,在日常嵌入式系統(tǒng)中也可能是危險(xiǎn)的主要來(lái)源。
在1985 年至1987 年間,醫(yī)療行業(yè)發(fā)生了一起嚴(yán)重事故。由于多任務(wù)系統(tǒng)中存在競(jìng)爭(zhēng)條件(Race Conditions),Therac-25 放射治療機(jī)造成了大量輻射過(guò)量,導(dǎo)致三名患者死亡,至少三名其他患者受到嚴(yán)重傷害[2]。操作員原本打算使用低功率光束進(jìn)行治療,但由于沒(méi)有放置擴(kuò)散磁鐵,實(shí)際使用的卻是高功率光束,導(dǎo)致劑量遠(yuǎn)遠(yuǎn)超出預(yù)期。這一問(wèn)題源自代碼庫(kù)中的競(jìng)爭(zhēng)條件(Race Conditions),這種競(jìng)爭(zhēng)條件在前一個(gè)模型Therac-20中就已經(jīng)存在,但被硬件安全控制所阻止。整個(gè)軟件系統(tǒng)由多個(gè)同時(shí)運(yùn)行的進(jìn)程組成,數(shù)據(jù)輸入和鍵盤(pán)處理程序共享一個(gè)變量來(lái)標(biāo)識(shí)數(shù)據(jù)輸入是否完成。在數(shù)據(jù)輸入階段完成后,系統(tǒng)會(huì)進(jìn)入磁鐵設(shè)置階段。但是,如果在這8 秒鐘的磁鐵設(shè)置階段內(nèi),用戶(hù)在數(shù)據(jù)輸入階段使用了特定的編輯序列,由于標(biāo)識(shí)變量的值的影響,設(shè)置無(wú)法應(yīng)用到機(jī)器硬件上。
在汽車(chē)行業(yè),自動(dòng)駕駛汽車(chē)中的軟件錯(cuò)誤也造成了多起死亡事故。例如,在2016 年,一輛汽車(chē)的傳感器系統(tǒng)未能識(shí)別出一輛大型白色18 輪卡車(chē)/ 拖車(chē)正在穿過(guò)高速公路,汽車(chē)以全速駛?cè)肓送宪?chē)的下方[3]。
為了盡可能避免這類(lèi)錯(cuò)誤,自動(dòng)代碼分析工具可以幫助開(kāi)發(fā)人員自動(dòng)檢測(cè)日益復(fù)雜的軟件中的錯(cuò)誤。
2 最危險(xiǎn)的軟件缺陷
2.1 內(nèi)存訪(fǎng)問(wèn)錯(cuò)誤是軟件錯(cuò)誤的主要來(lái)源之一
美國(guó)國(guó)家網(wǎng)絡(luò)安全卓越中心每年都會(huì)發(fā)布常見(jiàn)缺陷列表(CWE?),其中包括《Top 25 最危險(xiǎn)軟件缺陷》(CWE? Top 25)[4]。該清單展示了目前最常見(jiàn)和影響最大的軟件缺陷。
為了創(chuàng)建這份清單,CWE 團(tuán)隊(duì)利用了國(guó)家標(biāo)準(zhǔn)技術(shù)研究所(NIST)國(guó)家漏洞數(shù)據(jù)庫(kù)(NVD)中的常見(jiàn)漏洞和暴露(CVE?)數(shù)據(jù)和與每個(gè)CVE 記錄相關(guān)的常見(jiàn)漏洞評(píng)分系統(tǒng)(CVSS)的分?jǐn)?shù),包括關(guān)注網(wǎng)絡(luò)安全和基礎(chǔ)設(shè)施安全局(CISA)已知被利用漏洞(KEV)目錄中的CVE 記錄。應(yīng)用了一個(gè)公式來(lái)根據(jù)普遍性和嚴(yán)重性對(duì)每個(gè)軟件缺陷進(jìn)行評(píng)分。
用于計(jì)算2022 年Top 25 的數(shù)據(jù)集包含了前兩年內(nèi)共37,899 條CVE 記錄。2022 年,前11 大缺陷中有4個(gè)是與內(nèi)存相關(guān)的錯(cuò)誤( 圖1)。
圖1 2022 CWE? Top 25
2.2 C/C++語(yǔ)言中典型的內(nèi)存訪(fǎng)問(wèn)錯(cuò)誤
在2022 年,前11 種軟件缺陷中有四個(gè)與內(nèi)存訪(fǎng)問(wèn)錯(cuò)誤有關(guān),如圖2 所示。越界錯(cuò)誤位居2022 年CWE?Top 25 清單之首。該錯(cuò)誤類(lèi)型一般有三種變體,但基本問(wèn)題的核心都相同:程序在分配的內(nèi)存區(qū)域外寫(xiě)入或讀取了數(shù)據(jù)。
圖2 三種常見(jiàn)越界示例
當(dāng)數(shù)據(jù)大小超過(guò)所分配的內(nèi)存區(qū)域時(shí),可能會(huì)發(fā)生緩沖區(qū)溢出。這種情況下,數(shù)據(jù)可能被寫(xiě)入或讀取錯(cuò)誤的內(nèi)存位置。此外,當(dāng)程序計(jì)算數(shù)據(jù)大小或位置不正確時(shí)也可能發(fā)生緩沖區(qū)溢出。在我們的示例中,緩沖區(qū)溢出發(fā)生在程序試圖訪(fǎng)問(wèn)數(shù)組中無(wú)效索引的情況下,即索引小于0 或等于或大于數(shù)組長(zhǎng)度。
錯(cuò)誤,每種錯(cuò)誤發(fā)生的頻率都較低,但其影響也同樣嚴(yán)重,主要包括以下幾種。
● 未定義行為:程序的行為沒(méi)有被編程語(yǔ)言規(guī)范所定義。未定義行為的例子包括有符號(hào)整數(shù)溢出、空指針引用、在沒(méi)有序列點(diǎn)的表達(dá)式中多次修改同一個(gè)標(biāo)量以及通過(guò)不同類(lèi)型的指針訪(fǎng)問(wèn)對(duì)象。
● 內(nèi)存泄漏:當(dāng)程序員分配內(nèi)存但忘記使用delete()函數(shù)或delete[] 運(yùn)算符釋放內(nèi)存時(shí),就會(huì)發(fā)生內(nèi)存泄漏。C++ 中最常見(jiàn)的內(nèi)存泄漏是使用錯(cuò)誤的delete 運(yùn)算符。delete 運(yùn)算符應(yīng)用于釋放單個(gè)分配的內(nèi)存空間,而delete [] 運(yùn)算符應(yīng)用于釋放數(shù)據(jù)值數(shù)組。
● 使用后釋放:當(dāng)在釋放內(nèi)存后又引用內(nèi)存時(shí),會(huì)發(fā)生這種錯(cuò)誤。使用先前釋放的內(nèi)存可能會(huì)產(chǎn)生各種不利后果,從有效數(shù)據(jù)損壞到執(zhí)行任意代碼,具體取決于缺陷的實(shí)例和時(shí)序。
● 未初始化內(nèi)存讀?。喝绻麘?yīng)用程序從未被填充初始值的可尋址內(nèi)存中讀取,則會(huì)發(fā)生此錯(cuò)誤。錯(cuò)誤可能是由于初始化順序不正確或多線(xiàn)程應(yīng)用程序中的競(jìng)爭(zhēng)條件引起的。
● 返回后使用棧:如果在聲明函數(shù)返回后訪(fǎng)問(wèn)棧變量?jī)?nèi)存,則會(huì)發(fā)生此錯(cuò)誤。
圖3 列舉了這些錯(cuò)誤類(lèi)型的簡(jiǎn)短代碼示例。
圖3 C/C++代碼中常見(jiàn)內(nèi)存錯(cuò)誤
3 目前可用的自動(dòng)代碼分析工具
為了避免C/C++ 代碼中出現(xiàn)內(nèi)存錯(cuò)誤,已經(jīng)有一些動(dòng)態(tài)代碼分析工具可以幫助檢查,如圖4 中顯示是最著名并長(zhǎng)期被使用的Valgrind 和AddressSanitizer(簡(jiǎn)稱(chēng)ASan)兩個(gè)工具。兩者都支持多種CPU 架構(gòu),并以不同方式對(duì)代碼進(jìn)行檢測(cè)。但是,由于這兩種工具都會(huì)導(dǎo)致性能降低和內(nèi)存損耗,因此它們?cè)?a class="contentlabel" href="http://m.butianyuan.cn/news/listbylabel/label/嵌入式實(shí)時(shí)應(yīng)用">嵌入式實(shí)時(shí)應(yīng)用中的使用受到極大的限制。
圖4 兩款常用工具比較
3.1 Valgrind
Valgrind本質(zhì)上是一種使用即時(shí)編譯技術(shù)的虛擬機(jī),包括動(dòng)態(tài)重新編譯[5]。它首先將程序轉(zhuǎn)換為一種臨時(shí)、更簡(jiǎn)單的形式,稱(chēng)為中間表示(IR),然后工具可以自由地對(duì)IR 進(jìn)行任何轉(zhuǎn)換,最后Valgrind 將IR 轉(zhuǎn)換成機(jī)器代碼并讓主處理器運(yùn)行它。
Valgrind 附帶了多個(gè)工具, 默認(rèn)且最常用的是Memcheck。Memcheck 在幾乎所有指令周?chē)迦腩~外的檢測(cè)代碼,用于跟蹤數(shù)據(jù)的有效性和可尋址性。此外,Memcheck 用自己的實(shí)現(xiàn)替換了標(biāo)準(zhǔn)C 內(nèi)存分配函數(shù),該實(shí)現(xiàn)還包括在所有分配塊周?chē)O(shè)置內(nèi)存保護(hù)。這個(gè)功能使Memcheck 能夠檢測(cè)到微量偏差錯(cuò)誤。
Memcheck 能夠檢測(cè)并警告的問(wèn)題包括以下幾點(diǎn):
● 使用未初始化的內(nèi)存;
● 在內(nèi)存被釋放后讀寫(xiě);
● 越界訪(fǎng)問(wèn)malloc 分配的內(nèi)存塊;
● 內(nèi)存泄漏。
使用Valgrind 工具的主要代價(jià)是性能的損失。在Memcheck 下運(yùn)行的程序通常比在Valgrind 外運(yùn)行慢20-30 倍,并且使用更多的內(nèi)存(每次分配都會(huì)有一定的內(nèi)存開(kāi)銷(xiāo))。
3.2 ASan
AddressSanitizer(或ASan)是谷歌安全研究人員創(chuàng)建的一種開(kāi)源編程工具,用于識(shí)別C 和C++ 程序中的內(nèi)存訪(fǎng)問(wèn)問(wèn)題[6]。它可以檢測(cè)到內(nèi)存相關(guān)錯(cuò)誤,例如緩沖區(qū)溢出或?qū)铱罩羔槪ㄡ尫藕笫褂茫┑脑L(fǎng)問(wèn)等。AddressSanitizer 的實(shí)現(xiàn)是基于編譯器插樁和直接映射影子內(nèi)存。
為了監(jiān)控內(nèi)存分配并識(shí)別內(nèi)存泄漏,malloc 和free系列函數(shù)被替換,因此每次內(nèi)存分配/ 釋放都會(huì)被工具監(jiān)控。然后,每次讀取或?qū)懭雰?nèi)存訪(fǎng)問(wèn)都會(huì)被編譯為一段代碼,用來(lái)檢查該內(nèi)存地址是否被標(biāo)記為有害。如果是有害的,它將報(bào)告一個(gè)錯(cuò)誤。
通常情況下,應(yīng)用程序的虛擬地址空間被劃分為應(yīng)用程序代碼使用的程序內(nèi)存和存儲(chǔ)有害(不可尋址)內(nèi)存元數(shù)據(jù)內(nèi)存的影子內(nèi)存。 AddressSanitizer 將每8 字節(jié)的應(yīng)用程序內(nèi)存映射到1 字節(jié)的影子內(nèi)存中。如果一個(gè)內(nèi)存地址未被標(biāo)識(shí)有害(即可尋址),則影子內(nèi)存中的標(biāo)志位為0。如果一個(gè)內(nèi)存地址為有害(即不可尋址),則影子內(nèi)存中的標(biāo)志位為1。這樣,AddressSanitizer 就可以識(shí)別哪些內(nèi)存訪(fǎng)問(wèn)是允許的,哪些不允許并報(bào)告錯(cuò)誤。與Valgrind 一樣,您也必須為ASan付出高昂的代價(jià),包括速度損失和內(nèi)存需求。在A(yíng)san 下運(yùn)行的程序通常比在外部運(yùn)行慢2 倍,并且平均使用240%更多的內(nèi)存。
4 適用于嵌入式實(shí)時(shí)系統(tǒng)的Lauterbach跟蹤技術(shù)
鑒于現(xiàn)有工具有時(shí)無(wú)法滿(mǎn)足實(shí)時(shí)系統(tǒng)的需求,那么使用Lauterbach 的跟蹤技術(shù)或者是一種選擇。圖5 顯示了“Lauterbach Trace Pyramid”的功能模塊,頂部是新的ADCA 技術(shù)。ADCA 基于Lauterbach 的上下文跟蹤系統(tǒng)(CTS),而CTS 又基于標(biāo)準(zhǔn)實(shí)時(shí)流跟蹤技術(shù)。
圖5 “Lauterbach Trace Pyramid”架構(gòu)
4.1 實(shí)時(shí)流數(shù)據(jù)跟蹤Real Time Flow Trace
不斷提高的集成密度和價(jià)格壓力導(dǎo)致許多處理器將CPU 內(nèi)核、緩存、外設(shè)、FLASH 和RAM 內(nèi)存集成在一個(gè)封裝中(SoC),在許多情況下甚至不再具有外部存儲(chǔ)器接口。除了調(diào)試接口外,很多芯片廠(chǎng)商還在芯片上實(shí)現(xiàn)了具有特殊功能的跟蹤接口。這使得程序和數(shù)據(jù)以壓縮形式可以輸出到芯片外部(圖6),這種方法稱(chēng)為流跟蹤方法。
跟蹤總線(xiàn)鏈接到跟蹤接口,通過(guò)該總線(xiàn)以壓縮形式傳輸程序流和(或)數(shù)據(jù)訪(fǎng)問(wèn)信息。地址總線(xiàn)/ 數(shù)據(jù)總線(xiàn)的信息在CPU 核心處也可以直接輸出。這意味著也可以記錄對(duì)芯片內(nèi)部FLASH或RAM內(nèi)存(特別是緩存)的訪(fǎng)問(wèn)。
只有少數(shù)跟蹤接口支持特定的開(kāi)/ 關(guān)切換或定義地址窗口,以控制生成跟蹤數(shù)據(jù)。因此唯一的解決方案是使用具有大型跟蹤內(nèi)存的跟蹤工具,其中所有跟蹤數(shù)據(jù)都未經(jīng)過(guò)濾地被記錄起來(lái)。通過(guò)幾秒鐘的錄制時(shí)間,很可能可以在錄制數(shù)據(jù)中找到所尋求的錯(cuò)誤。此外,多任務(wù)程序運(yùn)行的跟蹤數(shù)據(jù)也可用于運(yùn)行時(shí)統(tǒng)計(jì)分析和/ 或代碼覆蓋率分析。
這種跟蹤技術(shù)唯一的缺點(diǎn)是帶寬問(wèn)題,即如果芯片內(nèi)部生成的跟蹤數(shù)據(jù)比通過(guò)跟蹤接口傳輸?shù)母?,就?huì)出數(shù)據(jù)丟失的情況。芯片制造商一般用FIFO 緩沖區(qū)和減少跟蹤數(shù)據(jù)來(lái)解決這個(gè)問(wèn)題。
實(shí)時(shí)流跟蹤雖然不是特別高尖端學(xué)科,但是,Lauterbach 的跟蹤工具提供了業(yè)界最高的數(shù)據(jù)帶寬和最豐富的數(shù)據(jù)分析功能。
圖6 流跟蹤的通用配置
4.2 TRACE32上下文跟蹤系統(tǒng)(CTS)
僅依靠流跟蹤數(shù)據(jù)可能需要花費(fèi)大量時(shí)間分析跟蹤數(shù)據(jù),以找出哪些指令、數(shù)據(jù)或系統(tǒng)狀態(tài)導(dǎo)致目標(biāo)系統(tǒng)出現(xiàn)故障。
Lauterbach 的基于跟蹤的調(diào)試- 簡(jiǎn)稱(chēng)CTS- 允許用戶(hù)根據(jù)跟蹤緩沖區(qū)中采樣的跟蹤數(shù)據(jù)重構(gòu)選定點(diǎn)的目標(biāo)系統(tǒng)狀態(tài)(圖7)。并且從這個(gè)選定點(diǎn)開(kāi)始,可以重復(fù)在TRACE32 PowerView GUI 中調(diào)試實(shí)時(shí)記錄在跟蹤存儲(chǔ)器中的程序步驟。執(zhí)行全功能跟蹤調(diào)試的前提條件是將程序和數(shù)據(jù)流完整記錄到跟蹤緩沖區(qū),直到程序執(zhí)行停止。
圖7 Context Tracking System (CTS)功能
使能上下文跟蹤系統(tǒng)(CTS)功能后,可以選擇一個(gè)記錄點(diǎn),在指令集模擬器(SIM) 中為其重構(gòu)目標(biāo)系統(tǒng)狀態(tài)。程序計(jì)數(shù)器(PC) 自動(dòng)設(shè)置在源程序中對(duì)應(yīng)的位置,即該記錄點(diǎn)所跟蹤數(shù)據(jù)的地址。
現(xiàn)在CTS 也已經(jīng)支持所有調(diào)試命令,例如Step、Step Over Call、Go、Return 等。 CPU 指令按照它們?cè)诟櫞鎯?chǔ)器中記錄的順序進(jìn)行處理。調(diào)試功能也實(shí)現(xiàn)了進(jìn)一步擴(kuò)展,甚至可支持程序向后步進(jìn)。
由于指令集模擬器(SIM)支持單個(gè)指令的執(zhí)行,因此也能夠跟蹤變量、內(nèi)存和寄存器的變化等。甚至T32 SW 還可以自動(dòng)修復(fù)由于跟蹤端口帶寬限制,所產(chǎn)生跟蹤數(shù)據(jù)遺漏而導(dǎo)致的代碼丟失。如果只采樣讀操作以防止跟蹤端口過(guò)載,則CTS 也可以重建所有寫(xiě)操作。
此外,TRACE32? 也可以使用CTS 技術(shù)支持緩存(Cache)狀態(tài)/ 使用率分析等,該技術(shù)也是基于跟蹤記錄中捕獲的程序跟蹤數(shù)據(jù)。如果設(shè)置了MMU 架構(gòu),則緩存分析將考慮對(duì)緩存控制寄存器的所有操作:包括緩存刷新、緩存的開(kāi)啟和關(guān)閉以及緩存鎖定等。
總之,Lauterbach 的CTS 可以大大簡(jiǎn)化調(diào)試,特別是對(duì)于僅靠停止調(diào)試模式往往不夠的實(shí)時(shí)應(yīng)用程序。
4.3 TRACE32 高級(jí)動(dòng)態(tài)代碼分析 (Advanced Dynamic Code Analysis ,ADCA)
ADCA 是一種先進(jìn)的CTS 模式,用于探索和修復(fù)由不同類(lèi)型的錯(cuò)誤觸發(fā)的內(nèi)存訪(fǎng)問(wèn)錯(cuò)誤。它在啟動(dòng)代碼之后運(yùn)行,捕獲有效的初始內(nèi)存和寄存器狀態(tài),堆棧和數(shù)據(jù)等。
ADCA 需要完整的程序跟蹤流和足夠的數(shù)據(jù)來(lái)重建所有指針以及從啟動(dòng)代碼的完整跟蹤數(shù)據(jù)。該工具還依賴(lài)于編譯器提供的正確和完整的調(diào)試信息,并需要理解編譯器生成和優(yōu)化的結(jié)構(gòu)。此外,它還需要理解特殊代碼,如中斷和RTOS 任務(wù)切換等。
ADCA 的核心功能是將靜態(tài)和動(dòng)態(tài)標(biāo)簽分配給所有數(shù)據(jù)和內(nèi)存地址。標(biāo)簽是不可見(jiàn)的元信息,由調(diào)試器支持。根據(jù)鑰匙鎖原理檢測(cè)內(nèi)存違規(guī):具有某個(gè)標(biāo)簽的數(shù)據(jù)只能訪(fǎng)問(wèn)與相同標(biāo)簽關(guān)聯(lián)的內(nèi)存地址(圖8)。
圖8 一對(duì)一鑰匙鎖校驗(yàn)機(jī)制
運(yùn)行程序并記錄跟蹤數(shù)據(jù)后,您可以運(yùn)行ADCA功能并結(jié)合TRACE32?PowerView 軟件的其他相關(guān)窗口的信息,識(shí)別相關(guān)錯(cuò)誤(圖9)。
圖9 TRACE32 PowerView相關(guān)窗口
Lauterbach 的ADCA 報(bào)告顯示了所有潛在內(nèi)存訪(fǎng)問(wèn)錯(cuò)誤的總結(jié)( 圖10)。下面將討論報(bào)告中的一個(gè)具體示例: 訪(fǎng)問(wèn)名為“check_array1”的數(shù)組以及訪(fǎng)問(wèn)沖突的內(nèi)存地址(0x418f5c) 時(shí)失敗。開(kāi)發(fā)人員可以使用這些信息來(lái)分析代碼,并通過(guò)使用TRACE32?PowerView GUI中顯示的附加信息來(lái)修復(fù)錯(cuò)誤。
圖10 TRACE32? ACDA 自動(dòng)檢測(cè)內(nèi)存錯(cuò)誤
從圖9 所示的可能性中,第一個(gè)可能的TRACE32?PowerView視圖應(yīng)該是存儲(chǔ)器顯示( 圖11)。在顯示器的左側(cè),可以觀(guān)察到地址418F5C 的標(biāo)簽變化。結(jié)果很明顯,與數(shù)組“check_array1”( 標(biāo)簽28A) 相關(guān)的最新有效內(nèi)存地址是418F5B。
圖11 TRACE32? ADCA 內(nèi)存視圖
在內(nèi)存顯示的中間部分可以觀(guān)察到,“check_array1”的最高有效索引( 與內(nèi)存地址418F58 到418F5B 和標(biāo)簽28A 相關(guān)聯(lián)) 是“9”。
正如稍后將看到的,這些信息對(duì)于錯(cuò)誤檢測(cè)很有價(jià)值,但當(dāng)然還不足以修復(fù)錯(cuò)誤。
接下來(lái)要探索的是寄存器顯示(如圖12)。顯然,寄存器R1 與標(biāo)簽28A 相關(guān)聯(lián),該標(biāo)簽屬于數(shù)組“check_array1”。不幸的是,R1 指向內(nèi)存地址418F5C,該地址位于“check_array1”的有效地址空間之外。此時(shí),錯(cuò)誤的原因已經(jīng)接近被發(fā)現(xiàn),只需要找出源代碼窗口即可(如圖13)。
圖12 TRACE32? ADCA寄存器視圖
根據(jù)寄存器顯示中的信息(如圖12),可以輕松確定寄存器R1 包含Lauterbach 的ADCA 在開(kāi)始時(shí)探索到的對(duì)“check_array1 [i]”進(jìn)行寫(xiě)訪(fǎng)問(wèn)的(無(wú)效)內(nèi)存地址。根據(jù)內(nèi)存顯示中的信息,這種無(wú)效訪(fǎng)問(wèn)的原因是顯而易見(jiàn)的:索引變量“i”從0 增加到10,這導(dǎo)致最后一個(gè)循環(huán)通過(guò)“check_array1 [10]”發(fā)生內(nèi)存訪(fǎng)問(wèn)違規(guī)。要修復(fù)錯(cuò)誤,您只需將代碼從“i<11”更改為“i <10”即可。
圖13 TRACE32? ADCA源碼視圖
盡管目前已經(jīng)有一些成熟的代碼分析工具,但它們卻都不適用于實(shí)時(shí)的嵌入式軟件應(yīng)用。而Lauterbach 高級(jí)動(dòng)態(tài)代碼分析恰恰滿(mǎn)足了嵌入式開(kāi)發(fā)人員對(duì)于實(shí)時(shí)性的要求和檢測(cè)C / C++ 中相關(guān)的潛在內(nèi)存訪(fǎng)問(wèn)錯(cuò)誤的需求。ADCA 是識(shí)別這些難以發(fā)現(xiàn)和復(fù)現(xiàn)的錯(cuò)誤的重大進(jìn)步,也可支持多核架構(gòu)。當(dāng)然也有一些限制。比如某些特殊的結(jié)構(gòu)和錯(cuò)誤類(lèi)型無(wú)法檢測(cè)。但是,這些類(lèi)型的錯(cuò)誤通常都會(huì)被編譯器檢測(cè)出來(lái)。特殊的代碼結(jié)構(gòu)可能需要額外的設(shè)置來(lái)提供分析信息。
Lauterbach ADCA 技術(shù)將在2023 年的軟件版本中作為T(mén)RACE32?PowerView 軟件更新的一部分對(duì)勞特巴赫客戶(hù)免費(fèi)提供。ADCA 也不會(huì)作為單獨(dú)產(chǎn)品出售,因此也無(wú)法用作第三方跟蹤工具的附加組件。希望這個(gè)功能為您的軟件開(kāi)發(fā)提供更多幫助。
參考文獻(xiàn):
[1] https://www.bugsnag.com/blog/bug-day-ariane-5-disaster, Retrieved 12 Feb 2023.
[2] https://pvs-studio.com/en/blog/posts/0438/, Retrieved12 Feb 2023.
[3] https://www.businessinsider.com/details-aboutthe-fatal-tesla-autopilot-accident-released-2017-6,Retrieved 12 Feb 2023.
[4] https://cwe.mitre.org/top25/archive/2022/2022_cwe_top25.html, Retrieved 12 Feb 2023.
[5] https://valgrind.org/docs/manual/mc-manual.html,Retrieved 12 Feb 2023.
[6] https://clang.llvm.org/docs/AddressSanitizer.html,Retrieved 12 Feb 2023.
作者簡(jiǎn)介:
Lauterbach GmbH公司的所有者之一。自1982年加入勞特巴赫以來(lái),一直在TRACE32調(diào)試器產(chǎn)品的開(kāi)發(fā)中處于核心位置,他對(duì)復(fù)雜的軟硬件系統(tǒng)研發(fā)經(jīng)驗(yàn)豐富。
(本文來(lái)源于EEPW 2023年9月期)
評(píng)論