Linux系統ELF檔案二進位制格式分析 二

2021-06-29 00:43:04 字數 3584 閱讀 6608

本文接著《linux系統elf檔案二進位制格式分析(一)》繼續分析elf檔案格式

二、程式頭表

程式頭表由幾個項組成,結構類似於陣列,項數記錄在elf檔案頭的e_phnum欄位,各項有統一的結構,每個項都描述了乙個段的資訊。

1.      資料結構

typedef struct elf32_phdrelf32_phdr;
(1)    p_type表示當前描述的段的種類。常見有以下常數。

#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 //該段包含有共享庫

(2)    p_offset給出了該段在二進位制檔案中的偏移量,單位為位元組。

(3)    p_vaddr給出了該段需要對映到程序虛擬位址空間中的位置。

(4)    p_paddr在只支援物理定址,不支援虛擬定址的系統當中才使用。

(5)    p_filesz給出了該段在二進位制檔案當中的長度,單位為位元組。

(6)    p_memsz給出了段在虛擬位址空間當中的長度,單位為位元組。與p_filesz不等時會通過截斷資料或者以0填充的方式處理。

(7)    p_flags儲存了標誌資訊,定義了該段的訪問許可權。有如下值

#define pf_r		0x4     //該段可讀

#define pf_w 0x2 //該段可寫

#define pf_x 0x1 //該段可執行

(8)    p_align指定了段在記憶體和二進位制檔案當中的對齊方式,即p_offset和p_vaddr必須是p_align的整數倍。

2.      可執行檔案中程式頭資訊(目標檔案中沒有)

由圖可知,該程式共有9個程式頭表,因此就有9個段。各段的資訊用**的形式表現了出來。另外需要注意的是下半部分所示內容:節到段的對映。該表中展示了每個段所包含的節的名稱,可以看到,乙個段包含了乙個到多個的節,而節頭表的作用則是記錄每個節的資訊。

三、節頭表

1.      資料結構

typedef struct  elf32_shdr;
(1)    sh_name指定了節的名稱,該值是在字串表.shstrtab中的乙個索引。將在後面介紹字串表時介紹。

(2)    sh_type指定了節的型別,常用值如下:

#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

(3)    sh_flags有一下標誌:

#define shf_write	0x1  //表示可寫

#define shf_alloc 0x2 //表示可分配虛擬記憶體

#define shf_execinstr 0x4 //表示**可執行

(4)    sh_addr指定節對映到虛擬位址空間中的位置

(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 是一種物件檔案...