郝玉濤 孫建祥 安占新
1.中國載人航天工程辦公室,北京 100071 2.北京航天自動控制研究所,北京 100854
2017年俄羅斯研制的 “聯(lián)盟-2.1B”火箭在東方港基地發(fā)射,由于飛行軟件使用的發(fā)射場坐標參數(shù)是拜科努爾發(fā)射場的數(shù)據(jù),導致火箭未能進入預定軌道,墜落大西洋[1]。由此可見,飛行軟件正確與否關系到運載火箭發(fā)射任務的成敗,確保飛行軟件執(zhí)行程序的正確性是航天型號軟件設計人員致力解決的重要問題之一。
目前,航天控制領域廣泛使用德州儀器公司(Texas Instruments,簡稱TI) DSP(Digital Signal Processors)處理器進行控制計算。軟件設計人員通過集成開發(fā)環(huán)境CCS(Code Composer Studio)或者CC(Code Composer)生成COFF(Common Object File Format,通用對象文件格式)格式的飛行軟件,再通過其配套的轉換工具,生成自舉表(Boot Table)格式的文件,固化在計算機的FLASH中。計算機上電后,通過自帶的bootloader引導程序,自動加載自舉表格式的文件運行[2]。自舉表格式的執(zhí)行程序能夠滿足運載型號部分計算機上電自動引導的需求,但不能滿足型號部分計算機需要通過二次引導程序[3-4]運行的需求。自舉表格式的文件不僅包含DSP執(zhí)行程序,還帶有其它額外信息。二次引導的目標文件(DSP執(zhí)行程序)不允許帶有這些額外信息。
為了滿足通過二次引導程序運行的需求,需要生成二進制格式的DSP執(zhí)行程序。以往,軟件設計人員主要采用2種人工提取方法:(1)通過集成開發(fā)環(huán)境控制仿真器,將COFF格式的目標文件下載到DSP處理器中,再按照MAP文件(用于表示程序、數(shù)據(jù)以及IO空間的映射)中的代碼段以及初始化數(shù)據(jù)段地址,提取相應內(nèi)存中的執(zhí)行程序以及初始化數(shù)據(jù);(2)軟件設計人員人工分析COFF格式的文件,在文件中提取出代碼段以及初始化數(shù)據(jù)段。這兩種人工生成執(zhí)行程序的方法使用設備多,環(huán)境復雜,操作繁瑣,易出錯,可靠性低。
文獻[2]研究了DSP處理器引導功能的軟硬件配置設計以及引導控制程序;文獻[3]研究了基于二次引導程序的在線升級程序的方法;文獻[4]研究了多核DSP的加載方法和流程;文獻[5]研究了COFF文件向自舉表文件的轉換方法以及基于FLASH的自動加載方法;文獻[6]研究了基于外部擴展FLASH存儲器的程序代碼自舉加載方法。目前針對二次引導的目標文件如何可靠提取,沒有相關文獻進行論述。本文提出了基于COFF和自舉表(Boot Table)格式文件的DSP執(zhí)行程序提取器設計方案及實現(xiàn)技術,不僅解決了文獻[2-6]中二次引導的目標文件自動提取問題,提高了生成效率和正確率,而且通過加殼技術[7],在目標文件中增加了DSP執(zhí)行程序的CRC校驗信息,提高了飛行程序使用的可靠性。
本文研究了COFF文件、自舉表文件的格式,提出了基于上述兩種文件提取DSP執(zhí)行程序的算法,介紹了軟件實現(xiàn)技術、功能驗證、性能評估以及在航天重大工程中的應用情況。
通用對象文件格式COFF是一種很流行的對象文件格式,是程序源代碼通過集成開發(fā)環(huán)境進行編譯、鏈接之后,最終產(chǎn)生的一種模塊化的文件格式。這種文件格式引入了“段”的機制,不同的目標文件可以擁有不同數(shù)量以及不同類型的段,為軟件開發(fā)人員提供了一組二進制接口定義,這些接口可以延伸到多種操作環(huán)境,從而減少重新編碼、重新編譯程序的需要。
COFF文件包括文件頭、可選文件頭、段頭信息表、段數(shù)據(jù)、重定位信息、行號入口表、符號表、字符串表[5]。其中段頭信息表、段數(shù)據(jù)、重定位信息、行號入口表對應多個段;文件頭、可選文件頭、段頭信息表、段數(shù)據(jù)與生成執(zhí)行程序密切相關。
文件頭用來保存COFF文件的基本信息,如段頭的數(shù)目、時間戳、符號表位置、屬性標記等,共占用22字節(jié),其中第2、3字節(jié)指明了段頭的數(shù)目。
可選頭在文件頭后面,從COFF文件的0x16偏移處開始,長度為28個字節(jié),用來保存在文件頭中沒有描述到的信息,如執(zhí)行代碼的大小、初始化數(shù)據(jù)的大小、未初始化數(shù)據(jù)的大小、程序入口地址、執(zhí)行代碼的開始地址、初始化數(shù)據(jù)的開始地址等。
從第51字節(jié)開始,為各段段頭信息表,用來描述段信息,每個段都有一個段頭信息表來描述,段的數(shù)目在文件頭中指出。每個段頭信息表共48個字節(jié),內(nèi)容包括段名、段數(shù)據(jù)載入內(nèi)存時的物理地址、段數(shù)據(jù)載入內(nèi)存時的虛擬地址、段數(shù)據(jù)的實際長度、段數(shù)據(jù)在COFF文件中的偏移量、段屬性。第9~12字節(jié)為此段在內(nèi)存中的物理地址;第21~24字節(jié)為此段程序或者數(shù)據(jù)在COFF文件中的偏移地址;第41~44字節(jié)為段屬性。段屬性為0x00000020時,表示此段是執(zhí)行代碼段;為0x00000040時,表示此段是初始化數(shù)據(jù)段;為0x00000080時,表示此段是未初始化的數(shù)據(jù)段。
段數(shù)據(jù)用來保存各個段的數(shù)據(jù),不同類型的段,其數(shù)據(jù)的內(nèi)容和結構也不相同。在目標文件中,這些數(shù)據(jù)都是原始數(shù)據(jù),無特別的格式。
在DSP系統(tǒng)中通常使用FLASH存儲器保存程序,在上電或者復位時,BootLoader引導程序將存儲在FLASH中的程序搬移到DSP片內(nèi)或者片外RAM中,并跳轉到用戶程序入口運行,這個程序搬移過程叫自舉加載。用戶程序與一些必要的引導信息結合在一起,形成特定格式的自舉表,以便BootLoader引導程序在自舉加載過程中識別有效的用戶程序、搬移地址以及程序入口地址。
自舉表可以通過集成開發(fā)環(huán)境提供的工具生成,其過程為:(1)使用hex.exe工具,將集成開發(fā)環(huán)境生成的COFF格式文件轉換成為工具能夠識別的hex文件格式,轉換前需要配置好程序引導地址、程序入口地址;(2)使用hexbin.exe工具,將hex格式文件轉換為自舉表格式文件。
自舉表格式[6]文件包括內(nèi)存寬度、STRB控制寄存器數(shù)值、數(shù)據(jù)塊,其中數(shù)據(jù)塊可以有多個,每個數(shù)據(jù)塊包括數(shù)據(jù)塊的大小、數(shù)據(jù)塊加載的起始地址以及數(shù)據(jù)。文件最后一個字數(shù)值為0,表示文件結束。
COFF文件解析器首先以二進制形式讀入擴展名為.out的COFF文件,分析COFF文件頭,其第2、3字節(jié)指明了段的數(shù)目;根據(jù)段數(shù)目,逐段分析段頭信息表,獲取每段的屬性標識,如果該段屬性為執(zhí)行代碼或者初始化數(shù)據(jù),記錄執(zhí)行代碼段、初始化數(shù)據(jù)段內(nèi)存中的物理地址、COFF文件中的偏移地址以及大小;計算執(zhí)行程序(包含初始化數(shù)據(jù))文件大??;計算執(zhí)行代碼段、初始化數(shù)據(jù)段在執(zhí)行程序文件中的位置,按照線性映射關系將此段數(shù)據(jù)存儲在相應內(nèi)存中。COFF文件解析算法工作流程如圖1所示。
圖1 COFF文件解析算法工作流程
詳細過程如下:
1)采用WIN32提供的內(nèi)存映射文件機制[8],根據(jù)可選頭中執(zhí)行代碼、初始化數(shù)據(jù)段的大小,在內(nèi)存中申請COFF文件相應大小的地址空間區(qū)域,將COFF文件中的數(shù)據(jù)以二進制形式讀入對應的地址空間區(qū)域。解析過程中直接讀取內(nèi)存中相應地址獲取COFF 文件數(shù)據(jù),不再對文件進行IO操作。
2)針對內(nèi)存中的COFF文件數(shù)據(jù),分析其文件頭,確定段數(shù)目:N。
3)逐段分析段頭信息表,如果該段屬性為0x00000020時,記錄此段內(nèi)存中的物理地址MemAddrText_i、大小LenText_i、文件中的偏移地址FileAddrText_i(i=1,2,3,……);如果該段屬性為0x00000040時,記錄此段內(nèi)存中的物理地址MemAddrInitData_j、大小LenInitData_j、文件中的偏移地址FileAddrInitData_j(j=1,2,3,…….)。
4)計算執(zhí)行程序文件大小LenExeFile,并申請相應大小的地址空間區(qū)域,用來與執(zhí)行程序、數(shù)據(jù)文件進行線性映射:
AddrLow=Min(FileAddrText_i,MemAddrInitData_j)(i=1,2,3,……,j=1,2,3,…,Min表示求最小值)。
AddrHigh=Max(FileAddrText_i,MemAddrInitData_j)(i=1,2,3,……,j=1,2,3,…,Max表示求最大值)。
LenExeFile=AddrHigh-AddrLow+LenLast(LenLast為通過Max獲得的起始地址最大的段的長度)。
5) 逐段分析段頭信息表,如果該段屬性為執(zhí)行代碼或者初始化數(shù)據(jù),計算此段數(shù)據(jù)在執(zhí)行程序文件中的位置,按照線性映射關系將此段數(shù)據(jù)存儲在相應內(nèi)存中:MemAddrSec_k(k=1,2,3,……)為執(zhí)行代碼段或者初始化數(shù)據(jù)段內(nèi)存中的物理地址, 執(zhí)行代碼段或者初始化數(shù)據(jù)段在執(zhí)行程序文件中的位置:
ShiftAddrSec_k=MemAddrSec_k-AddrLow(k=1,2,3,……)。
6)完成所有段的分析之后,按照線性映射關系將內(nèi)存中的數(shù)據(jù)存儲在文件中,獲得執(zhí)行程序文件。
自舉表文件解析器首先以二進制形式讀入自舉表文件,逐一分析各數(shù)據(jù)塊,獲取各數(shù)據(jù)塊的大小,據(jù)此計算執(zhí)行程序文件的大小,并申請相應內(nèi)存空間;根據(jù)各數(shù)據(jù)塊的大小、數(shù)據(jù)塊加載的起始地址,計算此段數(shù)據(jù)在執(zhí)行程序文件中的位置,并將數(shù)據(jù)塊的數(shù)據(jù)按照計算的位置存儲在內(nèi)存空間;將內(nèi)存空間中的數(shù)據(jù)最終存儲在執(zhí)行程序文件中。自舉表文件解析算法工作流程如圖2所示。
圖2 自舉表文件解析算法工作流程
詳細過程如下:
1) 讀入自舉表文件,獲取各段數(shù)據(jù)的大小LenSec_i(i=1,2,3,……),計算執(zhí)行程序文件映射內(nèi)存大小∑LenSec_i(i=1,2,3,……),申請相應空間,并清零。
2)重新讀取自舉表文件,跳過內(nèi)存寬度和寄存器數(shù)值,指向第一個數(shù)據(jù)塊的信息頭,針對每一數(shù)據(jù)塊逐一進行3)~6)的處理。
3)判斷自舉表文件當前內(nèi)容是否為0,為0,表示自舉文件結束,否則,表示仍有數(shù)據(jù)塊需要處理。
4)依次獲取本段數(shù)據(jù)塊的大小以及起始地址。
5)計算本段數(shù)據(jù)在執(zhí)行程序文件映射內(nèi)存中的相應位置,并將數(shù)據(jù)存儲在相應位置的內(nèi)存中。
6)如果自舉表文件結束,則將內(nèi)存中的數(shù)據(jù)存儲在執(zhí)行程序文件中。
自舉表文件解析算法也采用WIN32提供的內(nèi)存映射文件機制,其操作過程和方法與COFF文件解析算法相同。
本文以TI公司DSP為例進行說明,將集成開發(fā)環(huán)境CCS或者CC編譯、鏈接生成的COFF文件作為輸入文件,經(jīng)過COFF文件解析器解析,生成執(zhí)行程序;使用集成開發(fā)環(huán)境提供的hex.exe工具以及hexbin.exe工具,由COFF文件生成自舉表格式文件;自舉表格式文件經(jīng)過其解析器解析,生成執(zhí)行程序;為了提高生成執(zhí)行程序的可靠性,對由COFF格式和自舉表格式文件生成的執(zhí)行程序,通過二進制比較器進行逐字節(jié)比對,兩套執(zhí)行程序大小、內(nèi)容完全一致,則認為提取正確;最后通過二進制文件編輯器,使用加殼技術[7],在執(zhí)行程序頭部增加長度和CRC校驗信息,生成帶CRC校驗信息的執(zhí)行程序文件。軟件實現(xiàn)過程如圖3所。
圖3 軟件實現(xiàn)過程
在使用帶CRC校驗信息的執(zhí)行程序文件前,可以根據(jù)長度、CRC校驗碼確認文件的完整性和正確性;使用時,通過脫殼技術[9],刪除CRC校驗信息和文件長度。帶CRC校驗信息的執(zhí)行程序文件結構如圖4所示。
圖4 帶CRC校驗信息的執(zhí)行程序文件結構
0~3字節(jié),存放執(zhí)行程序的長度(以字節(jié)為單位);4~5字節(jié),填充0;6~7字節(jié),存放執(zhí)行程序的16位CRC校驗碼,計算CRC校驗碼的多項式為X16+X15+X2+1;從第8個字節(jié)開始,依次存放執(zhí)行程序。
COFF目標文件包含text段、data段、bss段、const段、cinit段、switch段、stack段、system段、far段、sect指令定義的初始化段、usect指令定義的未初始化段等。這些段的含義如表1所示。其中text段、const段、cinit段、switch段以及sect指令定義的段為初始化段,需要提取到執(zhí)行程序文件。
表1 COFF文件段的組成
在對提取器進行驗證時,測試用例考略了COFF文件的完整性、應用程序工程中鏈接文件定義段的隨機性、提取器軟件防錯處理等情況,共考慮10項內(nèi)容、117個組合情況,設計用例519個。詳細情況如表2所示。
表2 提取器測試內(nèi)容概況
針對使用提取器生成執(zhí)行程序(以下簡稱方式一)、使用集成開發(fā)環(huán)境通過仿真器提取執(zhí)行程序(以下簡稱方式二)、人工分析COFF文件提取執(zhí)行程序,設計人員進行了生成正確率和性能對比分析。
在載人航天工程、探月工程、探火工程的新一代運載火箭型號的分系統(tǒng)綜合試驗、匹配試驗、出廠測試、靶場測試以及發(fā)射任務過程中,隨機選擇了80KByte~300KByte大小的執(zhí)行程序、23位設計人員,初始化段和未初始化段隨機分配,每種狀態(tài)分別使用3種方式生成,每種方式均進行了200次,一次正確率(以往人工生成時,通過多次生成避免生成錯誤)測試結果如表3所示。
表3 一次正確率測試結果
上述測試過程中,記錄三種方式每次均提取正確的時間,隨機選擇100次的測試結果進行分析,如表4所示。
表4 性能測試結果
性能評估測試結果表明,通過提取器生成執(zhí)行程序,不僅能夠確保100%正確生成,提高了生成正確率,而且將生成效率提高了約20倍。
以往人工生成DSP執(zhí)行程序的方法使用設備多,環(huán)境復雜,操作繁瑣,易出錯,可靠性低。本文提出了基于COFF和自舉表文件的DSP執(zhí)行程序提取器設計及實現(xiàn)技術,并在載人航天工程、探月工程、探火工程的新一代運載火箭型號中進行了廣泛應用。通過功能驗證、性能評估以及型號應用實踐,結果表明,使用提取器,能夠快速、自動生成帶有CRC校驗信息的DSP執(zhí)行程序,該技術極大提高了DSP執(zhí)行程序的生成效率、正確率、可靠性和使用安全性。