Java解析ELF檔案:ELF檔案格式規範

柴月和岐月發表於2018-01-07

1.簡介

UNIX類作業系統中普遍採用目標檔案格式ELF(Executable and Linkable Format),來實現二進位制級軟體構件的靜態、動態組裝技術。
可執行連結格式(Executable and Linking Format)最初是由UNIX系統實驗室(UNIX System Laboratories,USL)開發併發布的,作為應用程式二進位制介面(Application Binary Interface,ABI)的一部分。工具介面標準(Tool Interface Standards,TIS)委員會將還在發展的ELF標準選作為一種可移植的目標檔案格式,可以在32位Intel體系結構上的很多作業系統中使用[1,2]。 
ELF標準的目的是為軟體開發人員提供一組二進位制介面定義,這些介面可以延伸到多種操作環境,從而減少重新編碼、重新編譯程式的需要。介面的內容包括目標模組格式、可執行檔案格式以及除錯記錄資訊與格式等。 

2.檔案格式

2.1簡介

目標檔案有三種型別: 
可重定位檔案(Relocatable File):包含適合於與其他目標檔案連結來建立可執行檔案或者共享目標檔案的程式碼和資料。  
可執行檔案(Executable File):包含適合於執行的一個程式,此檔案規定了 exec() 如何建立一個程式的程式映像。  
共享目標檔案(Shared Object File):包含可在兩種上下文中連結的程式碼和資料。首先連結編輯器可以將它和其它可重定位檔案和共享目標檔案一起處理,生成另外一個目標檔案。其次,動態連結器(Dynamic Linker)可能將它與某
個可執行檔案以及其它共享目標一起組合,建立程式映像。 

以上目標檔案全部是程式的二進位制表示,目的是直接在某種處理器上直接執行。

2.2檔案格式

目標檔案既要參與程式連結又要參與程式執行。出於方便性和效率考慮,目標檔案格式提供了兩種並行檢視,分別反映了這些活動的不同需求。

檔案開始處是一個 ELF 頭部(ELF Header),用來描述整個檔案的組織。節區部分包含連結檢視的大量資訊:指令、資料、符號表、重定位資訊等等。 
程式頭部表(Program Header Table),如果存在的話,告訴系統如何建立程式映像。用來構造程式映像的目標檔案必須具有程式頭部表,可重定位檔案不需要這個表。 
節區頭部表(Section Heade Table)包含了描述檔案節區的資訊,每個節區在表中都有一項,每一項給出諸如節區名稱、節區大小這類資訊。用於連結的目標檔案必須包含節區頭部表,其他目標檔案可以有,也可以沒有這個表。 

注意:儘管圖中顯示的各個組成部分是有順序的,實際上除了 ELF 頭部表以外,其他節區和段都沒有規定的順序(但是一般來講,除開自己新增的節區情況外,程式頭部表位於ELF頭部後面,節區頭部表位於最末端。同時執行檢視的段其實就是連結檢視不同的節區合起來而已,這一點需要注意下)

2.3讀取順序


1.首先讀取檔案頭部,檔案頭部會提供程式頭部表的偏移位置和表內的表項數量、節區頭部表的偏移位置和表內的表項數量
連結檢視:
2.讀取節區頭部表,獲取每個節區的偏移量
執行檢視:
3.讀取程式頭部表,獲取每個段區的偏移量
下圖源自非蟲大大的圖,可以用來加深理解:

3.使用010Editor的模組功能檢視ELF檔案

功能超強大的國外軟體十六進位制編輯器


安裝後,進入模板庫安裝介面:模板->模板庫,選擇ELF檔案



開啟一個SO檔案,點選執行,模板

則會很方便的顯示上面說的檔案頭部、程式頭部表、節區頭部表的大小和偏移位置,其中最下面的dynamic_symbol_table也是節區的一種型別,只是很重要所以列了出來,包含的是用來定位、重定位程式中符號定義和引用的資訊。


本篇只介紹了各個區域的大致描述和檔案格式,對於大部分程式設計師來講只需要瞭解格式就行了,至於每個區域的詳細內容則內容太多不貼出來了,想了解更多則請移步ELF檔案格式分析

4.參考

這篇部落格裡介紹了使用readelf命令檢視ELF檔案的用法(NDK裡也提供了不同平臺下readelf功能的命令,在ndk\toolchains目錄下,搜尋下readelf就出來了),和作者自己寫的java和C++解析類,建議去看看

相關文章