Linux動態鏈結之三 動態鏈結相關結構

2021-08-14 02:41:25 字數 2962 閱讀 5372

無論是靜態鏈結還是動態鏈結,初始都是作業系統讀取可執行檔案的file_header,以檢查檔案格式、操作許可權等屬性,然後根據段表獲取各個」segment」的vma虛擬裝載位置、檔案位址和操作屬性rwxp等,再根據相似屬性原則相連原則完成裝載,而後將控制權交給檔案頭結構中e_entry入口位址(elf程式的入口虛擬位址,可重定位檔案不可執行,故而為0,靜態鏈結的可執行檔案便是指向執行庫main初始化函式,動態鏈結的可執行檔案則是指向動態鏈結程式的入口位址)。

在linux下,動態鏈結器ld.so實際上本身也是乙個共享物件.so(但它和別的共享物件不同的是,它不能引用其他共享物件),作業系統將ld.so裝載進虛擬程序空間後,將把控制權移交給動態鏈結器的程式入口。ld.so獲取控制權後,首先執行一系列自身的初始化操作,然後將會按照鏈式法則順序載入一系列共享物件.so。當所有.so裝載完畢後,才將控制權重新交給可執行檔案本身。

1.「 .interp」段

現在面對需要動態鏈結的可執行檔案,系統該採用的動態鏈結器在哪?哪種動態鏈結器?這是由elf可執行檔案決定的。.interp段(interpreter直譯器)的內容很簡單,保留的就是:該可執行檔案所需的動態鏈結器的路徑。

.interp段中的動態鏈結器路徑/lib/ld-linux.so.2.是個

軟鏈結,其實指向的應該是/lib/ld-2.6.1.so,當系統glibc庫公升級時,該軟連線就是指向新的動態鏈結器,而不需要修改.interp中的路徑名來配合系統的公升級。

也可以通過readlf指令來獲取乙個可執行檔案所需要的動態鏈結器的路徑

$readlf  -l a.out | grep interpreter

[requesting program interpreter: /lib/ld-linux.so

.2]

2.「 .dynamic」段

前面的文章說道

外部函式位址got子表「.got.plt」的第一項便是指向.dynamic段。類似於.interp這樣的段,elf中還有幾個段也是專門用來動態鏈結的,比如.dynamic段和.dynsym段。

.dynamic段儲存了動態鏈結需要的基本資訊:依賴哪些共享物件、動態鏈結符號表的位置、動態鏈結重定位表的位置、共享物件初始化**的位址。.dynamic段中是如下結構體陣列,該結構體元素用來定義動態鏈結所需的各基本資訊。

…..若是想直接檢視當前檔案依賴於那些共享物件,可用ldd指令

$ldd  program1

linux-gate.so

.1 => (0xffffe000) //該檔案屬於核心虛擬共享物件,處在虛擬程序空間的高階,屬於核心區,涉及到核心載入

./lib.so (0xb7f62000)

libc.so

.6 => /lib/tls/i686/cmov/libc.so

.6 (0xb7e0d000)

/lib/ld-linux.so

.2 (0xb7f66000)

3.「 .dynsym」動態符號表

專表專用,加速動態鏈結符號查詢過程),故而elf動態鏈結模組同時擁有兩個表.symtab和.dynsym, .symtab包括所有符號,包括.dynsym中的符號。

動態符號表也需要一些輔助表,如動態符號字串表.dynstr (dynamic string table)(因為符號名稱是非等項的,為了方便dynsym表的管理,顯然需要字串這種不穩定分子轉移出來以實現dynsym表項等長),為了加快符號的查詢過程,往往還有輔助的符號雜湊表.hash。

4.動態鏈結重定位表

.so共享物件需要重定位的原因在於匯入符號的存在,無論是可執行檔案還是.so,一旦依賴於其他共享物件,也就是說有匯入符號存在,那麼它的**或資料中就會有對匯入符號的引用。在編譯時這些匯入符號的位址未知,靜態鏈結中,這些未知的位址引用在最終鏈結時被修正;而在動態鏈結中,匯入符號的位址只有在執行時才確定,所以需要在執行時將這些匯入符號的引用修正,即需要重定位。(類似於windows下的符號匯出表和符號匯入表)

對於使用pic技術的可執行檔案或共享物件來說,雖然他們的**段不需要重定位(因為位址無關),但是.data段有可能包含了對絕對位址的引用,因為**段中絕對位址相關的部分被分離了出來,變成了got,而got實際上是資料段的一部分。動態鏈結的檔案中,有.rel.dyn和.rel.plt,其中.rel.dyn是對資料引用的修正,修正的位置位於.got以及資料段,而.rel.plt(延遲繫結)是對函式引用的修正,所修正的位置位於.got.plt。

靜態鏈結用到的重定位入口

1.r_386_32 絕對位址修正

2.r_386_pc32下一指令相對位址修正

動態鏈結用到的重定位入口型別

1.r_386_relative:基址重置rebasing,基址+偏移位址

2.r_386_glob_dat:對.got表中的資料符號的重定位標誌,在.got表中填充該資料符號的絕對位址

3.r_386_jump_slot:對.got.plt的重定位標誌,只需要根據.rel.plt表給出的該函式符號在.got.plt的偏移量找到該函式符號的位置,填寫上該函式載入後的位址

重定位表的意義在於提示動態鏈結器要修正的外部符號資訊,可以配合實現plt等延遲繫結機制,實現動態鏈結的快速進行。

linux動態鏈結

在程式中總會用到各式各樣的庫,有兩種使用方式 靜態鏈結庫和動態鏈結庫,在windows下分別對應.lib檔案和.dll檔案,使用靜態庫時需要包含對應的標頭檔案並引用lib檔案,使用動態庫則需要手動通過函式載入dll中的函式。linux下使用方法則有所不同,linux下.a檔案.so檔案分別對應靜態和...

動態鏈結 靜態鏈結

在linux系統中,ld鏈結器將彙編器編譯出來的目標檔案和靜態庫里的.a檔案鏈結生成可執行檔案。靜態庫中的.a檔案的 會在靜態鏈結過程中新增到可執行檔案中,可執行檔案會變得很大。與靜態鏈結不同,linux系統的ld鏈結器會將動態庫.so檔案進行符號重定位生成可執行檔案,動態庫.so檔案並不新增到可執...

靜態鏈結 動態鏈結

如果函式庫的乙份拷貝是可執行檔案的物理組成部分,那麼我們稱之為靜態鏈結。如果可執行檔案只是包含了檔名,讓載入器在執行時能夠尋找程式所需的函式庫,那麼稱為動態鏈結。即根據函式庫是不是可執行檔案的組成部分區分靜態鏈結和動態鏈結。1 可執行檔案的體積小。2 雖然執行速度稍慢,但是能更加有效的利用磁碟空間,...