前言
在看uboot編譯過程時發現最終生成u-boot.bin檔案時生成了一個ELF格式的中間檔案u-boot,後來對ELF檔案了解了一下後發現平時用的對象檔案、可執行檔案和庫檔案都是ELF格式的。考慮到平時一直在使用這些檔案卻對他們知之甚少,是以從這裡開始系統學習一下ELF檔案格式。
UNIX/LINUX 平台下三種主要的可執行檔案格式:a.out(assembler and link editor output 彙編器和連結編輯器的輸出)、COFF(Common Object File Format 通用對象檔案格式)、ELF(Executable and Linking Format 可執行和連結格式)
關于 ELF 格式
ELF(Executable and Linking Format),即“可執行可連接配接格式”。ELF 檔案格式規範由 TIS(Tool Interface Standards – 工具接口标準)委員會制定,最初由 UNIX系統實驗室(UNIX System Laboratories – USL)做為應用程式二進制接口(Application Binary Interface - ABI)的一部分而制定和釋出。
ELF 的最大特點在于它有比較廣泛的适用性,通用的二進制接口定義使之可以移植到多種不同的操作環境上。這樣,不需要為每一種作業系統都定義一套不同的接口,是以減少了軟體的重複編碼與編譯,加強了軟體的可移植性。
這種接口包括目标标志格式、可執行檔案格式,以及調試資訊的格式。
ELF(v1.2)規範把 ELF 格式分為了三個層次。第一層是基本的部分,即格式中通用的部分,這部分在各種處理器架構和作業系統上都是相同的;第二層是處理器的擴充部分,這部分會因處理器架構的不同而不同;第三層是作業系統的擴充部分,這部分内容在不同的作業系統下面也可能是不同的。
ELF 檔案的格式
ELF檔案是由彙編器(assembler)和連接配接編輯器(link editor)生成的,它有三種類型:
- 可重定位檔案(Relocatable file):用于與其它目标檔案進行連接配接以建構可執行檔案或動态連結庫。可重定位檔案就是常說的目标檔案(.o檔案),之是以稱其為“可重定位”,是因為在這些檔案中,如果引用到其它目标檔案或庫檔案中定義的符号(變量或者函數)的話,隻是給出一個名字,這裡還并不知道這個符号在哪裡,其具體的位址是什麼。需要在連接配接的過程中,把對這些外部符号的引用重新定位到其真正定義的位置上,是以稱目标檔案為“可重定位”或者“待重定位”的。
- 可執行件(Executable file):經過連接配接的,可以執行的程式檔案。
- 可被共享的目标檔案(Shared object file):即動态連接配接庫檔案。它在以下兩種情況下被使用:第一,在連接配接過程中與其它動态連結庫或可重定位檔案一起建構新的目标檔案;第二,在可執行檔案被加載的過程中,被動态連結到新的程序中,成為運作代碼的一部分。
- 核心轉儲檔案(Core Dump):核心轉儲檔案是程序終止時記憶體映像的一個檔案。core檔案更詳細内容參見man 5 core
如前所述,ELF檔案的作用有兩個,一是用于建構程式,建構動态連結庫或都可執行程式,主要展現在連接配接的過程;二是用于運作程式。在這兩種情況下,對于同一個目标檔案,當它分别被用于連接配接和用于執行的時候,其特性是不一樣的,所關注的内容也不一樣。

ELF 檔案頭 (ELF header):位于檔案的最開始處,包含有整個檔案的結構資訊。
節 (section):是專用于連接配接過程而言的,在每個“節”中包含有指令資料、符号資料、重定位資料等等。
程式頭表 (program header table):在運作過程中是必須的,在連接配接過程中是可選的,因為它的作用是告訴系統如何建立程序的鏡像。
節頭表 (section header table):包含有檔案中所有“節”的資訊。在連接配接視圖中,“節頭表”是必須存在的,檔案裡的每一個“節”都需要在“節頭表”中有一個對應的注冊項,這個注冊項描述了節的名字、大小等等。
在上圖中,程式頭表緊跟在 ELF 檔案頭之後,節頭表緊跟在節資訊之後,但在實際的檔案中,這個順序并不是固定的。在 ELF 檔案的各個組成部分中,隻有ELF 檔案頭的位置是固定的,其它内容的位置全都可變。
下一篇文章細說ELF檔案的檔案頭。