靜態鏈結的過程
各個檔案之間都是單獨編譯的。編譯生成可重定位目標檔案後,目標檔案格
式也是elf可執行檔案格式但是並不能執行:根本原因是在編譯的時候目標檔案並沒有分配虛擬位址
原因如下:
如果是定義在本檔案的函式和變數編譯器可以為它分配位址,但是如果當前的原始檔引用其他檔案的函式或者是全域性變數,這個時候就無法確定其位址了。所以就把虛擬位址的確定同意推遲到鏈結的過程。就需要呼叫系統的鏈結器將目標檔案進行鏈結生成可執行檔案。處於簡單考慮,這裡以靜態鏈結進行分析鏈結過程做了哪些事情:鏈結過程主要包括了位址和空間分配、符號決議、重定位。
掃瞄所有的目標檔案,獲得它們各個段的長度,屬性和起始位址。
合併各個目標檔案的符號表:將目標檔案的所有符號表統一放到乙個全域性的符號表中進行合併。採用相似段合併的策略也就是說將所有目標檔案的.text段都合併到輸出檔案的.text段接著是所有目標檔案.data,.bss段進行合併到輸出檔案對應的段。通過這一步,鏈結器將能夠獲得所有輸入目標檔案的段長度,並且將他們合併計算出目標檔案的所有長度和位置。此後所有函式和變數的虛擬位址都可以確定。elf是從0x08048000(32位)0x400000開始分配虛擬位址的。
二、符號解析和重定位
使用第一步時收集的所有符號資訊放在全域性符號表中,有些是符號的引用,有些是符號的宣告。符號的引用需要進行符號解析和位址重定位,調整引用符號的虛擬位址。其中位址的重定位是鏈結過程的核心。
符號解析:對於指令中引用其他目標檔案中的符號找到符號的正確位址,也就是在全域性符號表中找對應的位址。找不到則報符號未定義錯誤,重複則報符號重定義錯誤。這個過程和重定位過程一起進行。重定位過程伴隨著符號解析。
重定位:就是修正指令對引用其它目標檔案的函式或變數的位址,未確定之前用的都是假位址。這個時候因為有第一步合併的全域性符號表,所有的符號都有自己的位址可以進行重定位。重定位的過程也參照elf檔案也就是目標檔案中的重定位表進行的,該錶記錄哪些段中包含著需要進行重新定位的函式和變數。也伴隨著符號解析的過程。並且也伴隨符號的解析過程。
《程式設計師的自我修養》
深入理解預編譯,編譯,彙編,鏈結的過程 之鏈結
我們接觸程式的時候,一般編譯和鏈結是一起做的,所以不容易看到編譯和鏈結的不同,這裡我們講一下編譯和鏈結的區別。範例1 main.c int main 對main.c生成執行檔案 gcc o main main.c 生成可執行檔案main 沒有字尾名 這個檔案什麼也不幹,但是可以執行。gcc o的過程...
深入理解嵌入式程式鏈結過程
1.鏈結就是將彙編生成的obj檔案,系統庫的obj檔案,庫鏈結起來,最終生成可以在特定平台 執行的可執行程式。2.用 gcc v o hellow hellow.c詳細檢視所有編譯過程 3.系統標準啟動檔案,對一般的應用程式來說,這些是必須的。4.nostdlib不連線系統標準檔案和啟動檔案.用於裸...
C 中靜態的深入理解
一 靜態成員 1 通過static關鍵字修飾,是屬於類,例項成員屬於物件,在這個類第一次載入的時候,這個類下面的所有靜態成員會被載入。2 靜態成員只被建立一次,所以靜態成員只有乙份,例項成員有多少個物件,就有多少份。3 類載入的時候,所有的靜態成員就會被建立在 靜態儲存區 裡面,一旦建立直到程式退出...