2009-08-28 123 views
19

我正在Linux下編寫一個簡單的用戶空間ELF加載器(爲什麼?爲了'好玩')。目前我的加載器非常簡單,只能加載靜態鏈接的包含位置無關代碼的ELF文件。加載時ELF重定位

通常,當程序由內核的ELF加載器加載時,它將被加載到它自己的地址空間中。因此,數據段和代碼段可以按照ELF段中指定的正確的虛擬地址加載。

然而,在我的情況下,我通過mmap從內核請求地址,並且可能會或可能不會獲得ELF段中請求的地址。這對於代碼段來說不是問題,因爲它與位置無關。但是,如果數據段未加載到預期的地址,代碼將無法正確引用存儲在數據段中的任何內容。

事實上,我的加載程序看起來很好用一個簡單的程序集可執行文件不包含任何數據。但是,只要我添加數據段並引用它,可執行文件無法正確運行或SEGFAULT。

如果可能的話,我可以如何修正對數據段的任何引用以指向正確的位置?爲了這個目的,在(靜態)ELF文件中是否存在重定位部分?

+1

由於進程調用mmap已經在地址空間中分配了這些頁面,因此在給出請求的地址時,mmap()失敗的原因是什麼? – 2009-08-29 21:14:51

+0

是的,這可能是原因。我曾想過要求'ld'把我的代碼/數據放在某個地方,但我想知道是否可以首先使用通用解決方案。如果我在這裏沒有得到任何答覆,我可以繼續嘗試。 – 2009-08-30 17:06:28

回答

8

如果修改.got部分中可用的絕對地址(全局偏移量表),程序應該可以工作。請務必修改絕對地址計算以迎合.text和.data之間的新距離,恐怕您需要弄清楚這些信息來自哪裏,適合您的架構。

看到這個:Global Offset Table (Processor-Specific)

好運。

+0

不應該嘗試計算新的距離。一些指令可能會使用相對尋址來引用數據段的內容,並且將段移走會簡單地破壞它。爲了正確地映射段,應該使用'MAP_FIXED',這樣如果所需的區域不可用,並且/或者以原子方式映射兩個段的大區域,然後取消映射它的部分並將各個段映射到位,則「mmap」調用將失敗的洞。 – 2015-02-14 16:17:42

4

除非您完全模擬內核提供的虛擬地址空間,並且在該虛擬空間內運行代碼,否則我看不出您可以這樣做的任何方式。當您從文件中映射數據部分時,您本質上將其重定位到您的ELF解釋器的虛擬地址空間的未知地址,並且您的代碼將無法以任何方式引用它。

很高興被證明是錯誤的。在這裏學習很酷。

+0

或者在不同的進程中有ELF和加載函數的目標,最小的部分需要在一個奇怪的地址的目標進程中。這樣,您可以使用大多數裝載機的標準工具和程序 – 2009-09-06 12:54:44