連結器、載入器與目的檔格式

預連結(prelinking)

每次一個動態連結的程式啟動,動態連結器都會做工:它為每個共享函式庫挑選位址,然後走過重定位、為程式用到的每個符號填好 GOT。對載入許多大型函式庫的程式,這份啟動工作在每一次啟動都重複,即使在穩定的系統上,那些函式庫通常都落在相同位置、解析到相同位址。預連結是把這份工作「事先做一次」並快取結果、使啟動能略過大部分的最佳化。

用簡單步驟說明這個想法:一個事先執行的預連結回合,在整個系統上為每個共享函式庫指定一個固定、不衝突的載入位址,然後預先算出解析後的重定位值、直接寫進二進位檔與函式庫裡。當一個預連結過的程式之後啟動,動態連結器檢查假設是否仍成立(函式庫在預連結預期的地方且未改變);若成立,它就能使用快取的位址、略過大部分重定位工作,使啟動更快。Apple 較舊的對應物叫預先繫結(prebinding),在 Mac OS X 上服務相同目的。兩者基本上都是一個賭注:函式庫的集合與位置夠穩定到能預先算出連結。

它作為歷史教訓比作為當前預設更重要。在機器較慢、函式庫集合有限的年代,預連結帶來可測量的啟動收益,但它大致失寵,在大多數現代系統上被停用或移除。理由很誠實:它從根本上與定址空間版面配置隨機化衝突(固定函式庫位址正是 ASLR 想避免的)、每當函式庫更新就得重做(所以套件管理員必須重新執行它),而現代動態連結器加上更快的硬體縮小了好處。所以把預連結當成一個聰明的想法,其安全成本超過了它的速度好處——值得理解,如今很少使用。

# 歷史上:一個預連結回合指定固定的函式庫位址 # 並把解析後的重定位烤進二進位檔裡: $ prelink -avmR # (現在在多數發行版上已棄用/移除) # 現代系統改保留 ASLR -> 函式庫「不」在固定位址。

預連結預先算出並快取函式庫位址與重定位以加速啟動;它與 ASLR 衝突,如今很少使用。

預連結與 ASLR 衝突,因為它把函式庫釘在固定位址——與隨機化相反。那個安全成本,加上每次函式庫更新都得重做,正是現代系統普遍停用它的原因。

又称
prelinkprebinding預連結預先繫結