elf檔案格式(Linux中物件檔案)

2021-07-02 13:05:48 字數 4559 閱讀 7185

elf(executable and linking format)是一種物件檔案的格式,用於定義不同型別的物件檔案

(object files)

中都放了什麼東西、以及都以什麼樣的格式去放這些東西。它自最早在 

system v 

系統上出現後,被 

xnix 

世界所廣泛接受,作為預設的二進位制檔案格式來使用。可以說,

elf是構成眾多

xnix

系統的基礎之一,所以作為嵌入式

linux

系統乃至核心驅動程式開發人員,你最好熟悉並掌握它。

首先,你需要知道的是所謂物件檔案(object files)

有三個種類:

1) 可重定位的物件檔案

(relocatable file)

這是由彙編器彙編生成的 .o 

檔案。後面的鏈結器

(link editor)

拿乙個或一些 

relocatable object files 

作為輸入,經鏈結處理後,生成乙個可執行的物件檔案 

(executable file) 

或者乙個可被共享的物件檔案

(shared object file)

。我們可以使用 

ar 工具將眾多的 

.o relocatable object files 

歸檔(archive)

成 .a 

靜態庫檔案。如何產生 

relocatable file

julwiki

。另外,可以預先告訴大家的是我們的核心可載入模組 

.ko 

檔案也是 

relocatable object file。

2) 可執行的物件檔案

(executable file)

這我們見的多了。文字編輯器vi

、調式用的工具

gdb***

歌曲的軟體

mplayer

等等都是

executable object file

。你應該已經知道,在我們的 

linux 

系統裡面,存在兩種可執行的東西。除了這裡說的 

executable object file

,另外一種就是可執行的指令碼(如

shell指令碼)

。注意這些指令碼不是 

executable object file

,它們只是文字檔案,但是執行這些指令碼所用的直譯器就是 

executable object file

,比如 

bash shell 

程式。

3) 可被共享的物件檔案

(shared object file)

這些就是所謂的動態庫檔案,也即 .so 

檔案。如果拿前面的靜態庫來生成可執行程式,那每個生成的可執行程式中都會有乙份庫**的拷貝。如果在磁碟中儲存這些可執行程式,那就會占用額外的磁碟空間;另外如果拿它們放到

linux

系統上一起執行,也會浪費掉寶貴的物理記憶體。如果將靜態庫換成動態庫,那麼這些問題都不會出現。動態庫在發揮作用的過程中,必須經過兩個步驟:

a) 鏈結編輯器

(link editor)

拿它和其他

relocatable object file

以及其他

shared object file

作為輸入,經鏈結處理後,生存另外的 

shared object file 

或者 executable file。

b) 在執行時,動態鏈結器

(dynamic linker)

拿它和乙個

executable file

以及另外一些 

shared object file 

來一起處理,在

linux

系統裡面建立乙個程序映像。

可以說,sections 

是在elf

檔案裡頭,用以裝載內容資料的最小容器。在

elf檔案裡面,每乙個 

sections 

內都裝載了性質屬性都一樣的內容,比方:

1) .text section 裡裝載了可執行**;

2) .data section 裡面裝載了被初始化的資料;

3) .bss section 裡面裝載了未被初始化的資料;

4) 以 

.rec 

打頭的 

sections 

裡面裝載了重定位條目;

5) .symtab 或者 

.dynsym section 

裡面裝載了符號資訊;

6) .strtab 或者 

.dynstr section 

裡面裝載了字串資訊;

7) 其他還有為滿足不同目的所設定的

section

,比方滿足除錯的目的、滿足動態鏈結與載入的目的等等。

這個結果顯示了 sum.o 

中包含的所有9個

sections

。因為sum.o

僅僅是參與

link editor

鏈結的可重定位檔案,而不參與最後程序映像的構建,所以

addr(sh_addr)為0

。後面你會看到可執行檔案以及動態庫檔案中大部分

sections

的這一字段都是有某些取值的。

off(sh_offset)

表示了該

section

離開檔案頭部位置的距離。

size(sh_size)

表示section

的位元組大小。

es(sh_entsize)

只對某些形式的

sections 

有意義。比方符號表 

.symtab section

,其內部包含了乙個**,**的每乙個條目都是特定長度的,那這裡的這個欄位就表示條目的長度10。

al(sh_addralign)

是位址對齊要求。另外剩下的兩列lk和

inf,對應著條目結構中的字段

sh_link

和字段sh_info

。它們中記錄的是

section head table 

中的條目索引,這就意味著,從這兩個字段出發,可以找到對應的另外兩個 

section

,其具體的含**釋依據不同種類的 

section 

而不同,後面會介紹。

注意上面結果中的 *** 

,表示的是對應

section

的相關標誌。比方

.text section 

裡面儲存的是**,所以就是唯讀的

(x);

.data

和.bss

裡面存放的都是可寫的

(w)資料

(非在堆疊中定義的資料

),只不過前者存的是初始化過的資料,比方程式中定義的賦過初值的全域性變數等;而後者裡面儲存的是未經過初始化的資料。因為未經過初始化就意味著不確定這些資料剛開始的時候會有些什麼樣的值,所以針對物件檔案來說,它就沒必要為了儲存這些資料而在檔案內多留出一塊空間,因此

.bss section

的大小總是為

0。後面會看到,當可執行程式被執行的時候,動態聯結器會在記憶體中開闢一定大小的空間來存放這些未初始化的資料,裡面的記憶體單元都被初始化成

0。可執行程式檔案中雖然沒有長度非0的 

.bss section

,但卻記錄有在程式執行時,需要開闢多大的空間來容納這些未初始化的資料。

.strtab section 中儲存著的都是以字元 為分割符的字串,這些字串所表示的內容,通常是程式中定義的函式名稱、所定義過的變數名稱等等。。。當物件檔案中其他地方需要和乙個這樣的字串相關聯的時候,往往會在對應的地方儲存 .strtab section 

中的索引值。比方下面將要介紹的符號表 

.symtab section 

中,有乙個條目是用來描述符號 

gv_inited 

的,那麼在該條目中就會有乙個字段

(st_name)

記錄著字串 

gv_inited 

在 .strtab section 

中的索引 

7 。 

.shstrtab 

也是字串表,只不過其中儲存的是 

section 

的名字,而非所函式或者變數的名稱。

字串表在真正鏈結和生成程序映像過程中是不需要使用的,但是其對我們除錯程式來說就特別有幫助,因為我們人看起來最舒服的還是自然形式的字串,而非像天書一樣的數字符號。前面使用objdump

來反彙編 

.text section 

的時候,之所以能看到定義了函式 

sum_func 

,那也是因為存在這個字串表的原因。當然起關鍵作用的,還是符號表 

.symtab section 

在其中作為中介,下面我們就來看看符號表。

ELF檔案格式

在介紹elf格式之前,先簡單說明一下可執行檔案的生成流程 1 編寫c原始檔,或彙編原始檔 2 準備共享庫格式的目標檔案 shared object file 如數學庫 標準庫 2 用編譯器 compiler 將c編譯成可重定位格式的目標檔案 relocatable object file 用彙編器 ...

ELF檔案格式

1.目標檔案 編譯器和彙編器生成可重定位目標檔案 包括共享目標檔案 鏈結器生成可執行目標檔案。2.可重定位目標檔案和可執行目標檔案的格式 可重定位目標檔案格式 可執行目標檔案格式 3.下面我們開始分析上面 而對於未被初始化的全域性變數和靜態區域性變數,編譯的時候並未被分配空間,而是僅僅在.bss段中...

ELF檔案格式

elf指executable and linking format,不僅包含可執行檔案,也包含庫檔案,包括靜態庫和動態庫。準備的說,也就是三種 這不廢話嗎 可執行檔案 靜態鏈結庫 動態鏈結庫 要觀察elf的具體資訊,可以用以下幾個工具 nm lists symbols from object fil...