基于ELF的嵌入式軟件源碼級(jí)交叉調(diào)試技術(shù)
2、程序頭表與段
程序頭表中有多個(gè)表項(xiàng),每個(gè)表項(xiàng)是一個(gè)程序段的信息,固定長(zhǎng)度為32個(gè)字節(jié),包含8個(gè)值,包括段在文件中的位置,段在內(nèi)存中的起始虛擬地址,段的長(zhǎng)度及其它屬性等。調(diào)試器根據(jù)程序頭表中的信息來確定需要下載到目標(biāo)機(jī)上的目標(biāo)文件內(nèi)容(指令與數(shù)據(jù))及其在目標(biāo)機(jī)中的內(nèi)存地址。
3、節(jié)頭表與節(jié)
節(jié)頭表中也有多個(gè)表項(xiàng),每個(gè)表項(xiàng)是一個(gè)節(jié)的信息,固定長(zhǎng)度為40個(gè)字節(jié),包含10個(gè)值,包括節(jié)名、節(jié)的類型、該節(jié)在文件中的位置、該節(jié)在內(nèi)存中的起始地址(如果該節(jié)出現(xiàn)在內(nèi)存映象中)、節(jié)的長(zhǎng)度等信息。某些節(jié)是程序段的組成部分,如包含程序二進(jìn)制指令代碼的正文節(jié).text和數(shù)據(jù)節(jié).rodata,.hash等,某些節(jié)不作為段的組成部分,只提供其它的額外信息。為源碼調(diào)試服務(wù)的有 .debug,.line,.symtab,.debug_ pubname,.debug_range等節(jié),其中.debug, .line節(jié)包含了源碼調(diào)試信息的基本內(nèi)容。
debug節(jié)中有多種類型的記錄,可分為幾大類:
編譯模塊信息:包含組成該文件的各個(gè)模塊的源文件名,路徑,及該模塊的代碼地址范圍等。
子程序信息:包含程序名,程序類型,起始終止地址,程序返回結(jié)果存放地址等。
變量信息:包含變量名、變量類型、變量存放地址信息等,變量有多種類型,簡(jiǎn)單變量、結(jié)構(gòu)變量等類型的變量其信息內(nèi)容各有不同。
將.debug節(jié)中各項(xiàng)內(nèi)容的結(jié)構(gòu)關(guān)系抽象為家族關(guān)系。以節(jié)的起始為根,首先是一個(gè)編譯單元的信息,它給出下一個(gè)編譯單元(兄弟關(guān)系)在文件中的相對(duì)位置。緊跟著編譯單元的是該編譯單元中的子程序與公共變量信息(父子關(guān)系),同樣的,編譯單元中頭一個(gè)函數(shù)記錄或變量記錄將給出它的兄弟的位置信息。緊隨該函數(shù)記錄的是該函數(shù)內(nèi)部的子程序與局部變量信息。相鄰層次成員是父子關(guān)系,同一層次上的成員是兄弟關(guān)系,如圖4所示:
.line節(jié)中包含目標(biāo)代碼地址與源代碼行號(hào)之間的對(duì)應(yīng)關(guān)系。對(duì)每個(gè)編譯單元給出其行記錄信息的長(zhǎng)度和目標(biāo)碼的起始基地址,以及該編譯單元中所有的行記錄,每條記錄以固定的格式表示:“該行目標(biāo)碼相對(duì)于基地址的偏移,列號(hào)(保留,暫未使用),行號(hào)”。
綜合上述程序段和節(jié)的內(nèi)容,即可確定源碼與目標(biāo)碼的映射關(guān)系。如給定一個(gè)文件名及行號(hào),確定其目標(biāo)代碼的信息。首先根據(jù)文件名確定其在.debug 節(jié)中的編譯模塊信息,從中可得該文件模塊的起始終止地址;再由其起始地址找到該編譯模塊的行記錄信息在.line節(jié)中的位置,根據(jù)行號(hào)找到行記錄,得到該行目標(biāo)碼的地址范圍;由這些地址信息,可直接從目標(biāo)機(jī)內(nèi)存中取得目標(biāo)代碼,也可結(jié)合程序段信息從目標(biāo)文件的程序段中取得該行所對(duì)應(yīng)的目標(biāo)代碼指令內(nèi)容。調(diào)試器利用地址與指令信息就可以查看、修改、執(zhí)行相應(yīng)目標(biāo)代碼,供用戶進(jìn)行調(diào)試。
4 源碼級(jí)交叉調(diào)試器實(shí)現(xiàn)的技術(shù)要點(diǎn)
在設(shè)計(jì)交叉調(diào)試器JDBG時(shí),首先完成與目標(biāo)文件無關(guān)的部分:連接目標(biāo)機(jī),查看修改目標(biāo)機(jī)寄存器和內(nèi)存;然后實(shí)現(xiàn)與目標(biāo)文件有關(guān)的部分:下載目標(biāo)文件到目標(biāo)機(jī),源碼級(jí)調(diào)試功能,包括斷點(diǎn)控制、執(zhí)行控制、變量觀察等,以下重點(diǎn)討論各項(xiàng)功能的設(shè)計(jì)與實(shí)現(xiàn)。
1、下載目標(biāo)文件
目標(biāo)文件中包含多種類型的內(nèi)容,目標(biāo)程序在目標(biāo)機(jī)上運(yùn)行時(shí)只需要程序的二進(jìn)制指令代碼與相關(guān)數(shù)據(jù),這些內(nèi)容包含在文件中的可執(zhí)行程序段中。下載目標(biāo)文件時(shí)在宿主機(jī)上提取目標(biāo)文件中的代碼與數(shù)據(jù)段,根據(jù)其地址映射關(guān)系利用remote協(xié)議中寫內(nèi)存的功能在目標(biāo)機(jī)上建立程序的遠(yuǎn)程映像。
2、斷點(diǎn)
斷點(diǎn)是調(diào)試器控制程序執(zhí)行的基本手段。各種機(jī)器有其特殊的斷點(diǎn)指令(如X86的int3指令),設(shè)置斷點(diǎn)就是將機(jī)器斷點(diǎn)指令替換所指定程序單元中的指令,使得程序運(yùn)行到斷點(diǎn)指令處時(shí),產(chǎn)生“斷點(diǎn)異?!?,用戶程序不再繼續(xù)執(zhí)行下去,目標(biāo)機(jī)向宿主機(jī)返回?cái)帱c(diǎn)停止信號(hào),由宿主機(jī)調(diào)試器接管對(duì)用戶程序的控制。
斷點(diǎn)分為邏輯斷點(diǎn)與物理斷點(diǎn),兩者是多對(duì)一的關(guān)系。邏輯斷點(diǎn)與源代碼對(duì)應(yīng),提供源級(jí)斷點(diǎn)信息(源文件名+行號(hào)或物理地址等);物理斷點(diǎn)與目標(biāo)碼對(duì)應(yīng),提供斷點(diǎn)的目標(biāo)碼地址及斷點(diǎn)處的指令內(nèi)容。插入一個(gè)斷點(diǎn)即根據(jù)邏輯斷點(diǎn)信息確定物理斷點(diǎn)地址,將該地址對(duì)應(yīng)指令用機(jī)器斷點(diǎn)指令替代;刪除斷點(diǎn)即恢復(fù)斷點(diǎn)指令處預(yù)先保存的原指令,使得程序可繼續(xù)執(zhí)行。
檢查點(diǎn)是一種條件斷點(diǎn),使程序在條件滿足時(shí)停止執(zhí)行。通常條件都涉及表達(dá)式的值變化,利用寫內(nèi)存保護(hù)來檢查表達(dá)式的值是最常用的方法,但這種方法不適用于不具備MMU功能的處理器。某些處理器(如i386)提供了專門的調(diào)試控制寄存器,通過在調(diào)試控制寄存器中設(shè)置相應(yīng)線性地址及中止條件(讀或?qū)?即可中止程序的運(yùn)行。通過查詢方式檢查表達(dá)式的值也是一種可行的方法,其效率相對(duì)較低。當(dāng)檢查點(diǎn)的條件滿足時(shí),檢查點(diǎn)的操作與普通斷點(diǎn)類似。
對(duì)一個(gè)斷點(diǎn)應(yīng)具有基本的插入、刪除、使能、使不能等基本操作功能。在設(shè)計(jì)中采用雙向鏈表結(jié)構(gòu)作為斷點(diǎn)的數(shù)據(jù)結(jié)構(gòu),使得斷點(diǎn)控制更加方便高效。
3、啟動(dòng)程序運(yùn)行
啟動(dòng)程序運(yùn)行首先從目標(biāo)文件的ELF頭中得到應(yīng)用程序的入口,將目標(biāo)機(jī)的PC寄存器置為該入口地址,從入口處開始執(zhí)行程序指令。如果程序中沒有設(shè)置任何斷點(diǎn)或檢查點(diǎn),則程序一直運(yùn)行到結(jié)束;如果程序中有斷點(diǎn),則程序運(yùn)行到第一個(gè)斷點(diǎn)處停止并返回其停止位置。
4、源碼級(jí)單步調(diào)試
源碼級(jí)單步以行為單位,一行源代碼對(duì)應(yīng)多條機(jī)器指令,因此一個(gè)源語句的單步執(zhí)行需要多個(gè)機(jī)器指令的單步執(zhí)行。最簡(jiǎn)單的實(shí)現(xiàn)方法就是從源語句對(duì)應(yīng)目標(biāo)代碼的起始地址開始逐條單步執(zhí)行機(jī)器指令。顯然這種方法效率很低,尤其調(diào)試嵌入式軟件需要大量宿主機(jī)/目標(biāo)機(jī)間的通訊,而且有的處理器自身并不提供機(jī)器單步執(zhí)行指令。因此,更有效的方法是用“內(nèi)部臨時(shí)斷點(diǎn)+連續(xù)執(zhí)行”的方式來實(shí)現(xiàn)。
評(píng)論