2011-07-08 127 views
19

首先,我從技術角度提出這個問題,而不是圖書館代碼用戶的觀點。不同之處在於共享對象包含程序頭文件,而普通對象文件則不包含程序頭文件。其他的區別是什麼?ELF對象文件和共享對象之間的ELF頭部區別是什麼?

至於我的問題的目的,我試圖找出哪些內容需要從共享對象文件中刪除,讓鏈接器將其視爲一個普通的對象文件,並嘗試重新定位和靜態鏈接它插入到生成的可執行文件中,而不是將其標識爲共享庫並生成DT_NEEDED參考。這反過來又是將共享庫原始「轉換」爲靜態鏈接的第一步(然而,可能需要進一步的工作以使重定位可滿足)。

+0

不是你的問題的答案,但你可能會發現'-r'選項到'ld'有用 – bdonlan

+0

如果他們不是你正在尋找的東西,他們可能至少幫助:http:// statifier。 sourceforge.net/(將共享庫直接鏈接到一個二進制文件)和http://libraryopt.sourceforge.net/(拆分一個共享庫,刪除不需要的符號並重建它們)...也許這兩個組合? – technosaurus

+0

感謝您的想法,但是我沒有找到好的結果,並且我意識到應該進行機械轉換(儘管中等痛苦,並且可能在一些非標準加載段的非常奇怪的庫上失敗)將共享庫轉換爲單個用於靜態鏈接的可重定位的'.o'文件。 –

回答

11

你會發現一個主要的區別是,在最後的鏈接階段,一些C庫組件靜態鏈接到庫中,形成了INIT和FINI符號等等。這些在程序頭中用DT_INITDT_FINI條目指定;您將需要將這些轉換爲靜態構造函數/析構函數條目。 DT_NEEDED條目將在轉換爲.o時丟失;您需要手動重新添加它們。

最終鏈接階段生成的PLT需要與最終輸出文件合併,或者轉換回普通重定位;這是不平凡的,因爲PLT只是代碼。 GOT也是一個問題;它位於.text段的固定相對偏移處,幷包含指向數據成員的指針。但是,它也包含一個指向_DYNAMIC結構的指針,其中每個庫或可執行文件只能有一個。而且你不能改變GOT中的偏移量,因爲它們是直接從代碼中引用的。

因此,再次將.so轉換爲真實的.o是相當困難的;在轉換到PLT/GOT時信息丟失了。更好的方法可能是更改C庫中的動態鏈接程序,以支持將已經映射到內存中的共享庫鏈接爲靜態圖像。也就是說,只需將.so轉換爲.o,然後將其轉換爲頁面對齊的只讀部分即可。然後將其傳遞給動態鏈接器以重新映射適當的權限並執行正常的共享庫初始化。然後添加一個靜態構造函數來調用C庫來初始化共享庫。最後,添加適當的導出符號以對應共享庫的.text段中的動態符號。

但是,這種方法的一個問題是,靜態構造函數可能會在初始化您的假solib的靜態構造函數之前運行。在這種情況下,他們不能嘗試從solib調用函數,否則可能會崩潰,因爲solib尚未初始化。通過使導出的符號指向蹦牀功能可以避免這種情況,從而確保solib首先被初始化(儘管數據符號並不那麼容易)。

您可能還會發現this previous question可能對您有些用處。

+3

然而,最重要的是,類型(Elf_Ehdr.e_type)也需要改變。 (EXEC/DYN與REL) –

相關問題