Linux鏈結 目標檔案格式

2021-10-24 13:50:31 字數 2068 閱讀 3977

將各種**段和資料段收集組合成為乙個單一檔案的過程。
鏈結器的出現使得構建大型軟體系統成為可能,因為它使得各個模組可以單獨完成編譯。當需要改進模組時,單獨的修改相應的模組並編譯,通過鏈結器重新鏈結生成新版本的軟體系統。

sum.cpp中定義乙個函式
int sum(int a,int b)

main.cpp中宣告並使用
int sum(int,int);

int main()

編譯系統通常包含預處理器、編譯器、彙編器、鏈結器。通過這些不同部分完成程式從源**到最終可執行程式的過程。

gnu編譯系統對上述程式的過程為:

g++ main.cpp sum.cpp -o prog
①符號解析:symbol resolution 目標檔案中定義和引用符號。每個符號可能對應於乙個函式、乙個全域性變數、或者乙個靜態變數(區域性變數在執行時棧中建立) 符號解析就是將符號引用與符號定義關聯起來。

②重定位:relocation 編譯器和彙編器生成的位址是從0開始的邏輯位址。鏈結器通過把每個符號定義與記憶體中乙個位置關聯起來,從而重定位這些部分。具體做法是使用彙編器產生的重定位條目資訊執行重定位。

目標檔案存在三種類別:

【目標檔案格式】

目標檔案是對程式二進位制**和資料的組織,貝爾實驗室第乙個unix系統使用a.out格式,windows使用可移植可執行的pe格式(如最常見的可執行程式.exe格式) 而linux中使用的是elf (executable and linkable format)格式。

目標檔案通常包含以下這些節:

.text

程式的機器**

.rodata

read only data 唯讀資料,如printf 中格式串

.data

已經初始化的全域性或靜態變數(區域性變數執行期建立在棧中)

.bss

未初始化的全域性或靜態變數,不佔據實際空間,僅僅為乙個佔位符

.symtab

符號表:存放程式中定義和引用的函式和全域性(靜態)變數資訊

.rel.text

對應與.text中位置的列表,呼叫外部函式或者引用全域性變數時修改

.rel.data

被模組引用或者定義的所有全域性變數的重定位資訊

objdump -x add.o   linux中採取objdump才看elf目標檔案資訊

可以看到目標檔案中,主要包含**段、資料段等節,同時以及最重要的符號表(symbol_tab)

自定義函式 add_funii  (已經被編譯期重新修改函式名 典型的加上i  i  對應引數描述) 在符號表最後乙個。

【符號與符號表】

符號表包含所在可重定位模組定義和引用的符號的資訊,通常包含三種不同的符號:

類別對應於源程式

全域性符號:由本模組定義,能被其它模組引用的符號

對應於c++源**中定義的全域性變數和函式

區域性符號:由本模組定義,但不能被其它模組引用的符號

對應於c++源**中定義的本檔案可見的static 變數和函式

外部符號:由其它模組定義並被本模組引用的全域性符號

本檔案宣告使用,在其它原始檔定義的全域性變數和函式

注意:符號表中不包含任何區域性非靜態變數的任何符號,這是因為這些區域性變數都是在執行時棧中建立和銷毀。

因此,static關鍵字最重要的用途:使得被修飾的函式或變數只能在本模組(檔案)中可見。

目標檔案格式

unix 最早的可執行檔案格式為a.out格式,它的設計非常的簡單,以至於後來共享庫這個概念出現的時候,a.out格式就變得捉襟見肘 於是人們設計了coff格式來解決這個問題,coff是由unix system v release 3首先提出並使用的格式規範,後來微軟公司基於coff格式,制定了pe...

目標檔案格式

在linux 0.12 系統中,gnu gcc 或gas 編譯輸出的目標模組檔案和鏈結程式生成的可執行檔案都使用了unix傳統的a.out格式。這是一種被稱為彙編與鏈結輸出 assembly linker editor output 的目標檔案格式。對於具有記憶體分頁機制的系統來說,這是一種簡單有效...

目標檔案格式

程式從原始碼編譯為目標 的時候,這個目標檔案的格式是怎麼樣的?elf目標檔案有 段,資料段和bss段。elf目標檔案的標頭檔案,段表,重定位表,字串表,符號表,除錯表。無論是可執行檔案,目標檔案或庫,它們實際上都是一樣基於段的檔案或是基於這種檔案的集合。程式的源 經過編譯後,按照 和資料分別存放到相...