目標檔案有三種形式:
1. 可重定位目標檔案
2. 可執行目標檔案
3. 共享目標檔案
編譯器和彙編器生成可重定位目標檔案/共享目標檔案,聯結器生成可執行目標檔案。
在這裡我們首先介紹可重定位目標檔案。
可重定位目標檔案:包含二進位制**和資料,可以在編譯時與其他可重定位目標檔案合併起來,建立乙個可執行目標檔案。
可重定目標檔案格式:
注意:
bss段 在目標檔案中不佔實際的空間,它僅僅只是乙個佔位符。目標檔案格式區分初始化和未初始化變數是為了效率,在目標檔案中,未初始化變數不需要佔據任何實際的磁碟空間。
.symatb段 不包含區域性變數的條目。
符號和符號表
符號:
每個可重定位目標模組 m,都有乙個符號表,它包含 m 所定義和引用的符號的資訊。有三種不同的符號:
1. 由 m 定義並能被其他模組引用的全域性符號。(非靜態的 c函式以及 不帶 c static 屬性的全域性變數)
2. 由其他模組定義並能被模組 m 引用的全域性符號。(外部符號,對應於定義在其他模組中的 c 函式和變數)
3. 只能被模組 m 定義和引用的本地符號。(帶 static 屬性的 c函式和全域性變數)
符號表:
符號表由彙編器構造,輸出到組合語言 .s 檔案中的符號。
.symtab 段中包含 elf 符號表,這張符號表包含乙個條目的陣列。
elf 符號表條目:
typedef strcut;
在這裡我們給出乙個簡單函式
#include
int buf[2] = ;
int main( void )
我們通過 gcc 編譯器生成對應的 .o 檔案,然後使用 readelf -ws 來檢視該 .o檔案的符號表。
開始的 8個條目可以暫時忽略,它們是聯結器內部使用的本地符號。
其中 ndx = 1 表示 .text段,ndx = 3 表示 .data 段。
從第九個條目開始,我們可以看到乙個關於全域性符號 buf 定義的條目,它是乙個位於.data 段中偏移量為 0 處的大小為 8 個位元組的目標。
其後跟隨著的是全域性符號 main 的定義,是位於 .text段中偏移為 0 處的 21 位元組函式。
最後乙個條目來自對外部符號 swap 的引用。並且是未定義的。
符號解析:
鏈結器解析符號是將每個引用與它輸入的可重定位目標檔案的符號表中的乙個確定的符號定義聯絡起來。
編譯器只允許每個模組中每個本地符號只有乙個定義,編譯器還確保靜態本地變數,它們也會有本地鏈結器符號,擁有唯一的名字。
當編譯器遇到乙個不是在當前模組中定義的符號時,它會假設該符號是在其他某個模組中定義的,生成乙個聯結器符號表條目,並把它交給鏈結器處理。如果鏈結器在它的任何輸出模組中都找不到這個被引用的符號,它就輸出一條錯誤資訊並終止。
可重定位目標檔案
可重定位目標檔案經由源程式預處理,編譯,彙編之後得到的檔案。其中包括不可讀的二進位制 擴充套件名為.o。現有兩個模組的 main.c int sum int a,int n int array 2 int main sum.c int sum int a,int n return s 一.在linu...
7 4 可重定位目標檔案
下圖展示了乙個典型的elf可重定位目標檔案的格式。elf頭 elf header 以乙個16位元組的序列開始,這個序列描述了生成該檔案的系統的字的大小和位元組順序,elf頭剩下的部分包含幫助鏈結器語法分析和解釋目標檔案的資訊。其中包括elf頭的大小,目標檔案的型別 如可重定位,可執行性,或者共享的 ...
可重定位目標檔案解析
程式 如下 最簡單的hello.c include intmain 我們首先生成可重定位目標檔案 gcc c hello.c這是有關可重定位目標檔案的結構圖 從mooc ppt上所截 計算機系統基礎 一 第十周第三講 讓我們看一下elf的檔案大體的資訊 選取幾個解釋一下 type rel 可重定位檔...