《電子技術(shù)應用》
您所在的位置:首頁 > 嵌入式技術(shù) > 設(shè)計應用 > DWARF格式調(diào)試信息中的數(shù)據(jù)壓縮方法淺析
DWARF格式調(diào)試信息中的數(shù)據(jù)壓縮方法淺析
2014年微型機與應用第24期
林廣棟,黃光紅,耿 銳
(中國電子科技集團公司第三十八研究所,安徽 合肥 230088)
摘要: DWARF格式是一種常用的調(diào)試信息格式。DWARF格式使用多種方法壓縮存儲調(diào)試信息,以減少對可執(zhí)行文件存儲空間的占用。DWARF使用變長數(shù)據(jù)LEB128存儲整型數(shù)。DWARF使用相鄰行調(diào)試信息的變化存儲行號調(diào)試信息,并利用該信息的特點將其進一步壓縮至1 B。DWARF把相同的內(nèi)部格式定義數(shù)據(jù)存儲在單獨的節(jié)區(qū)。DWARF格式定義的這些數(shù)據(jù)壓縮方式值得數(shù)據(jù)壓縮相關(guān)領(lǐng)域?qū)W習和借鑒。
Abstract:
Key words :

  摘  要DWARF格式是一種常用的調(diào)試信息格式。DWARF格式使用多種方法壓縮存儲調(diào)試信息,以減少對可執(zhí)行文件存儲空間的占用。DWARF使用變長數(shù)據(jù)LEB128存儲整型數(shù)。DWARF使用相鄰行調(diào)試信息的變化存儲行號調(diào)試信息,并利用該信息的特點將其進一步壓縮至1 B。DWARF把相同的內(nèi)部格式定義數(shù)據(jù)存儲在單獨的節(jié)區(qū)。DWARF格式定義的這些數(shù)據(jù)壓縮方式值得數(shù)據(jù)壓縮相關(guān)領(lǐng)域?qū)W習和借鑒。

  關(guān)鍵詞: DWARF;調(diào)試信息;數(shù)據(jù)壓縮;LEB128

0 引言

  數(shù)據(jù)壓縮是計算機領(lǐng)域一項廣泛使用的技術(shù),在多媒體、通信、存儲等領(lǐng)域得到廣泛應用[1-3]。數(shù)據(jù)壓縮技術(shù)分為兩大類:無損壓縮和有損壓縮。無損壓縮指壓縮過程不丟失信息的壓縮方法,可以由壓縮數(shù)據(jù)完整恢復壓縮前的數(shù)據(jù)。有損壓縮指壓縮過程丟失部分信息的壓縮方法,一般應用于多媒體領(lǐng)域。常用的無損壓縮方法包括哈夫曼編碼方法、算術(shù)編碼方法、基于字典的壓縮方法(如LZ78算法、LZW算法)等。只要涉及數(shù)據(jù)的存儲、傳輸,都可應用數(shù)據(jù)壓縮方法。

  調(diào)試信息指在可執(zhí)行文件中存儲的關(guān)于源代碼的信息。調(diào)試信息使程序員可以由程序執(zhí)行狀態(tài)追蹤至其源代碼,也使在源代碼的級別對程序進行調(diào)試成為可能。所以,調(diào)試信息是源代碼級調(diào)試功能實現(xiàn)必不可少的重要部分。調(diào)試信息以固定的格式存儲在被調(diào)試可執(zhí)行文件中,常用的調(diào)試信息格式包括STABS、COFF、DWARF等。其中DWARF(Debugging with Attributed Record Formats)格式是最常用的調(diào)試信息格式,它具有表達功能豐富、內(nèi)容緊湊等優(yōu)點[4]。DWARF格式有DWARF1、DWARF2、DWARF3三個版本,最常見的是DWARF2版本,本文介紹的內(nèi)容是基于DWARF2格式的。

  相比于其他調(diào)試信息格式,DWARF格式最大的優(yōu)點就是內(nèi)容高度緊湊。為了減少調(diào)試信息在可執(zhí)行文件中占用的空間,DWARF格式使用各種方法來壓縮調(diào)試信息數(shù)據(jù)。DWARF格式幾乎把調(diào)試信息的可壓縮特點利用到極致,是存儲空間最小的調(diào)試信息格式。由DWARF格式可以完整解析得到所有調(diào)試信息,所以DWARF格式使用的數(shù)據(jù)壓縮方法是一種無損數(shù)據(jù)壓縮方法。

  目前,國內(nèi)幾乎還沒有研究機構(gòu)對DWARF格式調(diào)試信息進行深入研究。本文對DWARF格式中使用的數(shù)據(jù)壓縮方法進行了歸納、總結(jié)、分析,供數(shù)據(jù)壓縮、調(diào)試信息生成、分析領(lǐng)域及相關(guān)領(lǐng)域?qū)W習參考。

1 LEB128數(shù)

  LEB128(Little Endian Base 128)數(shù)是一種變長的存儲整數(shù)的數(shù)據(jù)結(jié)構(gòu),它僅僅存儲整數(shù)的有效位,可以表示任意范圍內(nèi)的有符號或無符號整型數(shù)。LEB128數(shù)的存儲空間與整數(shù)的有效位成正比。若整數(shù)的有效位很少,相對于普通整型數(shù)的存儲方式,LEB128數(shù)可以顯著減小存儲空間。

  一些整數(shù)在大多數(shù)情況下只取很小的值,可以用1 B存儲。但由于該數(shù)可能取很大的值,不能將其存儲空間限制為1 B。若為了存儲個別情況下出現(xiàn)的大值而分配4 B或8 B的空間,大多數(shù)情況下會造成存儲空間的浪費。LEB128的優(yōu)點在于其存儲空間是可變的。若整數(shù)很小,最少1 B即可儲存LEB128數(shù)。若數(shù)字很大,LEB128數(shù)可以用多個字節(jié)表示。LEB128數(shù)既可以編碼小端存儲的數(shù)據(jù),也可以編碼大端存儲的數(shù)據(jù)。

  有符號數(shù)與無符號數(shù)轉(zhuǎn)化為LEB128數(shù)的過程不同。編碼與解析程序必須知道該LEB128數(shù)是有符號數(shù)還是無符號數(shù),否則就會編碼或解析錯誤。

  把一個整數(shù)編碼為LEB128數(shù)的過程抽象描述如下:

 ?。?)把該數(shù)的二進制有效位分割為若干段,每段7 bit;

 ?。?)把這些7 bit的數(shù)放入LEB128的各字節(jié)中,最高一位補1;

  (3)位于有效位最高位的7 bit,最高一位補0,標志數(shù)的結(jié)束。

  若整數(shù)的二進制有效數(shù)位小于7 bit,只需1 B的LEB128數(shù)即可表示。對于調(diào)試信息,大多數(shù)情況下整數(shù)的取值范圍在-128和255之間,可以用1 B的有符號或無符號LEB128數(shù)表示。相對于正常的整數(shù)存儲方式,節(jié)省了3/4的存儲空間。

  圖1、圖2分別為把無符號整數(shù)和有符號整數(shù)編碼為LEB128數(shù)的算法流程圖。

2 行號調(diào)試信息壓縮方法

  2.1 行號調(diào)試信息簡介

  行號調(diào)試信息是最基本的調(diào)試信息,它描述了源代碼中每一行代碼經(jīng)編譯鏈接后定位到的程序地址。它可以幫助調(diào)試系統(tǒng)由程序地址定位到源代碼中的位置,也可以由源代碼中的位置定位到程序地址。插入斷點、單步調(diào)試、暫停等調(diào)試功能都需要行號調(diào)試信息。常規(guī)的調(diào)試信息存儲方式把行號調(diào)試信息存儲為“行號,程序地址”對,每對記錄源代碼中一行代碼的行號和程序地址。例如,STABS格式調(diào)試信息以“行”為單位存儲行號調(diào)試信息,每個“行號,程序地址”對占用相等的存儲空間,擁有相同的格式[5]。該存儲方法的優(yōu)點是簡單易分析,缺點是占用空間較大。一般行號需要使用4 B存儲,程序地址也需要4 B存儲,一個“行號,程序地址”對至少需要8 B存儲。實際上,STABS格式需要15 B來存儲一個“行號,程序地址”對。

  一般的源代碼中,兩相鄰行源代碼的行號差距不會太大,兩行源代碼的程序地址也不會相差太大。如果使用相鄰行的行號差和程序地址差來記錄行號調(diào)試信息,并通過某種方式把這個信息壓縮存儲,將會大大減少行號調(diào)試信息的存儲空間。

  2.2 DWARF格式行號調(diào)試信息簡介

  DWARF格式利用相鄰行的行號調(diào)試信息相差不大的特點,使用與傳統(tǒng)方法完全不同的方式存儲行號調(diào)試信息。DWARF格式的行號調(diào)試信息存儲于.debug_line節(jié)區(qū)。DWARF格式首先定義了一個狀態(tài)機,該狀態(tài)機包含文件名、行號、程序地址等信息。DWARF格式還定義了一些精簡的操作碼,這些操作碼可以改變該狀態(tài)機的狀態(tài),每存儲一個操作碼,就相當于存儲了一個“行號,程序地址”對。

003.jpg

  DWARF格式定義的操作碼分為三類,可以對行號調(diào)試信息狀態(tài)機進行全面的操作。表1分別介紹這三類操作碼。

  三類操作碼中,最常用的是特殊操作碼,其存儲空間固定為1 B,可以改變行號調(diào)試信息狀態(tài)機中的行號和程序地址,并生成一個“行號,程序地址”對調(diào)試信息。

  標準操作碼可以對狀態(tài)機執(zhí)行一些特殊操作碼無法執(zhí)行的命令,如設(shè)置程序地址、改變文件名等。標準操作碼的范圍為從1開始的一段連續(xù)整數(shù)。例如,DWARF2格式預定義了9種標準操作碼,其操作碼編號分別為1、2、3…8、9。調(diào)試信息生成程序可以自定義標準操作碼。

  擴展操作碼用來執(zhí)行一些標準操作碼也無法描述的命令。

  2.3 特殊操作碼的數(shù)據(jù)壓縮機制

  特殊操作碼用1 B記錄行號改變量和程序地址改變量,并且還可以由該字節(jié)準確地計算得到行號改變量和程序地址改變量的原值。

  特殊操作碼的計算可以用下式抽象描述:

  特殊操作碼=程序地址改變量×行號改變量范圍+行號改變量(1)

  其中,行號改變量范圍為行號改變量的取值范圍,行號改變量應取大于或等于0并小于行號改變量范圍的值。

  由特殊操作碼計算得到行號改變量和程序地址改變量的過程可以抽象描述為:

  行號改變量=特殊操作碼%行號改變量范圍(2)

  程序地址改變量=特殊操作碼/行號改變量范圍(3)

  由取模算術(shù)運算的特點可知,由一個特殊操作碼可以確定唯一的行號改變量和程序地址改變量,而且這個行號改變量和程序地址改變量就是計算該特殊操作碼的輸入。

  在DWARF格式的實際定義中,根據(jù)行號調(diào)試信息的特點對上述公式進行了修正。行號調(diào)試信息的特點包括:

 ?。?)行號改變量可能是負數(shù)。對于高級語言(如C語言),其一行源代碼產(chǎn)生的程序可能分散在若干個位置,如for、while循環(huán)語句。這樣的一行源代碼會產(chǎn)生若干條行號調(diào)試信息,其中混夾著其他行源代碼的行號調(diào)試信息。所以,相鄰的行號調(diào)試信息的行號改變量可能是負數(shù)。而由取模算術(shù)運算的特點可知,要準確由特殊操作碼解壓縮得到行號調(diào)試信息,行號改變必須為正數(shù)。所以,式(1)中“行號改變量”應改為行號實際改變量與行號改變量最小可能值之差。

 ?。?)程序地址改變量一定是最小指令長度的倍數(shù)。程序段是由指令組成的,所以程序地址改變量實際上是本行源代碼生成的指令長度之和。而指令的長度有可能并不為1,例如,對某些機器,其指令長度只能為4,其程序地址改變量一定是4的倍數(shù)。所以,為了擴大特殊操作碼可描述的程序地址改變范圍,上述公式中的“程序地址改變量”應改為程序地址實際改變量除以最小指令長度。

  (3)特殊操作碼的取值范圍受限制。操作碼的第一個字節(jié)必須可以區(qū)分該操作碼的種類,否則調(diào)試信息解析程序無法判斷第一個字節(jié)是特殊操作碼還是其他兩類操作碼。所以特殊操作碼的取值應大于標準操作碼最大編號,并小于或等于255。例如,若標準操作碼編號的取值范圍為1~9,則特殊操作碼的最小可能值為10。所以,由上述公式計算得到的特殊操作碼應加上特殊操作碼的最小可能值。

  根據(jù)行號調(diào)試信息的以上特點,DWARF2中定義的實際特殊操作碼計算公式如下:

  特殊操作碼=(行號改變量-行號改變量最小值)+(行號改變范圍×程序地址改變量/最小指令長度)+特殊操作碼最小值(4)

  由特殊操作碼得到行號改變量和程序地址改變量的公式如下:

  行號改變量=(特殊操作碼-特殊操作碼最小值)%行號改變范圍+行號改變量最小值(5)

  程序地址改變量=(特殊操作碼-特殊操作碼最小值)/行號改變范圍×最小指令長度(6)

  可見,式(4)、(5)、(6)與式(1)、(2)、(3)本質(zhì)上是一樣的,只是在數(shù)據(jù)壓縮前后進行了一些算術(shù)處理,它們都可以由特殊操作碼準確得到行號調(diào)試信息。若一個行號調(diào)試信息經(jīng)過式(4)計算后超過特殊操作碼的取值范圍,則說明特殊操作碼無法描述該行號調(diào)試信息??梢允褂脴藴什僮鞔a或擴展操作碼來描述特殊操作碼不能描述的行號調(diào)試信息。

  式(4)中的行號改變量最小值、行號改變范圍、最小指令長度、特殊操作碼最小值都可以在解析行號調(diào)試信息之前從.debug_line節(jié)區(qū)獲取。其中“行號改變范圍”并不是一個源文件中行號改變量的實際最大范圍,而是一個適中的可以包含大部分行號改變范圍的值。使用太大的“行號改變范圍”雖然能夠增加特殊操作碼來描述的行號改變量,但是也會減少特殊操作碼可以描述的程序地址改變量。對于大于“行號改變范圍”的行號改變量,可以使用標準操作碼來存儲。

  若式(4)中的“行號改變量最小值”、“行號改變范圍”選取得當,絕大多數(shù)行號信息都可以通過特殊操作碼描述。實際經(jīng)驗表明,一個代碼書寫規(guī)范的C語言文件,80%以上的行號調(diào)試信息都可以通過特殊操作碼來記錄。一個特殊操作碼占用1 B,相比STABS格式,至少可以節(jié)省90%以上的存儲空間。

3 節(jié)點縮略信息

  DWARF格式中,除行號調(diào)試信息外,其他調(diào)試信息主要以節(jié)點的形式存放在.debug_info節(jié)區(qū)中。節(jié)點可以描述源文件、函數(shù)、變量、類型等調(diào)試信息。調(diào)試信息節(jié)點之間存在父子節(jié)點或兄弟節(jié)點的關(guān)系。一個源文件的所有調(diào)試信息節(jié)點構(gòu)成一個調(diào)試信息節(jié)點樹,描述源文件本身調(diào)試信息的節(jié)點是這個樹的根節(jié)點。節(jié)點具有各種屬性,調(diào)試信息一般存儲為節(jié)點的屬性值。節(jié)點可以有多種類型,屬性也有多種類型。一種類型的節(jié)點具有的屬性類型是不固定的,由調(diào)試信息生成程序定義。表2為常見的節(jié)點類型與可能的屬性類型。

005.jpg

  同一種屬性可以存儲為不同的格式。節(jié)點屬性的格式也是不固定的,由調(diào)試信息生成程序定義。表3為常見的節(jié)點屬性格式。

006.jpg

  按照常規(guī)的存儲方法,.debug_info中存儲一個節(jié)點的調(diào)試信息時,至少需要存儲如下幾類信息:

 ?。?)節(jié)點類型;

  (2)節(jié)點是否有子節(jié)點;

 ?。?)節(jié)點的所有屬性的類型;

  (4)節(jié)點的各個屬性的格式。

  這些信息稱為節(jié)點的縮略信息。根據(jù)DWARF格式的定義,存儲節(jié)點類型、屬性類型、屬性格式至少各需要1 B。若一個節(jié)點具有N個屬性,至少需要2+2×N個字節(jié)來存儲節(jié)點縮略信息。

  對大多數(shù)程序來說,其多數(shù)調(diào)試信息節(jié)點的縮略信息是相同的。例如,若一個可執(zhí)行文件由若干個源文件編譯而成,則其包含的若干個節(jié)點都是源文件調(diào)試信息節(jié)點。若一個源文件中有若干個函數(shù),則該源文件調(diào)試信息節(jié)點的若干個子節(jié)點都是函數(shù)調(diào)試信息節(jié)點類型。若函數(shù)中包含若干個局部變量,則該函數(shù)調(diào)試信息節(jié)點的若干個子節(jié)點都是變量類型。DWARF格式利用調(diào)試信息的這個特點,把節(jié)點的縮略信息抽取出來,放到.debug_abbrev節(jié)區(qū)中。在.debug_info節(jié)區(qū)中只需要引用節(jié)點的縮略信息,并存儲節(jié)點屬性的值即可。圖3為一個源文件節(jié)點類型在.debug_abbrev節(jié)區(qū)中存儲的縮略信息內(nèi)容示意,圖4為這個節(jié)點的值在.debug_info節(jié)區(qū)中的存儲內(nèi)容示意。

004.jpg

  通過這種方法,可以節(jié)省重復類型節(jié)點縮略信息的存儲空間。例如,若源文件中包括L個變量,一般每個變量調(diào)試信息節(jié)點有5個屬性,這些變量的節(jié)點縮略信息只需存儲一個即可,可以節(jié)省約10×L字節(jié)存儲空間。顯然,編譯生成可執(zhí)行文件的源文件越多、源文件中的代碼量越多,通過這種方法節(jié)省的空間就越多。

4 結(jié)論

  數(shù)據(jù)壓縮技術(shù)是計算機領(lǐng)域廣泛使用的技術(shù)。只要存在數(shù)據(jù)的存儲,就可應用數(shù)據(jù)壓縮技術(shù)。DWARF格式是一種常用的調(diào)試信息格式,它把調(diào)試信息存儲于可執(zhí)行文件中。為了減少調(diào)試信息占用的可執(zhí)行文件存儲空間,DWARF格式使用了各種方法來壓縮數(shù)據(jù)。由于DWARF格式可以完整地還原調(diào)試信息,因此這些數(shù)據(jù)壓縮方法是無損壓縮方法。本文介紹的DWARF格式數(shù)據(jù)壓縮方法對數(shù)據(jù)壓縮領(lǐng)域有重要的借鑒意義,對調(diào)試信息生成、分析領(lǐng)域也有重要的參考價值。

  參考文獻

  [1] 鄭翠芳.幾種常用無損數(shù)據(jù)壓縮算法研究[J].計算機技術(shù)與發(fā)展,2011,21(9):73-76.

  [2] 曾玲,饒志宏.幾種數(shù)據(jù)壓縮算法的比較[J].通信技術(shù),2002(9):12-15.

  [3] 袁玫,袁文.數(shù)據(jù)壓縮技術(shù)及其應用[M].北京:電子工業(yè)出版社,1994.

  [4] Unix International Programming Languages SIG. DWARF debugging information format[S]. UNIX International, 1993.

  [5] MENAPACE J, KINGDON J, MacKenzie D. The “stabs” debug format[S]. Free Software Foundation, 2003.


此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。