本文接著《linux系統elf檔案二進位制格式分析(一)》繼續分析elf檔案格式
二、程式頭表
程式頭表由幾個項組成,結構類似於陣列,項數記錄在elf檔案頭的e_phnum欄位,各項有統一的結構,每個項都描述了乙個段的資訊。
1. 資料結構
typedef struct elf32_phdrelf32_phdr;
(1) p_type表示當前描述的段的種類。常見有以下常數。
(2) p_offset給出了該段在二進位制檔案中的偏移量,單位為位元組。#define pt_null 0 //空段
#define pt_load 1 //可裝載段
#define pt_dynamic 2 //表示該段包含了用於動態聯結器的資訊
#define pt_interp 3 //表示當前段指定了用於動態連線的程式直譯器,通常是ld-linux.so
#define pt_note 4 //該段包含有專有的編譯器資訊
#define pt_shlib 5 //該段包含有共享庫
(3) p_vaddr給出了該段需要對映到程序虛擬位址空間中的位置。
(4) p_paddr在只支援物理定址,不支援虛擬定址的系統當中才使用。
(5) p_filesz給出了該段在二進位制檔案當中的長度,單位為位元組。
(6) p_memsz給出了段在虛擬位址空間當中的長度,單位為位元組。與p_filesz不等時會通過截斷資料或者以0填充的方式處理。
(7) p_flags儲存了標誌資訊,定義了該段的訪問許可權。有如下值
(8) p_align指定了段在記憶體和二進位制檔案當中的對齊方式,即p_offset和p_vaddr必須是p_align的整數倍。#define pf_r 0x4 //該段可讀
#define pf_w 0x2 //該段可寫
#define pf_x 0x1 //該段可執行
2. 可執行檔案中程式頭資訊(目標檔案中沒有)
由圖可知,該程式共有9個程式頭表,因此就有9個段。各段的資訊用**的形式表現了出來。另外需要注意的是下半部分所示內容:節到段的對映。該表中展示了每個段所包含的節的名稱,可以看到,乙個段包含了乙個到多個的節,而節頭表的作用則是記錄每個節的資訊。
三、節頭表
1. 資料結構
typedef struct elf32_shdr;
(1) sh_name指定了節的名稱,該值是在字串表.shstrtab中的乙個索引。將在後面介紹字串表時介紹。
(2) sh_type指定了節的型別,常用值如下:
(3) sh_flags有一下標誌:#define sht_null 0 //表示該節不實用,忽略
#define sht_progbits 1 //表示儲存了程式相關資訊,格式不定義的,需要程式解釋
#define sht_symtab 2 //表示儲存了符號表(接下來會介紹)
#define sht_strtab 3 //表示包含字串的表
#define sht_rela 4 //表示重定位資訊(後面介紹)
#define sht_hash 5 //儲存了乙個雜湊表
#define sht_dynamic 6 //儲存了關於動態鏈結的資訊
#define sht_note 7
#define sht_nobits 8
#define sht_rel 9 //表示重定位資訊(後面介紹)
#define sht_shlib 10
#define sht_dynsym 11 //同樣表示儲存了符號表(與sht_symtab的不同在後面介紹)
#define sht_num 12
(4) sh_addr指定節對映到虛擬位址空間中的位置#define shf_write 0x1 //表示可寫
#define shf_alloc 0x2 //表示可分配虛擬記憶體
#define shf_execinstr 0x4 //表示**可執行
(5) sh_offset指定節在檔案中位置的偏移量
(6) 因節的型別不同,sh_link和sh_info會有不同的解釋
當節為sht_dynamic型別時,sh_link指向節資料所用的字串表,此時sh_info無效。
當節為sht_hash型別時,sh_link指向所雜湊的符號表,此時sh_info無效。
當節為sht_rela或sht_rel型別時,sh_link指向相關的符號表,此時sh_info儲存節頭表中的索引,表示對哪個節進行重定位。
當節為sht_dynsym或sht_symtab型別時,sh_link指定了用作符號表的字串表,sh_info表示符號表中緊隨最後乙個區域性符號之後的索引位置。
(7) sh_addralign指定了節在記憶體中對齊係數
(8) sh_entsize指定了節中各資料項的長度,要求這些資料項長度都相同
2. 目標檔案中節資訊
從圖中可以看出,目標檔案各節的sh_addr值是沒有意義的,因為目標檔案不能載入到記憶體當中建立程序。
每個節都有自己的型別,定義了節中資料的含義。其中最重要的包括progbits(程式必須解釋的資訊,如二進位制**)、symtab(符號表)、rel(重定位資訊)和strtab(與elf相關的字串)。
不同的elf檔案可以有不同的節,但linux標準要求某些節必須存在,如總有乙個.text節來儲存二進位制**,.rel.text儲存text節中重定位資訊。
各個節的標誌含義如圖中最下方說明所示,表明了該節擁有的許可權。
3. 可執行檔案中節資訊
與目標檔案相比,可執行檔案節的數量明顯增加,這裡只介紹最主要的幾個。
.interp儲存了直譯器的檔名,是乙個ascii字串。
.data儲存了初始化過的資料,程式可修改這些資料。
.rodata儲存了唯讀資料,可讀但不可修改。
.init和.finit分別儲存程序初始化**和結束所用**。這兩個節是編譯器自己新增的,程式設計師一般不關心。
.hash是乙個雜湊表,用於對符號快速訪問的實現。
可執行檔案當中sh_addr有相應的數值,表示檔案載入到虛擬記憶體時,各個節必須載入到其sh_addr指定的虛擬記憶體的位置。對linux程式來說,應用程式各節通常使用0x08000000以上區域。
接下來《linux系統elf檔案二進位制格式分析(三)》將會介紹符號表、字串表和重定位項。
Linux系統ELF檔案二進位制格式分析 四
六 重定位項 重定位是將elf檔案中未定義的符號關聯到有效位置的過程,特別是目標檔案中這一項尤為重要。本例中引用了c語言庫函式printf和exit,鏈結時必須替換為該程序的虛擬位址空間中機器 所在位置。每個elf中,都有專門的型別為rel的節包含重定位項,標識了需要進行重定位的位置。每一項都是用相...
ELF二進位制目標檔案詳解
以下內容為 找出所有引用的外部模組並鏈結起來,這些外部模組或函式庫一般來自於開發者,作業系統和c執行庫。鏈結程式取出這些函式庫,修訂指標位置 重定位 並交叉引用模組中的符號解析,最終產生乙個可執行模組。符號可以是全域性的也可以是區域性的。全域性符號可以在模組內部定義,或由另一模組外部引用。靜態庫是在...
readelf的elf 二進位制檔案格式分析工具小記
readeklf工具和 objdump 命令提供的功能類似,但是它顯示的資訊更為具體,並且它不依賴 bfd 庫 bfd 庫是乙個 gnu 專案,它的目標就是希望通過一種統一的介面來處理不同的目標檔案 elf 檔案型別 elf executable and linking format 是一種物件檔案...