第四章 靜態(tài)鏈接

4.1 空間與地址分配

  • 問題:當(dāng)有多個目標(biāo)文件時,是如何合并到一個文件中的(生成可執(zhí)行文件),是在哪個位置插入相關(guān)代碼的?以什么規(guī)則進(jìn)行插入?

4.1.1 按序疊加

  • 最簡單的方式就是按序疊加,這樣做非常浪費(fèi)空間,因?yàn)槊總€段都需要地址和空間對齊,并且按章class 1,class 2,順序添加,出現(xiàn).text段重復(fù),導(dǎo)致內(nèi)存空間中大量碎片

4.1.2 相似段合并

  • 將.text段合并
  • 鏈接器一般都采用兩步鏈接:

    1.空間與地址分配:掃描所有的輸入目標(biāo)文件,并且獲得他們的各個段的長度,屬性和位置,并且將輸入目標(biāo)文件中的符號表中所有的符號定義和符號引用收集起來,同意放到一個全局符號表中,這一步鏈接器能獲取所有目標(biāo)文件的段長度,并且將它們合并,計(jì)算出輸出文件中各個段合并后的長度與位置,并建立映射關(guān)系

    2.符號解析與重定位:使用第一步收集到的信息,讀取文件中段內(nèi)容數(shù)據(jù)、重定位信息,并且進(jìn)行符號解析與重定位、調(diào)整代碼中的地址等,事實(shí)上第二步是鏈接過程的核心,特別是重定位過程

4.2 符號解析與重定位

4.2.1 重定位

  • 代碼里面使用的地址都是虛擬地址

4.2.2 重定位表

  • 鏈接器需要進(jìn)行重定位,哪些指令需要重定位,怎么重定位,需要依賴重定位表,他在ELF文件中是一個或多個段
    ,有時候也叫重定位段
  • 通俗的理解a.o文件引用外部的符號,都需要依賴重定位表進(jìn)行重定位

4.2.3 符號解析

  • 重定位過程伴隨著符號解析過程,當(dāng)鏈接器需要對某個符號進(jìn)行重定位時,它就要確定這個符號的目標(biāo)地址

4.3 COMMON塊

  • 鏈接器本身并不支持符號的類型,變量類型對i 鏈接器來說是透明的,它只知道一個符號的名字,并不知道類型是否一致,所以會出現(xiàn)多個強(qiáng)符號相同報錯的現(xiàn)象

4.4 C++相關(guān)問題

  • C++一些語言特性必須由編譯器和鏈接器共同支持才能完成

4.4.1 重復(fù)代碼消除

  • C++編譯期提供了一個編譯選項(xiàng)叫函數(shù)級別鏈接,這個選項(xiàng)的作用是所有函數(shù)都單獨(dú)保存在一個段里面,當(dāng)鏈接器需要用到某個函數(shù)時候,就將它合并到輸出文件中,對那些沒有用到的函數(shù)則拋棄掉,好處是減少輸出文件的大小,壞處是編譯和鏈接過程會變慢,編譯器會計(jì)算各個函數(shù)的依賴關(guān)系

4.4.2 全局構(gòu)造與析構(gòu)

  • 一般的C/C++程序是從main開始,main函數(shù)結(jié)束而結(jié)束
  • 但是在main函數(shù)調(diào)用之前,為了讓程序順利執(zhí)行,要初始化進(jìn)程執(zhí)行環(huán)境

4.4.3 C++與ABI

  • ABI:采用同樣的目標(biāo)文件格式、擁有同樣的符號修飾標(biāo)準(zhǔn)、變量的內(nèi)存分布方式相同、函數(shù)的調(diào)用方式相同,等等。其中我們把符號修飾標(biāo)準(zhǔn)、變量內(nèi)存布局、函數(shù)調(diào)用方式等這些跟可執(zhí)行代碼二進(jìn)制兼容性相關(guān)的內(nèi)容叫ABI
  • API往往是源代碼級別的接口,ABI往往是二進(jìn)制層面的接口

4.5 靜態(tài)庫鏈接

  • 靜態(tài)庫可以簡單的看成一組目標(biāo)文件的集合

4.6 鏈接過程控制

4.6.2 最小的程序

todo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容