詳解鏈結下的ELF可重定位目標檔案結構

2021-09-27 12:01:28 字數 2093 閱讀 5359

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 包含重定位資訊 指出哪些符號引用處需要重定位...