0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ELF文件、鏡像(Image)文件、可執(zhí)行文件、對(duì)象文件詳解

技術(shù)讓夢(mèng)想更偉大 ? 來(lái)源:CSDN技術(shù)社區(qū) ? 2022-12-30 10:24 ? 次閱讀

ELF 文件規(guī)范

ELF(Executable and Linking Format)是一個(gè)二進(jìn)制文件規(guī)范。用于定義不同類型的對(duì)象文件(Object files)中都放了什么東西、以及都以什么樣的格式去放這些東西。

現(xiàn)在流行的二進(jìn)制可執(zhí)行文件格式 (Executable File Format),主要是 Windows 下的 PE(Portable Executable)和 Linux 的 ELF(Executable and Linking Format)可執(zhí)行和鏈接格式)。他們都是 COFF(Common Object File Format)的變種。ARM 體系中采用的也是 ELF 文件格式。

COFF 是在 Unix System V Release 3 時(shí)由 UNIX 系統(tǒng)實(shí)驗(yàn)室(UNIX System Laboratories, USL)首先提出并且使用的文件規(guī)范,后來(lái)微軟公司基于 COFF 格式,制定了 PE 格式標(biāo)準(zhǔn),并將其用于當(dāng)時(shí)的 Windows NT 系統(tǒng)。在 System V Release 4 時(shí),UNIX 系統(tǒng)實(shí)驗(yàn)室在 COFF 的基礎(chǔ)上,開發(fā)和發(fā)布了 ELF 格式,作為應(yīng)用程序二進(jìn)制接口 (Application Binary Interface,ABI)。

此后,工具接口標(biāo)準(zhǔn)委員會(huì)(Tool Interface Standard Committee,TISC)選擇了正在發(fā)展中的 ELF 標(biāo)準(zhǔn)作為工作在 32 位 INTEL 體系上不同操作系統(tǒng)之間可移植的二進(jìn)制文件格式??梢詮倪@里 找到詳細(xì)的標(biāo)準(zhǔn)文檔。如下圖:
6f2c260a-87d6-11ed-bfe3-dac502259ad0.png

TISC 共出過(guò)兩個(gè)版本(v1.1和 v1.2)的標(biāo)準(zhǔn)文檔。兩個(gè)版本內(nèi)容上差不多,但 v1.2 版本重新組織了原本在 v1.1 版本中的內(nèi)容。可讀性更高。兩個(gè)版本的目錄如下所示:

6f400904-87d6-11ed-bfe3-dac502259ad0.png
由于 TISC 的 v1.2 比較老舊,且后續(xù)沒(méi)有再更新,尤其是在 64 位出現(xiàn)之后,原來(lái)的 ELF v1.2 已經(jīng)不再試用,因此,System V 對(duì) ELF v1.2 進(jìn)行了擴(kuò)展,這個(gè)擴(kuò)展就是 System V Application Binary Interface AMD64 Architecture Processor Supplement,實(shí)際了 Unix 系統(tǒng)與 類 Unix 系統(tǒng)都使用 System V 擴(kuò)展的這個(gè)版本。

6f50525a-87d6-11ed-bfe3-dac502259ad0.png

在 ELF 文件規(guī)范中,把系統(tǒng)中采用 ELF 格式的文件(規(guī)范中稱為「對(duì)象文件(Object File)」)歸類為以下三種:

「可重定位文件(Relocatable File ):」 這類文件包含代碼和數(shù)據(jù),可用來(lái)連接成可執(zhí)行文件或共享對(duì)象文件(Object File),靜態(tài)鏈接庫(kù)歸為此類,對(duì)應(yīng)于 Linux 中的 .o ;Windows 的 .obj.

「可執(zhí)行文件(Executable File ):」 這類文件包含了可以直接執(zhí)行的程序,它的代表就是 ELF 可執(zhí)行文件。Linux 下,他們一般沒(méi)有擴(kuò)展名,比如 /bin/bash;Windows 下的 .exe

「共享對(duì)象文件(Object File)(Shared Object File ):」 這種文件包含代碼和數(shù)據(jù),鏈接器可以使用這種文件跟其他可重定位文件的共享對(duì)象文件(Object File)鏈接,產(chǎn)生新的對(duì)象文件(Object File)。對(duì)應(yīng)于Linux 中的 .so,Windows 中的 DLL另外是動(dòng)態(tài)鏈接器可以將幾個(gè)這種共享對(duì)象文件(Object File)與可執(zhí)行文件結(jié)合,作為進(jìn)程鏡像文件來(lái)運(yùn)行。

在 Linux 系統(tǒng)中,還有一類文件,被稱為「核心轉(zhuǎn)儲(chǔ)文件(Core Dump File)」 ,當(dāng)進(jìn)程意外終止,系統(tǒng)可以將該進(jìn)程地址空間的內(nèi)容及終止時(shí)的一些信息轉(zhuǎn)存到核心轉(zhuǎn)儲(chǔ)文件。 對(duì)應(yīng) Linux 下的 core dump。

對(duì)象文件參與程序鏈接(構(gòu)建程序)和程序執(zhí)行(運(yùn)行程序)。 為了方便和高效,對(duì)象文件(Object File)格式提供文件內(nèi)容的并行視圖,反映了這些活動(dòng)的不同需求。 下圖顯示了對(duì)象文件(Object File)的組織。6f826e5c-87d6-11ed-bfe3-dac502259ad0.png
其中,各部分的含義都是規(guī)范定義好的!?
6f9e7444-87d6-11ed-bfe3-dac502259ad0.png

數(shù)據(jù)表示法

??對(duì)象文件(Object File)格式支持具有 8 位字節(jié)和 32 位體系結(jié)構(gòu)的各種處理器。 然而,它旨在可擴(kuò)展到更大(或更?。┑捏w系結(jié)構(gòu)。 因此,對(duì)象文件(Object File)用一種與機(jī)器無(wú)關(guān)的格式表示一些控制數(shù)據(jù),從而可以識(shí)別對(duì)象文件(Object File)并以通用方式解釋它們的內(nèi)容。 目標(biāo)處理器中的剩余數(shù)據(jù)使用目標(biāo)處理器的編碼,而不管創(chuàng)建文件的機(jī)器如何。出于可移植性的原因,ELF 不使用位字段。

Name Size Alignment Purpose
Elf32_Addr 4 4 Unsigned program address
Elf32_Half 2 2 Unsigned medium integer
Elf32_Off 4 4 Unsigned file offset
Elf32_Sword 4 4 Signed large integer
Elf32_Word 4 4 Unsigned large integer
unsigned char 1 1 Unsigned small integer

??對(duì)象文件格式定義的所有數(shù)據(jù)結(jié)構(gòu)都遵循相關(guān)類的自然大小和對(duì)齊準(zhǔn)則。如果需要,數(shù)據(jù)結(jié)構(gòu)包含顯式填充,以確保 4 字節(jié)對(duì)象的 4 字節(jié)對(duì)齊,強(qiáng)制結(jié)構(gòu)大小為 4 的倍數(shù),以此類推。數(shù)據(jù)從文件開始也有適當(dāng)?shù)膶?duì)齊。因此,例如,包含 Elf32 Addr 成員的結(jié)構(gòu)將在文件中的 4 字節(jié)邊界上對(duì)齊。

字符表示法

??ELF 中對(duì)于符號(hào)的字符編碼也有一定的要求。當(dāng) ELF 接口文檔提到字符常量時(shí),例如’/‘或’ n’,它們的數(shù)值應(yīng)遵循 7 位 ASCII 準(zhǔn)則。 對(duì)于先前的字符常量,單字節(jié)值分別為 47 和 10。??根據(jù)字符編碼,在 0 到 127 范圍之外的字符值可以占用一個(gè)或多個(gè)字節(jié)。 應(yīng)用程序可以根據(jù)需要使用不同語(yǔ)言的不同字符集擴(kuò)展來(lái)控制自己的字符集。 盡管 TIS-一致性 不限制字符集,但它們通常應(yīng)遵循一些簡(jiǎn)單的指導(dǎo)原則:

0 到 127 之間的字符值應(yīng)對(duì)應(yīng)于 7 位 ASCII 代碼。 也就是說(shuō),編碼大于 127 的字符集應(yīng)包含 7 位ASCII 碼作為子集。

值大于 127 的多字節(jié)字符編碼應(yīng)僅包含值在 0 到 127 范圍之外的字節(jié)。也就是說(shuō),每個(gè)字符使用多個(gè)字節(jié)的字符集不應(yīng)嵌入類似于 7 位 ASCII 字符的字節(jié)。 一個(gè)多字節(jié),非 ASCII 字符。

多字節(jié)字符應(yīng)該是自我識(shí)別的。 例如,這允許在任何一對(duì)多字節(jié)字符之間插入任何多字節(jié)字符,而不改變字符的解釋。

關(guān)于 ELF 文件規(guī)范這里就不多做詳細(xì)介紹了,感興趣的可以去 Linux 基金會(huì)的官方網(wǎng)站下載規(guī)范來(lái)看看!

ARM ELF 文件格式

??ARM 體系中,所有文件均采用的 ELF 文件格式。我們可以在 ARM 的官網(wǎng)找到 ARM 關(guān)于 ARM ELF 文件格式的說(shuō)明文檔。后文參考部分的下載中是目前可以從 ARM 官網(wǎng)找到的所有和 ARM ELF 相關(guān)的 PDF 文檔。

??目前,我們可以找到的 ARM ELF 相關(guān)的文檔主要有 4 個(gè):《ARM ELF File Format》、《ELF for the ARM? Architecture》、《ARM ELF》以及 ARM 的鏈接器手冊(cè)。其中,《ARM ELF File Format》是比較早期的文檔,針對(duì)于 ARM SDT 時(shí)代的 ELF 文件,有點(diǎn)過(guò)時(shí)了;后者三個(gè)則是最新的介紹文檔,《ELF for the ARM? Architecture》 僅僅是對(duì) ARM ELF 取值的一些特殊說(shuō)明,是在讀者先了解 ELF 文件規(guī)范的基礎(chǔ)上進(jìn)行的說(shuō)明。

??ARM 中的各種源文件(包括匯編文件,C 語(yǔ)言程序及 C++ 程序等)經(jīng)過(guò) ARM 編譯器編譯后生成 ELF 格式的對(duì)象文件(Object File)(.o文件)。這些對(duì)象文件(Object File)和相應(yīng)的 C/C++ 運(yùn)行時(shí)用到的庫(kù)經(jīng)過(guò) ARM 連接器處理后,生成 ELF 格式的鏡像文件(image),這種 ELF 格式的映像文件是一種可執(zhí)行文件,可被寫入嵌入式設(shè)備的 ROM 中。

??在 ARM 體系中,所有的二進(jìn)制文件均被稱為「對(duì)象文件」。其中,鏈接器最終生成的 ELF 格式的可執(zhí)行文件又被稱為「鏡像文件(Image file)」。ARM ELF 鏡像文件或者對(duì)象文件由「輸入節(jié)(Input Sections)」、「輸出節(jié)(Output Sections)」、「域(Regions)」「段(Segments)」 組成,每個(gè)鏈接階段都有不同的鏡像視圖。如下圖所示:
6fc054e2-87d6-11ed-bfe3-dac502259ad0.png

「ELF object file view (linker input):」 ELF 對(duì)象文件視圖由輸入節(jié)組成。 ELF 對(duì)象文件可以是:

一個(gè)可重定位文件,包含適合與其他對(duì)象文件(Object File)鏈接的代碼和數(shù)據(jù),以創(chuàng)建可執(zhí)行文件或共享對(duì)象文件。

包含代碼和數(shù)據(jù)的共享對(duì)象文件。

「Linker view:」 連接器視圖針對(duì)程序地址空間會(huì)有兩個(gè)視圖。并且這兩個(gè)視圖在存在重疊,位置無(wú)關(guān)和可重定位的程序片段(代碼或數(shù)據(jù))時(shí)變得不同:

如果片段與位置無(wú)關(guān)或可重定位,則其執(zhí)行地址在執(zhí)行期間可能會(huì)有所不同。

程序片段的加載地址是鏈接器期望外部代理(例如程序加載器,動(dòng)態(tài)鏈接器或調(diào)試器)從 ELF 文件復(fù)制片段的目標(biāo)地址。 這可能不是片段執(zhí)行的地址。

程序片段的執(zhí)行地址是目標(biāo)地址,其中鏈接器期望片段在參與程序的執(zhí)行時(shí)駐留。

「ELF image file view (linker output):」 ELF 鏡像文件視圖由程序段和輸出節(jié)組成:

RO section.

RW section.

XO section.

ZI section.

一個(gè)加載域?qū)?yīng)于一個(gè)程序段。

一個(gè)執(zhí)行域包含一個(gè)或多個(gè)以下輸出節(jié):

一個(gè)或多個(gè)執(zhí)行域組成一個(gè)加載域。

?When describing a memory view:

The term root region means a region that has the same load and execution addresses. 術(shù)語(yǔ)根區(qū)域是指具有相同加載和執(zhí)行地址的區(qū)域。

Load regions are equivalent to ELF segments. 加載區(qū)域等效于 ELF段。?

輸入節(jié) Input section

??一個(gè)輸入節(jié)就是是輸入對(duì)象文件中的一個(gè)獨(dú)立的部分。 它包含代碼,初始化數(shù)據(jù),或著是描述未初始化或必須在鏡像文件執(zhí)行前設(shè)置為零的內(nèi)存片段。 這些屬性由 RO,RW,XO 和 ZI 等屬性表示。 armlink 使用這些屬性將輸入節(jié)分組為更大的構(gòu)建塊,稱為輸出節(jié)和域。

輸出節(jié) Output section

??一個(gè)輸出節(jié)就是一組輸入節(jié)的組合,它們具有相同的 RO,RW,XO 或 ZI 屬性,并且由鏈接器連續(xù)放置在存儲(chǔ)器中。 輸出節(jié)與組成它的輸入節(jié)具有相同的屬性。 在輸出節(jié)中,輸入節(jié)根據(jù)節(jié)放置規(guī)則進(jìn)行排序。

域 Region

??一個(gè)域最多包含四個(gè)輸出節(jié),具體取決于內(nèi)容和具有不同屬性的節(jié)的數(shù)量。 默認(rèn)情況下,域中的輸出節(jié)根據(jù)其屬性進(jìn)行排序。 首先是 XO 屬性的輸出節(jié),然后是 RO 屬性的輸出節(jié),再然后是 RW 屬性的輸出節(jié),最后是 ZI 屬性的輸出節(jié)。 域通常會(huì)映射到物理存儲(chǔ)設(shè)備,例如 ROM,RAM 或外圍設(shè)備。 您可以使用分散加載文件來(lái)更改輸出節(jié)的順序。

程序段 Program segment

??一個(gè)程序段對(duì)應(yīng)于一個(gè)加載域,并且包含執(zhí)行域。 程序段包含文本和數(shù)據(jù)等信息。

?存在 XO( execute-only)節(jié)時(shí)的注意事項(xiàng)

您可以在同一執(zhí)行域中混合 XO 和 非 XO 節(jié)。 但是,輸出的結(jié)果是一個(gè) RO 節(jié)。

如果輸入文件具有一個(gè)或多個(gè) XO 節(jié),則鏈接器將生成單獨(dú)的 XO ELF 段。 在最終鏡像中,除非使用分散加載文件或 --xo-base 選項(xiàng)另有指定,否則 XO 段緊接在 RO 段之前。?

鏡像的加載視圖和執(zhí)行視圖

??鏡像的域在加載時(shí)放置在系統(tǒng)存儲(chǔ)器映射中。 內(nèi)存中域的位置可能會(huì)在執(zhí)行期間發(fā)生變化。在執(zhí)行鏡像之前,可能必須將鏡像的某些域移動(dòng)到其執(zhí)行地址并創(chuàng)建 ZI 輸出節(jié)。 例如,初始化的 RW 數(shù)據(jù)可能必須從其 ROM 中的加載地址復(fù)制到 RAM 中的執(zhí)行地址。鏡像的內(nèi)存映射具有以下不同視圖:

加載視圖 Load view

根據(jù)鏡像加載到內(nèi)存中時(shí)所處的地址,即鏡像執(zhí)行開始前的位置,描述每個(gè)鏡像的域和節(jié)。

執(zhí)行視圖 Execution view

根據(jù)鏡像執(zhí)行期間所在的地址描述每個(gè)鏡像的域和節(jié)。

下圖顯示了沒(méi)有(XO)節(jié)的鏡像的這些視圖:
7019cde2-87d6-11ed-bfe3-dac502259ad0.png
下圖顯示了具有 XO 節(jié)的鏡像的加載和執(zhí)行視圖:
70302d12-87d6-11ed-bfe3-dac502259ad0.png

Image entry points

??鏡像中的入口點(diǎn)就是鏡像中的一個(gè)位置(地址),該位置(地址)會(huì)被加載到 PC 寄存器。 它是程序執(zhí)行開始的位置。 雖然鏡像中可以有多個(gè)入口點(diǎn),但在鏈接時(shí)只能指定一個(gè)入口點(diǎn)。并非每個(gè) ELF 文件都必須有入口點(diǎn)。 不允許在單個(gè) ELF 文件中存在多個(gè)入口點(diǎn)。

??對(duì)于嵌入式 Cortex-M 核的程序,程序的執(zhí)行是從復(fù)位向量所在的位置(地址)開始執(zhí)行。復(fù)位向量會(huì)被加載到 PC 寄存器中,且復(fù)位向量的位置(地址)并不固定。 通常,復(fù)位向量指向 CMSIS Reset_Handler 函數(shù)。有兩種不同類型的入口點(diǎn):

初始化入口點(diǎn):鏡像的初始入口點(diǎn)是存儲(chǔ)在 ELF 頭文件中的單個(gè)值。 對(duì)于那些需要由操作系統(tǒng)或引導(dǎo)加載程序加載到 RAM 中的程序,加載程序通過(guò)將控制轉(zhuǎn)移到鏡像中的初始入口點(diǎn)來(lái)啟動(dòng)鏡像執(zhí)行。一個(gè)鏡像只能有一個(gè)初始化入口點(diǎn)。初始入口點(diǎn)可以是 ENTRY 指令設(shè)置的入口點(diǎn)之一,但不是必需的。

ENTRY 指令指定的入口點(diǎn):可以為鏡像從多個(gè)可能的入口點(diǎn)中選擇其中一個(gè)。每個(gè)鏡像只能有一個(gè)入口點(diǎn)。您可以在匯編程序文件中使用 ENTRY 指令在對(duì)象中創(chuàng)建入口點(diǎn)。 在嵌入式系統(tǒng)中,該指令的典型用途是標(biāo)記進(jìn)入處理器異常向量(例如 RESET,IRQ 和 FIQ)的代碼。該指令使用 ENTRY 關(guān)鍵字標(biāo)記輸出代碼部分,該關(guān)鍵字指示鏈接器在執(zhí)行未使用的部分消除時(shí)不刪除該部分。對(duì)于 C/C++ 程序,C 庫(kù) 中的 __main 就是入口點(diǎn)。

如果加載程序要使用嵌入式的映像,則它必須在標(biāo)頭中指定一個(gè)初始入口點(diǎn)。 使用--entry命令行選項(xiàng)選擇入口點(diǎn)。

ARM ELF 文件實(shí)例

??與標(biāo)準(zhǔn)的 ELF 文件相比,ARM ELF 的某些值比較特殊,下面以實(shí)際文件來(lái)說(shuō)明一下每個(gè)部分。編譯工具如下圖:
7043912c-87d6-11ed-bfe3-dac502259ad0.png
編譯后,會(huì)在對(duì)應(yīng)目錄下生成 .o 文件和 .axf 文件,為了分析 ELF 文件,我們將使用 readelf 工具。在詳細(xì)解析之前,先用 Winhex 直接打開生成的 .o 文件,可以看到文件開頭有 ELF 字樣。表明它是一個(gè) ELF 文件。如下:
7060edb2-87d6-11ed-bfe3-dac502259ad0.png
注意:.o 不是 ARM 的可執(zhí)行文件!axf 為可執(zhí)行文件。以下用兩種程序作對(duì)比。

??一個(gè)簡(jiǎn)單的可執(zhí)行 ARM ELF 文件的概念布局如下圖所示。請(qǐng)注意,文件中各部分的實(shí)際排序可能與下圖中的順序不同,因?yàn)橹挥?ELF Header 在文件中具有固定位置。
70763064-87d6-11ed-bfe3-dac502259ad0.png
注意,針對(duì)目前最新版本的 ARM ELF,上圖有點(diǎn)過(guò)時(shí)!

ELF Header

??ELF Header 描述了體系結(jié)構(gòu)和操作系統(tǒng)等基本信息,并指出 Section Header Table 和 Program Header Table 在文件中的什么位置。實(shí)際文件中,只有 ELF Header 位置是絕對(duì)的,且只能在最開始,其他部分部分的位置順序并不一定完全相同。

??Program Header Table 在匯編和鏈接過(guò)程中沒(méi)有用到,所以在重定位文件中可以沒(méi)有;Section Header Table 中保存了所有 Section 的描述信息,Section Header Table 在加載過(guò)程中沒(méi)有用到,對(duì)于可執(zhí)行文件,可以沒(méi)有該部分。當(dāng)然,對(duì)于某些類型的文件來(lái)說(shuō),可以同時(shí)擁有 Program header table 和 Section Header Table,這樣 load 完后還可以重定位。(例如:shared objects)

??ELF Header 可以使用如下數(shù)據(jù)結(jié)構(gòu)表示:

#defineEI_NIDENT16

typedefstruct{
unsignedchare_ident[EI_NIDENT];//Magic
Elf32_Halfe_type;//Type
Elf32_Halfe_machine;//Machine
Elf32_Worde_version;//Version
Elf32_Addre_entry;//Entrypointaddress
Elf32_Offe_phoff;//Startofprogramheaders
Elf32_Offe_shoff;//Startofsectionheaders
Elf32_Worde_flags;//Flags
Elf32_Halfe_ehsize;//Sizeofthisheader
Elf32_Halfe_phentsize;//Sizeofprogramheaders
Elf32_Halfe_phnum;//Numberofprogramheaders
Elf32_Halfe_shentsize;//Sizeofsectionheaders
Elf32_Halfe_shnum;//Numberofsectionheaders
Elf32_Halfe_shstrndx;//Sectionheaderstringtableindex
}Elf32_Ehdr;
123456789101112131415161718

下面兩幅圖分別顯示了不同文件的 ELF Header。以上數(shù)據(jù)結(jié)構(gòu)中的注釋,即對(duì)應(yīng)于下圖中的各部分字段。.o 文件 ELF Header 如下圖所示:
708a6bba-87d6-11ed-bfe3-dac502259ad0.png.
axf 文件 ELF Header 如下圖所示:

70a9945e-87d6-11ed-bfe3-dac502259ad0.png

下面對(duì)以上兩幅圖中的內(nèi)容做一下詳細(xì)介紹:

第 1 行 ELF Header:這是 readelf 工具的顯示,實(shí)際文件中不存在這個(gè)符號(hào)!直接從 Magic 開始!

第 2 行 Magic:用來(lái)指名該文件是一個(gè) ELF 對(duì)象文件(Object File),對(duì)應(yīng)于 Elf32_Ehdr 數(shù)據(jù)結(jié)構(gòu)中的

unsignedchare_ident[EI_NIDENT];

,使用以下宏值進(jìn)行索引

名稱 取值 意義
EI_MAG0 0 文件標(biāo)識(shí)
EI_MAG1 1 文件標(biāo)識(shí)
EI_MAG2 2 文件標(biāo)識(shí)
EI_MAG3 3 文件標(biāo)識(shí)
EI_CLASS 4 文件類
EI_DATA 5 數(shù)據(jù)編碼
EI_VERSION 6 文件版本
EI_PAD 7 補(bǔ)齊字節(jié)開始處
EI_NIDENT 16 e_ident[]大小

e_ident[EI_MAG0]~e_ident[EI_MAG3]

:包含了 ELF 文件的魔數(shù),依次固定是 0x7f 和 ‘E’、‘L’、‘F’。

e_ident[EI_CLASS]

:取值如下

名稱 取值 意義
ELFCLASSNONE 0 非法類別
ELFCLASS32 1 32
ELFCLASS64 2 64

ARM ELF 文件應(yīng)包含 ELFCLASS32。

e_ident[EI_DATA]

名稱 取值 意義
ELFDATANONE 0 非法數(shù)據(jù)編碼
ELFDATA2LSB 1 高位在前
ELFDATA2MSB 2 低位在前

選擇將由執(zhí)行環(huán)境中的默認(rèn)數(shù)據(jù)順序控制。 在以 BE8 模式運(yùn)行的 Architecture v6 處理器上,所有的指令均為小端格式。 適合在此模式下操作的可執(zhí)行文件將在 e_flags 字段中設(shè)置 EF_ARM_BE8。

e_ident[EI_VERSION]

:指定 ELF頭部的版本,當(dāng)前必須為 1。

e_ident[7]~e_ident[15]

:是填充符,通常是 0

第 3 行 Class:該值就是 e_ident[EI_CLASS]。

第 4 行 Data:該值就是 e_ident[EI_DATA]。

第 5 行 Version:該值就是 e_ident[EI_VERSION]

第 6 行 OS/ABI:該值應(yīng)該是

e_ident

的擴(kuò)展部分。操作系統(tǒng)類型,ABI 是 Application Binary Interface 的縮寫。除非文件使用具有 OS 特定含義的標(biāo)志(例如,使用 SHN_LOOS 通過(guò) SHN_HIOS 的段索引),否則該字段應(yīng)為零。 目前,該字段有一個(gè)特定于處理器的值,如下。

取值 意義
ELFOSABI_ARM_AEABI (64) 該對(duì)象包含符號(hào)版本控制擴(kuò)展,如§3.1.1符號(hào)版本控制中所述。

第 7 行 ABI Version: 該值應(yīng)該是 e_ident 的擴(kuò)展部分。版本號(hào),當(dāng)前為 0 。

第 8 行 Type:表示該對(duì)象文件(Object File)類型(上圖中的類型省略了ET_)。

名稱 取值 意義
ET_NONE 0 未知對(duì)象文件(Object File)格式
ET_REL 1 可重定位文件
ET_EXEC 2 可執(zhí)行文件
ET_DYN 3 共享對(duì)象文件(Object File)
ET_CORE 4 Core 文件(轉(zhuǎn)儲(chǔ)格式)
ET_LOPROC 0xff00 特定處理器文件 ET_LOPROC 和 ET_HIPROC 之間的取值用來(lái)標(biāo)識(shí)與處理器相關(guān)的文件格式。
ET_HIPROC 0xffff 特定處理器文件

目前沒(méi)有特定于 ARM 的對(duì)象文件類型。

ET_LOPROC

ET_HIPROC

之間的所有值都保留給本規(guī)范的未來(lái)版本。

第 9 行 Machine:機(jī)器平臺(tái)類型。ARM 架構(gòu)為 EM_ARM(上圖中的類型省略了ET_)。

Name Value Meaning
EM_NONE 0 No machine
EM_M32 1 AT&T WE 32100
EM_SPARC 2 SPARC
EM_386 3 Intel Architecture
EM_68K 4 Motorola 68000
EM_88K 5 Motorola 88000
EM_860 7 Intel 80860
EM_MIPS 8 MIPS RS3000 Big-Endian
EM_MIPS_RS4_BE 10 MIPS RS4000 Big-Endian
……
EM_ARM 40 ARM/Thumb Architecture

第 10 行 Version:當(dāng)前對(duì)象文件(Object File)的版本號(hào)。

名稱 取值 意義 說(shuō)明
EV_NONE 0 Invalid version
EV_CURRENT 1 Current version 該項(xiàng)的取值可根據(jù)需要改變

第 11 行 Entry point address:程序的虛擬地址入口點(diǎn)。在 ARM 中:

在可執(zhí)行 ELF 文件中,e_entry 是鏡像唯一入口點(diǎn)的虛擬地址,如果鏡像沒(méi)有唯一入口點(diǎn),則為 0。

在可重定位ELF文件中,e_entry 是被 SHF_ENTRYSECT 所標(biāo)記的段的入口點(diǎn)的偏移量,若沒(méi)有入口點(diǎn),則為 0。

Bit[0] = 1,表示 Thumb 指令;Bit[0:1] = 00,表示ARM指令;Bit[0:1] = 10,保留;平臺(tái)標(biāo)準(zhǔn)可以指定可執(zhí)行文件總是具有入口點(diǎn),在這種情況下,e_entry 指定入口點(diǎn),即使為零。

第 12 行 Start of program headers:程序頭的起始地址,.o 文件沒(méi)有 Program Headers 。

第 13 行 Start of section headers:節(jié)頭的起始地址。上圖中的 486388 是十進(jìn)制,即:表示節(jié)頭是從地址偏移 0x76BF4 處開始。

第 14 行 Flags:是一個(gè)與處理器相關(guān)聯(lián)的標(biāo)志。

名稱 意義
EF_ARM_ABIMASK (0xFF000000) (current version is 0x05000000) 此ELF文件符合的ARM EABI的版本,該值為一個(gè)8比特的掩碼。 當(dāng)前EABI是版本5。0表示未知符合。
EF_ARM_BE8 (0x00800000) ELF文件包含適合在ARM Architecture v6處理器上執(zhí)行的BE-8代碼。 該標(biāo)志只能在可執(zhí)行文件上設(shè)置。
EF_ARM_GCCMASK (0x00400FFF) gcc-arm-xxx生成的舊版代碼(ABI版本4及更早版本)可能會(huì)使用這些位。
EF_ARM_ABI_FLOAT_HARD (0x00000400) (ABI version 5 and later) 設(shè)置可執(zhí)行文件頭(e_type = ET_EXEC或ET_DYN)以標(biāo)注可執(zhí)行文件的構(gòu)建是為了符合硬件浮點(diǎn)過(guò)程調(diào)用標(biāo)準(zhǔn)。 與舊版(預(yù)版本5)兼容,gcc用作EF_ARM_VFP_FLOAT
EF_ARM_ABI_FLOAT_SOFT (0x00000200) (ABI version 5 and later) 設(shè)置在可執(zhí)行文件頭(e_type = ET_EXEC或ET_DYN)中明確標(biāo)注可執(zhí)行文件的構(gòu)建符合軟件浮點(diǎn)過(guò)程調(diào)用標(biāo)準(zhǔn)(基準(zhǔn)標(biāo)準(zhǔn))。 如果EF_ARM_ABI_FLOAT_XXXX位都清零,則默認(rèn)符合基本過(guò)程調(diào)用標(biāo)準(zhǔn)。 與舊版(預(yù)版本5)兼容,gcc用作EF_ARM_SOFT_FLOAT。

注意:以上部分與 ARM 早期文檔是有區(qū)別的,很多值已經(jīng)不同

第 15 行 Size of this header:ELF 文件頭的字節(jié)數(shù)。

第 16 行 Size of program headers:Program Headers 大小。.o 文件大小為 0。

第 17 行 Number of program headers:Program Headers 的數(shù)量(可以有多個(gè))。

第 18 行 Size of section headers:sections header 的大小

第 19 行 Number of section headers:sections header 的數(shù)量。

第 20 行 Section header string table index:節(jié)頭部表格中與節(jié)名稱字符串表相關(guān)的表項(xiàng)的索引。如果文件沒(méi)有節(jié)名稱字符串表,此參數(shù)可以為 SHN_UNDEF。

注意:實(shí)際文件中,每一部分的位置順序并不一定完全相同,只有 ELF Header 位置是絕對(duì)的,且只能在最開始。

Section Header(節(jié)頭)

??節(jié)頭表提供了對(duì) ELF 文件中所有節(jié)的訪問(wèn)。節(jié)中包含對(duì)象文件(Object File)中的所有信息,除了:ELF 頭部、程序頭部表格、節(jié)頭部 表格。節(jié)滿足以下條件:

對(duì)象文件(Object File)中的每個(gè)節(jié)都有對(duì)應(yīng)的節(jié)頭部描述它,反過(guò)來(lái),有節(jié)頭部不意 味著有節(jié)。

每個(gè)節(jié)占用文件中一個(gè)連續(xù)字節(jié)域(這個(gè)區(qū)域可能長(zhǎng)度為 0)。

文件中的節(jié)不能重疊,不允許一個(gè)字節(jié)存在于兩個(gè)節(jié)中的情況發(fā)生。

對(duì)象文件(Object File)中可能包含非活動(dòng)空間(INACTIVE SPACE)。這些區(qū)域不屬于任何 頭部和節(jié),其內(nèi)容未指定。

??ELF 頭部中,e_shoff 成員給出從文件頭到節(jié)頭部表格的偏移字節(jié)數(shù);e_shnum 給出表格中條目數(shù)目;e_shentsize 給出每個(gè)項(xiàng)目的字節(jié)數(shù)。從這些信息中可以確切地定位節(jié)的具體位置、長(zhǎng)度。節(jié)頭部表格中比較特殊的幾個(gè)下標(biāo)如下:

名稱 取值 說(shuō)明
SHN_UNDEF 0 標(biāo)記未定義的、缺失的、不相關(guān)的,或者沒(méi)有含義的節(jié)引用
SHN_LORESERVE OxFF00 保留索引的下界
SHN_LOPROC 0xFF00 SHN_HIPROC 0XFF1F 保留給處理器特殊的語(yǔ)義
SHN_ABS 1 包含對(duì)應(yīng)引用量的絕對(duì)取值。這些值不會(huì)被重定位所 影響
SHN_COMMON 2 相對(duì)于此節(jié)定義的符號(hào)是公共符號(hào)。如 FORTRAN 中 COMMON 或者未分配的 C 外部變量。
SHN_HIRESERVE 保留索引的上界

介于 SHN_LORESERVE 和 SHN_HIRESERVE 之間的表項(xiàng)不會(huì)出現(xiàn)在節(jié)頭部表中。

.o文件 Section Header(部分)
70c64e50-87d6-11ed-bfe3-dac502259ad0.png
.axf 文件 Section Header
70dd463c-87d6-11ed-bfe3-dac502259ad0.png
上圖中的表頭可以用如下數(shù)據(jù)結(jié)構(gòu)描述(對(duì)應(yīng)關(guān)系見注釋):

typedefstruct{
Elf32_Wordsh_name;//name
Elf32_Wordsh_type;//Type
Elf32_Wordsh_flags;//Flg
Elf32_Addrsh_addr;//Addr
Elf32_Offsh_offset;//Off
Elf32_Wordsh_size;//Size
Elf32_Wordsh_link;//Lk
Elf32_Wordsh_info;//Inf
Elf32_Wordsh_addralign;//Al
Elf32_Wordsh_entsize;//ES
}Elf32_Shdr;
123456789101112

sh_name:給出節(jié)名稱。是節(jié)頭部字符串表節(jié)(Section Header String Table Section)的索引。名字是一個(gè) NULL 結(jié)尾的字符串。ELF 文件規(guī)定一些標(biāo)準(zhǔn)節(jié)的名字,例如 .text、.data、.bss。此外,如上圖中,許多節(jié)名字都是 ARM 自己擴(kuò)展的。

sh_type:為節(jié)的內(nèi)容和語(yǔ)義進(jìn)行分類。ARM ELF 只使用了其中的一部分。參見下表(部分)。

名稱 取值 含義
SHT_NULL 0 此值標(biāo)志節(jié)頭部是非活動(dòng)的,沒(méi)有對(duì)應(yīng)的節(jié)。此節(jié)頭部中的其他成員取值無(wú)意義。
SHT_PROGBITS 1 此節(jié)包含程序定義的信息,其格式和含義都由程序來(lái)解釋釋。
SHT_SYMTAB 2 此節(jié)包含一個(gè)符號(hào)表。目前對(duì)象文件(Object File)對(duì)每種類型的節(jié)都只能包含一個(gè),不過(guò)這個(gè)限制將來(lái)可能發(fā)生變化。一般,SHT_SYMTAB 節(jié)提供用于鏈接編輯(指 ld而言) 的符號(hào),盡管也可用來(lái)實(shí)現(xiàn)動(dòng)態(tài)鏈接。
SHT_STRTAB 3 此節(jié)包含字符串表。對(duì)象文件(Object File)可能包含多個(gè)字符串表節(jié)。
SHT_RELA 4 此節(jié)包含重定位表項(xiàng),其中可能會(huì)有補(bǔ)齊內(nèi)容(addend),例如 32 位對(duì)象文件(Object File)中的 Elf32_Rela 類型。對(duì)象文件(Object File)可能擁有多個(gè)重定位節(jié)。
SHT_HASH 5 此節(jié)包含符號(hào)哈希表。所有參與動(dòng)態(tài)鏈接的目標(biāo)都必須包含一個(gè)符號(hào)哈希表。目前,一個(gè)對(duì)象文件(Object File)只能包含一個(gè)哈希表, 不過(guò)此限制將來(lái)可能會(huì)解除。
SHT_DYNAMIC 6 此節(jié)包含動(dòng)態(tài)鏈接的信息。目前一個(gè)對(duì)象文件(Object File)中只能包含一個(gè)動(dòng)態(tài)節(jié),將來(lái)可能會(huì)取消這一限制。
SHT_NOTE 7 此節(jié)包含以某種方式來(lái)標(biāo)記文件的信息。
SHT_NOBITS 8 這種類型的節(jié)不占用文件中的空間,其他方面和 SHT_PROGBITS 相似。盡管此節(jié)不包含任何字節(jié),成員sh_offset 中還是會(huì)包含概念性的文件偏移
SHT_REL 9 此節(jié)包含重定位表項(xiàng),其中沒(méi)有補(bǔ)齊(addends),例如 32 位對(duì)象文件(Object File)中的 Elf32_rel 類型。對(duì)象文件(Object File)中可以擁有多個(gè)重定位節(jié)。

除了以上標(biāo)準(zhǔn)節(jié)類型外,ARM 架構(gòu)下,還有以下特殊的類型:

名稱 取值 含義
SHT_ARM_EXIDX 0x70000001 異常索引表
SHT_ARM_PREEMPTMAP 0x70000002 BPABI DLL動(dòng)態(tài)鏈接搶占地圖
SHT_ARM_ATTRIBUTES 0x70000003 對(duì)象文件兼容性屬性
SHT_ARM_DEBUGOVERLAY 0x70000004
SHT_ARM_OVERLAYSECTION 0x70000005

sh_flags:字段定義了一個(gè)節(jié)中包含的內(nèi)容是否可以修改、是否可以執(zhí)行等信息。如果一個(gè)標(biāo)志比特位被設(shè)置,則該位取值為1。未定義的各位都設(shè)置為 0。

名稱 取值 含義
SHF_WRITE 0x1 節(jié)包含進(jìn)程執(zhí)行過(guò)程中將可寫的數(shù)據(jù)
SHF_ALLOC 0x2 此節(jié)在進(jìn)程執(zhí)行過(guò)程中占用內(nèi)存。某些控制節(jié)并不出現(xiàn)于目標(biāo) 文件的內(nèi)存映像中,對(duì)于那些節(jié),此位應(yīng)設(shè)置為 0
SHF_EXECINSTR 0x4 節(jié)包含可執(zhí)行的機(jī)器指令
SHF_MASKPROC 0xF0000000 所有包含于此掩碼中的四位都用于處理器專用的語(yǔ)義

ARM 中的特殊取值如下:

Name Value Purpose
SHF_ARM_NOREAD 0x20000000 本節(jié)的內(nèi)容不應(yīng)由程序執(zhí)行者讀取

sh_addr:如果節(jié)將出現(xiàn)在進(jìn)程的內(nèi)存鏡像中,此成員給出節(jié)的第一個(gè)字節(jié)應(yīng)處的位置。否則,此字段為 0。

sh_link 和 sh_info:根據(jù)節(jié)類型的不同,sh_link 和 sh_info 的具體含義也有所不同。ARM 取值如下:

sh_type sh_link sh_info
SHT_SYMTAB, SHT_DYNSYM 相關(guān)聯(lián)的字符串表的節(jié)頭部索引 最后一個(gè)局部符號(hào)(綁定 STB_LOCAL)的符號(hào)表索引值加一
SHT_DYNAMIC 此節(jié)中條目所用到的字符串表格 的節(jié)頭部索引 0
SHT_HASH 此哈希表所適用的符號(hào)表的節(jié)頭部索引 0
SHT_REL、SHT_RELA 相關(guān)符號(hào)表的節(jié)頭部索引 重定位所適用的節(jié)的節(jié)頭部索引
其它 SHN_UNDEF 0

sh_addralign:節(jié)沒(méi)有最小對(duì)齊要求。 但是,包含 thumb 代碼的部分必須至少為 16 位對(duì)齊,并且包含 ARM 代碼的部分必須至少為 32 位對(duì)齊。具有 SHF_ALLOC 屬性的任何節(jié)必須滿足 sh_addralign >= 4。其他節(jié)可根據(jù)需要對(duì)齊。 例如,調(diào)試表通常沒(méi)有對(duì)齊要求。并且輸入到靜態(tài)鏈接器的數(shù)據(jù)段可以自然對(duì)齊。平臺(tái)標(biāo)準(zhǔn)可能會(huì)限制他們可以保證的最大對(duì)齊(通常是頁(yè)面大?。?。

sh_entsize:某些節(jié)中包含固定大小的項(xiàng)目,如符號(hào)表。對(duì)于這類節(jié),此成員給出每個(gè)表項(xiàng)的長(zhǎng)度字節(jié)數(shù)。如果節(jié)中并不包含固定長(zhǎng)度表項(xiàng)的表格,此成員取值為 0。

sh_size:此成員給出本節(jié)的長(zhǎng)度(字節(jié)數(shù))。除非節(jié)的類型是 SHT_NOBITS,否則節(jié)占用文件中的 sh_size 字節(jié)。類型為 SHT_NOBITS 的節(jié)長(zhǎng)度可能非零,不過(guò)卻不占用文件中的空間。

sh_offset:此成員的取值給出節(jié)的第一個(gè)字節(jié)與文件頭之間的偏移。不過(guò),SHT_NOBITS 類型的節(jié)不占用文件的空間,因此其 sh_offset 成員給出的是其概念性的偏移。

注意:

保留給處理器體系結(jié)構(gòu)的節(jié)名稱一般構(gòu)成為:「處理器體系結(jié)構(gòu)名稱簡(jiǎn)寫 + 節(jié)名稱」。且處理器名稱應(yīng)該與 e_machine 中使用的名稱相同。例如:上圖最后的 .ARM.attributes

對(duì)象文件(Object File)中也可以包含多個(gè)名字相同的節(jié)。

上圖節(jié)名 ER_IROM1、RW_IRAM1、RW_IRAM 是由連接器的分散加載文件指定的名稱??梢愿鶕?jù)需要自行修改。

??ARM 節(jié)名稱是以下面列出的具有預(yù)定義含義的標(biāo)準(zhǔn)前綴之一開始的名稱,或者是包含美元($)字符的名稱。 在 ARM EABI 下沒(méi)有其他具有特殊意義的段名稱。

節(jié)前綴名 節(jié)類型 節(jié)屬性 解釋
.bss SHT_NOBITS SHF_ALLOC+SHF_WRITE 本節(jié)保存有助于程序內(nèi)存映像的未初始化數(shù)據(jù)。 根據(jù)定義,當(dāng)程序開始運(yùn)行時(shí),系統(tǒng)將使用零初始化數(shù)據(jù)。 該部分不占用文件空間,如段類型 SHT_NOBITS 所示。
.comment SHT_PROGBITS None 本節(jié)包含版本控制信息
.data SHT_PROGBITS SHF_ALLOC+SHF_WRITE 這些部分保存有助于程序內(nèi)存映像的已初始化數(shù)據(jù)
.data1 SHT_PROGBITS SHF_ALLOC+SHF_WRITE
.debug… SHT_PROGBITS None 本節(jié)保存符號(hào)調(diào)試信息。 內(nèi)容未指定。 具有前綴.debug的所有段名保留供將來(lái)使用
.dynamic SHT_DYNAMIC SHF_ALLOC [+SHF_WRITE] 本節(jié)保存動(dòng)態(tài)鏈接信息,并具有SHF_ALLOC和SHF_WRITE等屬性。 操作系統(tǒng)和處理器確定SHF_WRITE位是否被置位
.hash SHT_HASH [SHF_ALLOC] 本節(jié)包含一個(gè)符號(hào)哈希表。
.line SHT_PROGBITS None 本節(jié)保存符號(hào)調(diào)試的行號(hào)信息,其中描述了源程序和機(jī)器代碼之間的對(duì)應(yīng)關(guān)系。 內(nèi)容未指定
.rodata SHT_PROGBITS SHF_ALLOC 這些部分保存通常有助于過(guò)程映像中的不可寫段的只讀數(shù)據(jù)
.rodata1 SHT_PROGBITS SHF_ALLOC
.rel name .rela name SHT_REL SHT_RELA [SHF_ALLOC] 這些節(jié)中包含了重定位信息。如果文件中 包含可加載的段,段中有重定位內(nèi)容,節(jié) 的屬性將包含 SHF_ALLOC 位,否則該位 置 0。傳統(tǒng)上 name 根據(jù)重定位所適用的節(jié) 區(qū)給定。例如 .text 節(jié)的重定位節(jié)名字,將是:.rel.text 或者 .rela.text。
.shstrtab SHT_STRTAB None 本節(jié)保存節(jié)名稱。
.strtab SHT_STRTAB [SHF_ALLOC] 此節(jié)包含字符串,通常是代表與符號(hào)表項(xiàng) 相關(guān)的名稱。如果文件擁有一個(gè)可加載的 段,段中包含符號(hào)串表,節(jié)的屬性將包含 SHF_ALLOC 位,否則該位為 0。
.symtab SHT_SYMTAB [SHF_ALLOC] 此節(jié)包含一個(gè)符號(hào)表。如果文件中包含一 個(gè)可加載的段,并且該段中包含符號(hào)表,那 么節(jié)的屬性中包含SHF_ALLOC 位,否則 該位置為 0。
.text SHT_PROGBITS SHF_ALLOC+ SHF_EXECINSTR 本節(jié)包含程序的文本或可執(zhí)行指令

除了以上標(biāo)準(zhǔn)節(jié)外,ARM 架構(gòu)下,還有以下特殊的節(jié):

節(jié)前綴名 節(jié)類型 節(jié)屬性 說(shuō)明
.ARM.exidx* SHT_ARM_EXIDX SHF_ALLOC + SHF_LINK_ORDER 以.ARM.exidx開頭的節(jié)包含部分展開的索引條目。
.ARM.extab* SHT_PROGBITS SHF_ALLOC 以.ARM.extab開頭的節(jié)包含異常展開信息的名稱部分。
.ARM.preemptmap SHT_ARM_PREEMPTMAP SHF_ALLOC 以.ARM.preemptmap開頭的節(jié)包含一個(gè)BPABI DLL動(dòng)態(tài)鏈接優(yōu)先地圖。
.ARM.attributes SHT_ARM_ATTRIBUTES none 包含構(gòu)建屬性
.ARM.debug_overlay SHT_ARM_DEBUGOVERLAY none
.ARM.overlay_table SHT_ARM_OVERLAYSECTION See DBGOVL for details

??這里需要注意一下 Debug Sections。Debug Sections 僅在調(diào)試時(shí)使用,稍微復(fù)雜一些。ARM 可執(zhí)行 ELF 文件的調(diào)試節(jié)中包含多種類型的調(diào)試信息,ELF 可執(zhí)行文件的使用者(如armlink)可以通過(guò)檢查可執(zhí)行文件的節(jié)表來(lái)區(qū)分這些種類型的調(diào)試信息。

??ARM 系列的開發(fā)工具在不同的發(fā)展時(shí)期,采用的調(diào)試信息是有區(qū)別的,后來(lái)統(tǒng)一采用 DWARP。目前采用的應(yīng)該是 3.0 版本。具體如下:

ASD debugging tables:These provide backwards compatibility with ARM’s Symbolic Debugger. ASD debugging information is stored in a single Section in the executable named .asd.

DWARP version 1.0

When DWARF 1.0 debugging information is included by the linker in the ELF executable, the file contains the following ELF Sections, each of which has a Section Header Table entry:

Section name Contents
.debug debugging entries
.line fileinfo entries
.debug_pubnames table for accelerated access to debug items
.debug_aranges address ranges for compilation units

DWARF version 2.0

When DWARF 2.0 debugging information is included by the linker in the ELF executable, the file contains the following ELF sections, each of which has a Section Header Table entry:

Section name Contents
.debug_info debugging entries
.debug_line fileinfo statement program
.debug_pubnames table for accelerated access to debug items
.debug_aranges address ranges for compilation units
.debug_macinfo macro information (#define / #undef)
.debug_frame call frame information
.debugj_abbrev abbreviation table
.debug_str debug string table

關(guān)于DWARF調(diào)試標(biāo)準(zhǔn)詳見:http://www.dwarfstd.org/。目前最新版本是The DWARF Debugging Standard Version 5

Program Headers(程序頭)

??可執(zhí)行文件或者共享對(duì)象文件(Object File)的程序頭部是一個(gè)結(jié)構(gòu)數(shù)組,每個(gè)結(jié)構(gòu)描述了一個(gè)段或者系統(tǒng)準(zhǔn)備程序執(zhí)行所必需的其它信息。對(duì)象文件(Object File)的"段"包含一個(gè)或者多個(gè)"節(jié)",也就是"段內(nèi)容(Segment Contents)"。程序頭部?jī)H對(duì)于可執(zhí)行文件和共享對(duì)象文件(Object File)有意義。圖7 Program Header
70f2e712-87d6-11ed-bfe3-dac502259ad0.png
程序頭可以使用如下數(shù)據(jù)結(jié)構(gòu)來(lái)表示(對(duì)應(yīng)關(guān)系見注釋):

typedefstruct{
Elf32_Wordp_type;//Type
Elf32_Offp_offset;//Offset
Elf32_Addrp_vaddr;//VirtAddr
Elf32_Addrp_paddr;//PhyAddr
Elf32_Wordp_filesz;//FileSiz
Elf32_Wordp_memsz;//MemSiz
Elf32_Wordp_flags;//Flg
Elf32_Wordp_align;//Align
}Elf32_Phdr;
12345678910

p_type:這個(gè)成員告訴這個(gè)數(shù)組元素描述什么樣的段,或者如何解釋數(shù)組元素的信息。 類型值及其含義如下圖所示。

名稱 取值 意義
PT_NULL 0 數(shù)組元素未使用; 其他成員的值是未定義的。 此類型使程序頭表已忽略條目。
PT_LOAD 1 數(shù)組元素指定由p_filesz和p_memsz描述的可加載段。
PT_DYNAMIC 2 數(shù)組元素指定動(dòng)態(tài)鏈接信息。
PT_INTERP 3 數(shù)組元素指定要作為解釋器調(diào)用的以空值結(jié)尾的路徑名的位置和大小。
PT_NOTE 4 數(shù)組元素指定輔助信息的位置和大小。
PT_SHLIB 5 該段類型是保留的,但具有未指定的語(yǔ)義。
PT_PHDR 6 數(shù)組元素(如果存在)指定程序頭表本身的位置和大小。
PT_ARM_ARCHEXT 0x70000000 Platform architecture compatibility information
PT_ARM_EXIDX PT_ARM_UNWIND 0x70000001 Exception unwind tables

p_offset:此成員給出從文件頭到該段第一個(gè)字節(jié)的偏移

p_vaddr:此成員給出段的第一個(gè)字節(jié)將被放到內(nèi)存中的虛擬地址。

p_paddr:此成員僅用于與物理地址相關(guān)的系統(tǒng)中。因?yàn)?System V 忽略所有應(yīng)用程序的物理地址信息,此字段對(duì)與可執(zhí)行文件和共享對(duì)象文件(Object File)而言,具體內(nèi)容是未指定的。

p_filesz:此成員給出段在文件鏡像中所占的字節(jié)數(shù)??梢詾?0。

p_memsz: 此成員給出段在內(nèi)存鏡像中占用的字節(jié)數(shù)??梢詾?0。

p_flags:此成員給出與段相關(guān)的標(biāo)志。

名稱 取值 意義
PF_X 1 可執(zhí)行的段
PF_W 2 可寫的段
PF_R 4 可讀的段
PF_MASKPROC 0xf0000000 保留

p_align:可加載的進(jìn)程段的 p_vaddr 和 p_offset 取值必須合適,相對(duì)于對(duì)頁(yè)面大小的取模而言。此成員給出段在文件中和內(nèi)存中如何 對(duì)齊。數(shù)值 0 和 1 表示不需要對(duì)齊。否則 p_align 應(yīng)該是個(gè) 正整數(shù),并且是 2 的冪次數(shù),p_vaddr 和 p_offset 對(duì) p_align 取模后應(yīng)該相等。

Symbol table(符號(hào)表)

??一個(gè)對(duì)象文件的符號(hào)表保存了定位和重定位所在程序的符號(hào)定義和引用所需的信息。符號(hào)表以數(shù)組的下標(biāo)進(jìn)行索引。0 指定表中的第一個(gè)條目,并用作未定義的符號(hào)索引。ARM 結(jié)構(gòu)中,符號(hào)表與標(biāo)準(zhǔn)的 ELF 文件沒(méi)有任何區(qū)別。

圖12 .o文件 Symbol table(部分)
71129b98-87d6-11ed-bfe3-dac502259ad0.png
??在 C 語(yǔ)言中,符號(hào)表保存了程序?qū)崿F(xiàn)或使用的所有全局變量和函數(shù),如果程序引用一個(gè)自身代碼未定義的符號(hào),則稱之為未定義符號(hào),這類引用必須在靜態(tài)鏈接期間用其他目標(biāo)模塊或庫(kù)解決,或在加載時(shí)通過(guò)動(dòng)態(tài)鏈接解決。

符號(hào)表可以使用以下數(shù)據(jù)結(jié)構(gòu)表示:

typedefstruct{
Elf32_Wordst_name;//Name
Elf32_Addrst_value;//Value
Elf32_Wordst_size;//Size
unsignedcharst_info;//
unsignedcharst_other;
Elf32_Halfst_shndx;//Ndx
}Elf32_Sym;
12345678

st_name:該成員將對(duì)象文件(Object File)的符號(hào)字符串表中的索引保存在符號(hào)名稱的字符表示中

st_value:該成員給出相關(guān)聯(lián)的符號(hào)的值。 根據(jù)上下文,這可能是絕對(duì)值,地址等等; 不同對(duì)象文件(Object File)類型的符號(hào)表?xiàng)l目對(duì) st_value 成員的解釋略有不同。

在可重定位文件中,st_value 保持其索引為 SHN_COMMON 的符號(hào)的對(duì)齊約束。

在可重定位文件中,st_value 包含已定義符號(hào)的節(jié)偏移量。 也就是說(shuō),st_value 是 st_shndx 標(biāo)識(shí)的部分開頭的偏移量。

在可執(zhí)行文件和共享對(duì)象文件中,st_value 包含虛擬地址 1。 為了使這些文件的符號(hào)對(duì)動(dòng)態(tài)鏈接器更有用,段偏移(文件解釋)讓位于與段號(hào)無(wú)關(guān)的虛擬地址(存儲(chǔ)器解釋)。

st_size:許多符號(hào)具有相關(guān)尺寸。 例如,數(shù)據(jù)對(duì)象的大小是對(duì)象中包含的字節(jié)數(shù)。 如果符號(hào)沒(méi)有大小或未知的大小,該成員將保持0。

st_info:該成員指定符號(hào)的類型和綁定屬性。 值和值的列表如下面兩個(gè)表格所示。 以下代碼顯示了如何操作這些值。

#defineELF32_ST_BIND(i)((i)>>4)

#defineELF32_ST_TYPE(i)((i)&0xf)

#defineELF32_ST_INFO(b,t)(((b)<<4)+((t)&0xf))
12345

A symbol’s binding determines the linkage visibility and behavior.

Name Value Meaning
STT_NOTYPE 0 The symbol’s type is not specified.
STT_OBJECT 1 The symbol is associated with a data object, such as a variable, an array, and so on.
STT_FUNC 2 The symbol is associated with a function or other executable code.
STT_SECTION 3 The symbol is associated with a section. Symbol table entries of this type exist primarily for relocation and normally have STB_LOCAL binding.
STT_FILE 4 A file symbol has STB_LOCAL binding, its section index is SHN_A BS, and it precedes the other STB_LOCAL symbols for the file, if it is present.
STT_LOPROC 13 Values in this inclusive range are reserved for processor-specific semantics. If a symbol’s value refers to a specific location within a section, its section index member, st_shndx, holds an index into the section header table. As the section moves during relocation, the symbol’s value changes as well, and references to the symbol continue to point to the same location in the program. Some special section index values give other semantics.
STT_HIPROC 15

In each symbol table, all symbols with STB_LOCAL binding precede the weak and global symbols. A symbol’s type provides a general classification for the associated entity. Figure 3-17, Symbol Types, ELF32_ST_TYPE

Name Value Meaning
STT_NOTYPE 0 The symbol’s type is not specified.
STT_OBJECT 1 The symbol is associated with a data object, such as a variable, an array, and so on.
STT_FUNC 2 The symbol is associated with a function or other executable code.
STT_SECTION 3 The symbol is associated with a section. Symbol table entries of this type exist primarily for relocation and normally have STB_LOCAL binding.
STT_FILE 4 A file symbol has STB_LOCAL binding, its section index is SHN_A BS, and it precedes the other STB_LOCAL symbols for the file, if it is present.
STT_LOPROC 13 Values in this inclusive range are reserved for processor-specific semantics. If a symbol’s value refers to a specific location within a section, its section index member, st_shndx, holds an index into the section header table. As the section moves during relocation, the symbol’s value changes as well, and references to the symbol continue to point to the same location in the program. Some special section index values give other semantics.
STT_HIPROC 15

st_other:該成員目前只有 0,沒(méi)有定義。

st_shndx:每個(gè)符號(hào)表?xiàng)l目與某些部分有關(guān)"定義"; 該成員保存相關(guān)部分標(biāo)題表索引。 如上圖3-7和3.3.1節(jié)所述,一些段索引表示特殊含義。

??The symbols in ELF object files convey specific information to the linker and loader. See section 4, ARM- and Thumb-Specific Definitions, for a description of the actual linking model used in the system.

SHN_ABS:The symbol has an absolute value that will not change because of relocation.

SHN_COMMON:The symbol labels a common block that has not yet been allocated. The symbol’s value gives alignment constraints, similar to a section’s sh_addralign member. That is, the link editor will allocate the storage for the symbol at an address that is a multiple of st_value. The symbol’s size tells how many bytes are required.

SHN_UNDEF:This section table index means the symbol is undefined. When the link editor combines this object file with another that defines the indicated symbol, this file’s references to the symbol will be linked to the actual definition.

As mentioned above, the symbol table entry for index 0 (STN_UNDEF) is reserved. It is shown in Figure 3-18. Figure 3-18, Symbol Table Entry: Index 0

Name Value Note
st_name 0 No name
st_value 0 Zero value
st_size 0 No size
st_info 0 No type, local binding
st_other 0
st_shndx SHN_UNDEF No section

String table(字符串表)

??字符串表節(jié)包含以 NULL(ASCII 碼 0)結(jié)尾的字符序列,通常稱為字符串。ELF 對(duì)象文件(Object File)通常使用字符串來(lái)表示符號(hào)和節(jié)名稱。對(duì)字符串的引用通常以字符串在字符 串表中的下標(biāo)給出。ARM結(jié)構(gòu)中,字符串表與標(biāo)準(zhǔn)的 ELF 文件沒(méi)有任何區(qū)別。

axf 文件

??axf 文件是 ARM 的調(diào)試文件,其格式符合上一節(jié)講的對(duì)象文件(Object File)格式(ELF)。其中除了包含了完整的 bin 文件外,還附加了其他的調(diào)試信息。在調(diào)試的時(shí)候,這些調(diào)試信息是不必下到 RAM 中去的,真正下到 RAM 中的信息僅僅是可執(zhí)行代碼。下圖為 axf 文件的頭部。
712e0856-87d6-11ed-bfe3-dac502259ad0.png

??通過(guò)直接查看完整的 axf 文件可以看出,axf 中絕大多數(shù)都是和調(diào)試相關(guān)的內(nèi)容。真正的 Bin 只是其中的一小部分。Bin 的結(jié)尾處在 axf 文件中也很容易找到,再次就不在贅述。??既然前面我們說(shuō)了,axf 文件就是 ELF 文件格式,那么我們可以使用 readelf 工具,具體查看一下axf文件。下圖是一個(gè) axf 文件的節(jié)表

714f2b44-87d6-11ed-bfe3-dac502259ad0.png

Bin文件

??bin 文件是 ARM 的可執(zhí)行文件,是最純粹的二進(jìn)制機(jī)器代碼。與 HEX 文件包括地址信息的不同,BIN 文件格式只包括了數(shù)據(jù)本身。在燒寫或下載 HEX 文件的時(shí)候,一般都不需要用戶指定地址,因?yàn)?HEX 文件內(nèi)部的信息已經(jīng)包括了地址。而燒寫 BIN 文件的時(shí)候,用戶是一定需要指定地址信息的。??ARM 的 Bin 文件就是 axf 的精華部分(掐掉ELF頭,去掉 .symtab、.debug和.symtab區(qū)里的信息)。下圖是筆者使用 Winhex 截取的 ARM 的 Bin 文件的開頭和結(jié)尾的示意圖。
7168c0d6-87d6-11ed-bfe3-dac502259ad0.png

hex 文件

??首先,hex 文件最初由 Intel 提出。在 Intel HEX 文件中,每一行是一個(gè) HEX 記錄,由十六進(jìn)制數(shù)組成的機(jī)器碼或者數(shù)據(jù)常量,Intel HEX 文件經(jīng)常被用于將程序或數(shù)據(jù)傳輸存儲(chǔ)到 ROM、EPROM,大多數(shù)編程器和模擬器使用 Intel HEX 文件。??hex 文件全部由可打印的 ASCII 字符組成。如下圖就是 ARM-MDK5.22 生成的一個(gè)hex文件(部分)
71891a2a-87d6-11ed-bfe3-dac502259ad0.png

從上圖不難看出,hex 文件就是一個(gè)個(gè)的十六進(jìn)制的字符串。實(shí)際上,一個(gè) Intel HEX 文件可以包含任意多的十六進(jìn)制記錄,每條記錄有五個(gè)域,每條記錄都由一個(gè)冒號(hào)":"打頭。一個(gè)數(shù)據(jù)記錄以一個(gè)回車和一個(gè)換行結(jié)束。其格式如下::CCAAAARR[DD...]ZZ其中:

CC:本條記錄中數(shù)據(jù)(dd)的字節(jié)數(shù)目

AAAA:本條記錄中的數(shù)據(jù)在存儲(chǔ)區(qū)中的起始地址

RR:記錄類型:

00 數(shù)據(jù)記錄 (data record)

01 文件結(jié)束記錄 (end record)

02 擴(kuò)展段地址記錄 (paragraph record)

03 擴(kuò)展線性地址記錄 (transfer address record)

DD… :數(shù)據(jù)域。表示一個(gè)字節(jié)的數(shù)據(jù),一個(gè)記錄可能有多個(gè)數(shù)據(jù)字節(jié),字節(jié)數(shù)目可以 查看ll域的說(shuō)明

ZZ:效驗(yàn)和域,表示記錄的效驗(yàn)和,計(jì)算方法是將本條記錄冒號(hào)開始的所有字母對(duì)所表示的十六進(jìn)制數(shù)字都加起來(lái)然后模除 256 得到的余數(shù)最后求出余數(shù)的補(bǔ)碼即是本效驗(yàn)字節(jié) cc。

舉例如下::10400000781A00203D420008034C0008D14B0008FC

10: 長(zhǎng)度 16

4000: 起始地址

00: 表示數(shù)據(jù)記錄

78 ~ 08: 數(shù)據(jù)

FC:校驗(yàn)和

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 文件
    +關(guān)注

    關(guān)注

    1

    文章

    561

    瀏覽量

    24671
  • Image
    +關(guān)注

    關(guān)注

    0

    文章

    32

    瀏覽量

    11870
  • 鏡像
    +關(guān)注

    關(guān)注

    0

    文章

    160

    瀏覽量

    10689
  • elf
    elf
    +關(guān)注

    關(guān)注

    0

    文章

    12

    瀏覽量

    2166

原文標(biāo)題:ELF 文件、鏡像(Image)文件、可執(zhí)行文件、對(duì)象文件詳解

文章出處:【微信號(hào):技術(shù)讓夢(mèng)想更偉大,微信公眾號(hào):技術(shù)讓夢(mèng)想更偉大】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【實(shí)用開發(fā)工具】將BAT腳本打包成exe可執(zhí)行文件

    【實(shí)用開發(fā)工具】將BAT腳本打包成exe可執(zhí)行文件
    的頭像 發(fā)表于 08-21 19:51 ?2.6w次閱讀
    【實(shí)用開發(fā)工具】將BAT腳本打包成exe<b class='flag-5'>可執(zhí)行文件</b>

    C語(yǔ)言變成可執(zhí)行文件的四大步驟

    從C語(yǔ)言變成最終的可執(zhí)行文件,需要經(jīng)過(guò)四步。
    發(fā)表于 10-18 10:37 ?5378次閱讀

    【視頻分享】如何調(diào)試可執(zhí)行文件

    在LabVIEW中,經(jīng)常發(fā)現(xiàn)可執(zhí)行文件和源代碼執(zhí)行結(jié)果有出入。本視頻講解如何調(diào)試可執(zhí)行文件。在優(yōu)酷上面看到的關(guān)于如何調(diào)試可執(zhí)行文件視頻,感覺(jué)還是挺受益的,分享給大家!
    發(fā)表于 07-20 14:46

    用MDK生成bin格式的可執(zhí)行文件

    用MDK 生成bin 文件1用MDK 生成bin 文件Embest 徐良平在RV MDK 中,默認(rèn)情況下生成*.hex 的可執(zhí)行文件,但是當(dāng)我們要生成*.bin 的可執(zhí)行文件時(shí)怎么辦呢
    發(fā)表于 08-02 10:52 ?71次下載

    基于LabVIEW的可執(zhí)行文件調(diào)用的研究與實(shí)現(xiàn)

    LabVIEW 是美國(guó)NI 公司推出的一種基于G 語(yǔ)言的虛擬儀器軟件開發(fā)工具。在LabVIEW 開發(fā)的軟件中,用戶可能需要調(diào)用.exe 可執(zhí)行文件。本文結(jié)合實(shí)例詳細(xì)介紹了三種調(diào)用方法:通過(guò)Call
    發(fā)表于 08-14 11:42 ?65次下載

    了解在Linux下可執(zhí)行文件格式

    Linux下面,目標(biāo)文件、共享對(duì)象文件、可執(zhí)行文件都是使用ELF文件格式來(lái)存儲(chǔ)的。程序經(jīng)過(guò)編譯之
    發(fā)表于 05-15 08:49 ?1904次閱讀

    Linux下可執(zhí)行文件格式

    Linux支持的可執(zhí)行文件主要有:Coff,elf,flat,類似Windows的.exeCoff文件格式? Common Object File Format,最早與uclinux
    發(fā)表于 04-02 14:46 ?1555次閱讀

    CCES創(chuàng)建可執(zhí)行文件的操作流程

    本模塊將介紹用CrossCore? Embedded Studio (CCES)創(chuàng)建可執(zhí)行文件的整個(gè)流程。涉及的主題包括使用新項(xiàng)目向?qū)?、配置系統(tǒng)和工具選項(xiàng),以及構(gòu)建過(guò)程。
    的頭像 發(fā)表于 07-11 06:06 ?3385次閱讀

    使用Java語(yǔ)言編寫戰(zhàn)機(jī)的設(shè)計(jì)報(bào)告和源代碼以及可執(zhí)行文件

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用Java語(yǔ)言編寫戰(zhàn)機(jī)的設(shè)計(jì)報(bào)告和源代碼以及可執(zhí)行文件免費(fèi)下載導(dǎo)入eclipse即可運(yùn)行。
    發(fā)表于 11-05 08:00 ?0次下載
    使用Java語(yǔ)言編寫戰(zhàn)機(jī)的設(shè)計(jì)報(bào)告和源代碼以及<b class='flag-5'>可執(zhí)行文件</b>

    C語(yǔ)言的源代碼文件和目標(biāo)文件可執(zhí)行文件的詳細(xì)介紹

    1、源代碼文件 存放程序代碼的文件,即我們編輯代碼的文件,稱為源代碼文件。 C語(yǔ)言源程序文件的擴(kuò)展名為“.c”。源代碼
    的頭像 發(fā)表于 02-18 11:52 ?8476次閱讀

    ELF相比Hex、Bin文件格式有哪些不同?

    素材來(lái)源:綜合CSDN 編輯整理:strongerHuang 關(guān)于計(jì)算機(jī)的文件有很多種,今天分享一種用于二進(jìn)制文件、可執(zhí)行文件、目標(biāo)代碼、共享庫(kù)和核心轉(zhuǎn)儲(chǔ)格式文件。 一、
    的頭像 發(fā)表于 10-16 09:54 ?5478次閱讀
    <b class='flag-5'>ELF</b>相比Hex、Bin<b class='flag-5'>文件</b>格式有哪些不同?

    用于讀取ELF格式文件的詳細(xì)信息的命令:readelf命令

    1.功能簡(jiǎn)介 readelf 用于讀取 ELF(Executable and Linkable Format)格式文件的詳細(xì)信息,包括目標(biāo)文件可執(zhí)行文件、共享目標(biāo)
    的頭像 發(fā)表于 02-09 18:12 ?4995次閱讀
    用于讀取<b class='flag-5'>ELF</b>格式<b class='flag-5'>文件</b>的詳細(xì)信息的命令:readelf命令

    【Python】如何將Python腳本打包成exe可執(zhí)行文件

    【Python實(shí)用技巧】如何將Python腳本打包成exe可執(zhí)行文件?
    的頭像 發(fā)表于 08-18 12:40 ?1.8w次閱讀
    【Python】如何將Python腳本打包成exe<b class='flag-5'>可執(zhí)行文件</b>

    單獨(dú)下載可執(zhí)行文件到MM32F5微控制器

    使用Keil MDK或者IAR等使用圖形界面的開發(fā)環(huán)境,可以在圖形界面環(huán)境下編譯源碼工程,并下載編譯生成的可執(zhí)行文件到目標(biāo)微控制器中。但若使用ARMGCC等命令行工具鏈,需要額外的下載工具,才能將編譯生成的可執(zhí)行文件下載到目標(biāo)微控制器中。
    的頭像 發(fā)表于 02-17 09:32 ?827次閱讀

    labview怎么生成可執(zhí)行文件

    生成可執(zhí)行文件(EXE)是LabVIEW程序開發(fā)中的一個(gè)重要步驟,它允許用戶將LabVIEW項(xiàng)目打包成一個(gè)獨(dú)立的應(yīng)用程序,便于在沒(méi)有安裝LabVIEW的計(jì)算機(jī)上運(yùn)行。 1. 準(zhǔn)備工作 在開始生成
    的頭像 發(fā)表于 09-04 17:07 ?668次閱讀