gcc編譯器讀取源程式檔案(.c檔案)並把它翻譯成乙個可執行目標檔案,翻譯過程中就包括了鏈結。
在現代系統中,鏈結是由叫做鏈結器的程式自動執行的。
鏈結是將各種**和資料片段收集並組合成為乙個單一檔案的過程,這個檔案可被載入到記憶體並執行。也就是將所有的檔案彙總為乙個檔案。
·靜態聯結器以一組可重定位目標檔案和命令列引數作為輸入,生成乙個完全鏈結的,可以載入和執行的可執行目標檔案作為輸出。
·可重定位目標檔案由各種不同的**和資料節組成,每一節都是乙個連續的位元組序列
·為了構造可執行檔案,鏈結器必須完成兩個主要任務
1、符號解析:目標檔案定義和引用符號,每個符號對應於乙個函式、乙個全域性變數或者乙個靜態變數。其目的是將每個符號引用正好和乙個符號定義關聯起來
我們來看一下乙個典型的elf可重定位目標檔案的格式
elf頭
以乙個16個位元組的序列開始,這個序列描述了生成該檔案的系統的字的大小和位元組順序。elf頭剩下的部分包含幫助鏈結器語法分析和解釋目標檔案的資訊。其中包括elf頭的大小,目標檔案的型別,及其型別,節頭部表的檔案偏移,節頭部表中條目的大小和數量。
.text節
已編譯程式的機器**(比如一些函式)
.rodata
唯讀資料,比如printf語句中的格式串和開關語句跳轉表
.data
已初始化的全域性變數和靜態c變數(區域性c變數在執行時被儲存在棧中,不出現在data和bss中)
.bss
未初始化的全域性和靜態c變數,以及所有被初始化為0的全域性或靜態變數
.symtab
乙個符號表,它存放在程式中定義和應用的函式和全域性變數的資訊(不包含區域性變數條目)
.rel.text
.text節的重定位資訊,用於重新修改**段的指令中的位址資訊
.rel.data
.data節的重定位資訊,用於對被模組使用或定義的全域性變數進行重定位的資訊
.debug
乙個除錯符號表(gcc -g)
.line
原始c源程式中的行號和.text節中機器指令之間的對映,通過-g呼叫
.strtab
乙個字串表。其中內容包括.symtab和.debug節中的符號表,以及頭節部中的節名字。
節頭表每個節的節名,偏移和大小
接下來,我們用一段簡單的**演示一下
int sum(int *a, int n);
int array[2] = ;
int main()
先只鏈結,生成可重定位目標檔案
調出elf頭的內容
根據節頭部表資訊看可重定位檔案。根據每個節的偏移量和大小畫出整個可重定位檔案。
每個節放什麼變數詳細去看前面的**,這裡以乙個程式舉例
·.bss節中不放入初始值,只要說明將來執行是占用幾個位元組即可,因此,.bss實際上不占用磁碟空間,提高了磁碟空間利用率
·有時.common和.bss會交替出現,這裡分辨一下
.common 未初始化的全域性變數
.bss 未初始化的靜態變數,以及初始化為0的全域性或靜態變數
ELF格式可重定位目標檔案
乙個典型的elf格式的可重定位目標檔案以elf頭開始,還包括 區 資料區,以下是具體形式 elf頭 text 已編譯程式的機器 rodata 唯讀資料 data 已初始化的全域性和靜態c變數 bss 未初始化的全域性和靜態c變數,初始化為0的全域性或靜態變數 symtab 符號表 rel.text ...
ELF可重定位目標檔案格式
現在我們用乙個簡單的c語言程式addvec.c做示範,如下 int addvec 0p void addvec int x,int y,int z,int z int i addvec for i 0 i開啟終端,輸入指令 不同節的位置和大小是由節頭部表的描述的,其中目標檔案中每個節都有乙個固定大小...
04可重定位目標檔案ELF檔案解析
目錄 一 可重定位目標檔案的特點 二 可重定位目標檔案的格式 可被鏈結 合併 生成可執行檔案或共享目標檔案 靜態鏈結庫檔案由若干個可重定位目標檔案組成 包含 資料 已初始化全域性變數和區域性靜態變數.data和未初始化的全域性變數和區域性靜態變數.bss 包含重定位資訊 指出哪些符號引用處需要重定位...