掌握RISC-V程式碼庫

作者 : Rafael Taubinger,IAR Systems技術行銷專家

嵌入式產業面臨日趨複雜的挑戰,必須以更快的速度因應軟體錯誤衍生的風險,RISC-V程式碼庫尤其如此…

嵌入式產業面臨日趨複雜的挑戰,必須以更快的速度因應軟體錯誤衍生的風險,這些錯誤除了影響產品品質,還將導致安全問題。RISC-V程式碼庫尤其如此,程式碼經常會重複使用或從其他CPU架構移植,而且預期得到相同的運作效能,但大多數開發者只是開始使用RISC-V架構、新指令集,以及少數的延伸架構(extension)。

談到掌控RISC-V程式碼庫,實際上涉及兩個層面。第一是重複使用程式碼庫,可以沿用在未來的專案。第二點是不良的程式碼品質實際上是一項廣泛蔓延的問題,許多證據顯示不良的編碼方式將衍生許多漏洞。顯然每個開發者與企業都需要改進程式碼品質,讓軟體經得起時間的考驗,意謂軟體沒有缺陷,抑或盡可能接近無缺陷的狀態。

重複使用程式碼

Boehm提出的COCOMO結構成本模型如圖1所示,此模型預測在重複使用程式碼所需的修改作業量,會顯著影響撰寫程式碼的相對成本。X軸是要重複使用程式碼進行修改的比率,而Y軸則代表撰寫全新程式碼的比率。請注意三個程式碼樣本其中的二個,大部分都不需要修改,重複使用程式碼的比率高達50%。重點在於,如果真的想重複使用程式碼,條件是必須具備高品質,而且還得有妥善的設計才能壓低重複使用的成本。

 

圖1:Boehm的COCOMO非線性重複使用方法。

 

著重程式碼品質

程式碼品質至關重要,其理由有幾項:第一,依照開發組織成熟程度的不同,工作時間可能最多有80%的比重會花在除錯作業上。如果能在釋出正式版之前快速隔離各項缺陷,缺陷注入比率就能壓低,意謂能更快達到組織制定的品質標準。不過這也代表程式碼殘存的bug會比較少,比較適合拿來重複使用,日後發現先前未找到bug的機率會比較小。高品質的程式碼更容易維護,因為缺陷數量比較少,如果依循良好的軟體工程原則便更容易延伸,之後推動的後續專案也能更快進行。另外如果有需要,程式也能更容易通過安全認證,這相當於更高的程式碼品質意謂在重複使用時「技術負債」會比較少。

現有的程式編碼標準

目前程式編碼方面已有許多標準,但被廣泛採行的僅有少數。MISRA C是汽車產業軟體可靠性協會制定的C語言開發標準,其目標是促進嵌入式系統的程式碼安全性、可移植性,以及可靠性,尤其是採用ISO C標準所開發的系統。

MISRA C標準的第一版《車載軟體C語言使用指引》於1998年發表,正式名稱為MISRA C:1998。之後於2004年更新,並於2012年加入更多規則。另外,還根據C++ 2003標準制定了MISRA C++ 2008規範。

此外,MITRE的CWE通用缺陷列表亦規範完善的程式編碼標準。mitre.org組織的人員執行一項調查,希望找出開發者意外注入程式碼的缺陷屬於什麼種類。出乎意料的是,所有領域的開發者——包括網頁、app、桌面、或嵌入式系統——都傾向於犯相同種類的錯誤。因此該組織歸納出通用缺陷列表,列出開發者應避開的這些常見疏失。舉例來說,C++程式碼(或甚至C程式碼)配置資源之後沒有釋出。另外則是沒有宣告函數原型(prototyping)就使用函數,這點也是良好編碼策略中一項值得關注的議題。

如果沒有宣告函數原型,在編譯時就不會嚴格檢查型別,產生的程式執行效率會比較差,因為C語言的規則明定若沒有宣告原型,所有引數就會轉換成整數格式。如果MCU沒有浮點運算單元,就會導致進行型別轉換(casting),以及浮點運算作業。正因如此,永遠都應宣告函數原型,然而CWE的主要用意在於找出有風險與不良的程式編碼行為。

SEI CERT C與C++亦定義常見漏洞,這些項目來自實際案例研究,像是檢查浮點數的越界(out-of-bound)狀態,以及確保你沒有覆寫常數。此外還列出程式編碼的風格慣例,讓程式碼更有可讀性讓其他人能夠看懂。

MISRA C 2012的實務範例

業界廣泛採用MISRA C 2012標準,據此確保各種嵌入式應用的程式碼品質。本文剖析一些規則與指引,藉此認識程式編碼標準對程式碼造成的影響。

以Directive 4.6指引為例,規定不允許使用基本資料型別(primitive data type),一開始這項規定看似很奇怪,但瞭解背後的理由後就完全了解理該如此。不同編譯器處理整數等類型資料的方式不盡相同,包括大小長度,以及符號類型的規範都不一致,這也導致審核程式碼的工作相當棘手。如果你是審核者,難免會質疑程式原始作者是否瞭解編譯器會如何解譯程式碼。如果不使用基本資料型別,就會讓程式碼在不同編譯器與架構之間維持不變性(invariant)。

大多時候,開發者會使用uint16_t告知編譯器變數是不帶正負號的16位元數值,因為長度和正負號都在變數類型中明確宣告,並加入到stdint.h。

另一項有意思的指引是rule 13,規定AND或OR邏輯運算元的右側不能有副作用(side-effect)。圖2的程式片斷看似完全正確,實則不然。

 

圖2:MISRA C 2012-rule 13程式碼範例。

 

問題在於左邊表述式必須是偽(false),才會執行右側的表述,只有在這個時候pointer p會是後置遞增(post-incremented)。然而問題是在撰寫程式碼時很容易弄錯這項行為,其他人在審閱、測試、或維護程式碼時都必須瞭解你在寫程式時遵循的條件判斷式。這部分的程式碼加上註解當然有助於其他人瞭解判斷邏輯,但實務上一般很少看到程式會載明詳細的註解。

另一個很好的例子就是rule 14,它規定if或while的陳述句必須加上大括弧(curly braces)。圖3顯示範例程式碼片段。

 

圖3:MISRA C 2012-rule 14程式碼範例。

 

這很難判斷z = 1語句是否打算成為else區塊的一部分,這是因為這裡的縮排(indented)和前面的陳述式一樣,如果刻意寫成這樣,這裡就會出現一項bug,因為顯然並不依循程式所寫的邏輯走到程式碼區段,這條規則協助避免這類的程式編碼錯誤,這只是MISRA C 200多條規則的一個小範例,讓程式碼更加可靠與可移植,進而使設計案符合未來發展需要。

寫出好程式的捷徑

改進程式碼品質的最快途徑就是使用程式碼分析工具。事實上,如果程式曾執行功能安全認證,就必須執行靜態分析,這類工具除了幫你找出程式碼中最常見的缺陷來源,還能找到開發者往往沒料想到的問題,或在寫程式時沒有考量到的問題。尤其是在套用程式碼產生器(scaffold)的狀況,這類工具真的能幫你開發出更好的程式,因為它們能強制執行相關的編碼標準。

依據所用靜態分析解決方案的品質,在還在開發階段檢查程式碼時,它們就會檢查許多其他潛在問題。為瞭解其運作方式,來看看C-STAT靜態分析工具(內建在IAR Embedded Workbench for RISC-V)的工作狀況。C-STAT延用MISRA C 2004與2012版;MISRA C++ 2008 規則集;MITRE的通用缺陷列表(CWE),以及SEI CERT C。圖4顯示使用這些編碼標準能啟用或強制遵守的規則。

 

圖4:選取標準與規則。

 

這裡還可以打開分類目錄,僅選取我們覺得自己專案適用的規則。此外,還可以針對群組、檔案、函數、或每行程式碼客製化這些選項設定,選取套用的標的有極高粒度(granularity)選擇性。完成工具的設定後,專案(或群組、個別程式檔案)就可進行分析(或多個檔案),在完成分析後,可對每個檔案逐一檢查問題。

圖5顯示偵測到問題CERT-ERR33-C_c屬於CERT C規則界定的問題,這些規則大多解釋相當明確,也可參考使用者指南以及說明檔(F1),如圖6所示。

 

圖5:程式碼分析訊息。

 

圖6:上下文關聯式說明檔。

 

在說明視窗中,可看到問題的完整敘述,這種bug的明確性,以及出現這類bug時問題的嚴重性,以及列出違反的所有編碼標準。最重要的是如圖7所示,可以看到1~3個範例,顯示犯錯的錯誤實例,以及如何修正,藉以透過檢查並讓程式碼更強固,藉此協助你快速消弭靜態分析工具在程式碼中找到的缺陷。

 

圖7:沒通過及通過檢查的程式碼範例。

 

自動化作業流程

確保程式碼品質對於每天在辦公桌工作的開發者而言很重要,另外對於現代與可擴充伺服器中持續性整合/持續性交付(CI/CD)的虛擬機、容器(Docker)、Runners而言更是如此。程式碼分析工具應具備擴充性,透過自動執行任務確保與程式編碼標準的相容性,包括擴充至規模更大的團隊,以及當人員散佈在全球不同地域下依然能遵循這些標準。圖8顯示使用C-STAT靜態分析工具,在Linux-Ubuntu作業系統中使用命令列介面操作。對於許多自動作業流程,跨平台支援屬於標準流程,有助於提升開發團隊的效率。

 

圖8:自動化作業流程。

 

藉由程式碼分析取得助力

靜態分析其中一項主要理論效益就是它不會影響程式運作的系統效能,這是因為在執行分析時根本就不在系統上運作。此外,它也不受測試套件的品質所影響。尋找運作程式碼的錯誤,實際上是和程式在處理特定資料集所涉及的路徑(path)有關係,然而靜態分析工具理論上會檢查程式碼所有可能經過的路徑。

在開發初期或在重複使用程式碼時導入程式碼品質控制機制,藉以讓程式碼符合未來的需求,從而將錯誤造成的影響減至最低,為RISC-V開發者提供已整合的靜態分析工具,以及定義完備的程式編碼標準,能協助他們在開發時找出程式碼中的各種問題,這些錯誤造成的成本將遠低於產品出貨後出問題所導致的損失。

本文同步刊登於《電子工程專輯》雜誌2022年6月號

 

 

 

 

加入我們官方帳號LINE@,最新消息一手掌握!

發表評論