動(dòng)態(tài)鏈接的步驟基本上分為3步:
- 啟動(dòng)動(dòng)態(tài)鏈接器本身
- 裝載所有需要的共享對(duì)象
- 重定位和初始化
動(dòng)態(tài)鏈接器自舉
動(dòng)態(tài)鏈接器本身也是一個(gè)共享對(duì)象霹粥,但是事實(shí)上它有一些特殊性蔽莱。對(duì)于普通共享對(duì)象文件來(lái)說(shuō),它的重定位工作由動(dòng)態(tài)鏈接器來(lái)完成趾唱;它也可以依賴(lài)于其他共享對(duì)象,其中的被依賴(lài)的共享對(duì)象由動(dòng)態(tài)鏈接器負(fù)責(zé)鏈接和裝載∏#可是對(duì)于動(dòng)態(tài)鏈接器本身來(lái)說(shuō)赞警, 不可以依賴(lài)于其他任何共享對(duì)象;其次是動(dòng)態(tài)鏈接器本身所需要的全局和靜態(tài)變量的重定位工作由它本身完成虏两。
動(dòng)態(tài)鏈接器必須在啟動(dòng)時(shí)有一段非常精巧的代碼可以完成這項(xiàng)艱巨的工作而同時(shí)又不能用到全局和靜態(tài)變量愧旦。這種具有一定限制條件的啟動(dòng)代碼往往被稱(chēng)為自舉。
動(dòng)態(tài)鏈接器入口地址即是自舉代碼的入口定罢,當(dāng)操作系統(tǒng)將進(jìn)程控制權(quán)交給動(dòng)態(tài)鏈接器時(shí)笤虫,動(dòng)態(tài)鏈接器的自舉代碼即開(kāi)始執(zhí)行
裝載共享對(duì)象
完成基本自舉以后,動(dòng)態(tài)鏈接器將可執(zhí)行文件和鏈接器本身的符號(hào)表都合并到一個(gè)符號(hào)表當(dāng)中祖凫,我們可以稱(chēng)它為全局符號(hào)表耕皮。
鏈接器從可執(zhí)行文件中的.dynamic 段中獲取所依賴(lài)的共享對(duì)象,并將這些共享對(duì)象的名字放入到一個(gè)裝載集合中蝙场。當(dāng)一個(gè)新的共享對(duì)象被裝載進(jìn)來(lái)的時(shí)候,它的符號(hào)表會(huì)被合并到全局符號(hào)表中粱年,所以當(dāng)所有的共享對(duì)象都被裝載進(jìn)來(lái)的時(shí)候售滤,全局符號(hào)表里面將包含進(jìn)程中所有的動(dòng)態(tài)鏈接所需要的符號(hào)。
當(dāng)多個(gè)共享對(duì)象中台诗,存在同名的函數(shù)或變量時(shí)完箩,一個(gè)共享對(duì)象里面的全局符號(hào)被另一個(gè)共享對(duì)象的同名全局符號(hào)覆蓋的現(xiàn)象又被稱(chēng)為共享對(duì)象全局符號(hào)介入(Global Symbol Interpose)
重定位和初始化
當(dāng)上面的步驟完成之后,鏈接器開(kāi)始重新遍歷可執(zhí)行文件和每個(gè)共享對(duì)象的重定位表拉队,將它們的GOT/PLT中的每個(gè)需要重定位的位置進(jìn)行修正弊知。因?yàn)榇藭r(shí)動(dòng)態(tài)鏈接器已經(jīng)擁有了進(jìn)程的全局符號(hào)表,所以這個(gè)修正過(guò)程也顯得比較容易粱快。
重定位完成之后秩彤,如果某個(gè)共享對(duì)象有“.init”段,那么動(dòng)態(tài)鏈接器會(huì)執(zhí)行“.init”段中的代碼事哭,用以實(shí)現(xiàn)共享對(duì)象特有的初始化過(guò)程漫雷。
當(dāng)完成了重定位和初始化之后,所有的準(zhǔn)備工作就宣告完成了鳍咱,所需要的共享對(duì)象也都已經(jīng)裝載并且鏈接完成了降盹,這時(shí)候動(dòng)態(tài)鏈接器就如釋重負(fù),將進(jìn)程的控制權(quán)轉(zhuǎn)交給程序的入口并且開(kāi)始執(zhí)行