2011-08-27 88 views
25

我最近收到了:創建共享目標時爲什麼fPIC絕對需要64位而不是32位平臺?

...對`局部符號」搬遷R_X86_64_32不能使用;使用-fPIC重新編譯

嘗試將程序編譯爲共享庫時發生錯誤。

現在解決這個問題並不困難(用-fPIC重新編譯所有依賴關係),但經過一番研究後發現,這個問題只存在於x86-64平臺上。在32位上,任何依賴於位置的代碼仍然可以通過動態加載程序進行重定位。

最好answer我能找到的是:

86具有的.text遷移的支持(這是當你有 位置dependend代碼會發生什麼)。這種支持是有代價的,即每個包含這種重定位的頁面都基本上是不共享的,即使它位於共享庫中,從而破壞了共享庫的概念。因此,我們決定禁止這種基於AMD64(加上它創建 問題如果該值比需要32位以上,因爲所有的.text relocs只有 有大小「word32」)

但我不覺得這很充足。如果重定位破壞了共享庫的概念,爲什麼它可以在32位平臺上完成?另外,如果需要對ELF格式進行更改以支持64位,那麼爲什麼並非所有的字段都增加以容納?

這可能是一個小問題,但它的動機是這樣的事實:a)有問題的代碼是一個科學代碼,它不會有必要採取性能打擊和b)這個信息是不可能的首先找到!

[編輯: '答案'

@awoodlands answer可能是最好的 '的字面解釋',@servn added一些有用的信息。

在搜索中找到更多有關不同類型的搬遷,我發現this,最終的x86_64 ABI reference(見68頁) ]

+1

我不知道回答你的問題,但你應該知道了'在x86-64(相對於x86-32)中,-fPIC性能降低,因爲它具有更多的寄存器,PC相對尋址以及考慮PIC設計的ABI。我不會說它已經消失了,但是測量一下,你可能會感到驚喜。 – zwol

+0

這似乎是共識,對於無可否認的極大便利的表現來說是一個小小的懲罰。我將不得不親自嘗試。 –

+0

主要問題當然是爲什麼編譯器有一個「強制選項」。 「你沒有說這個魔術字」是一個相當幼稚的遊戲。 – MSalters

回答

10

據我所知,這個問題是X86-64似乎引入一個新的,更快引用數據相對於指令指針的方式,這在x86-32中不存在。

This article有它一個很好的深入分析,並給出了下面的執行摘要:

的X86-64使用指令指針相抵消 數據的地址是一個很好的優化能力,但在共享庫 的情況下,假設有關數據的相對位置是無效的 並且不能使用。在這種情況下,對全局數據的訪問(即 任何可能在你身上改變的東西)都必須經過抽象層 ,即全局偏移表。

I.e. -fPIC尋址爲尋址增加了一個額外的抽象層,以使通常尋址風格中以前可能的(以及所希望的功能)仍然適用於較新的體系結構。

+0

這是一篇很棒的文章,謝謝! –

7

但我不覺得這相當合適。如果重定位破壞了共享庫的概念,爲什麼它可以在32位平臺上完成?

這是可以做到的,它只是是不是特別有效......計算遷移具有運行成本,重新定位的可執行文件需要額外的內存,並且該機制引入了大量的複雜性到可執行文件加載器。另外,Linux發行版確實希望鼓勵所有代碼使用-fPIC進行編譯,因爲更改可執行文件的基址是一種緩解策略,可以使攻擊安全漏洞的攻擊變得更加困難。

還值得一提的是-fPIC通常不是一個重要的性能成本,尤其是如果您使用-fvisibility = hidden或等效的話。

爲什麼不是所有的領域的大小都增加以適應?

問題中的「字段」是x86-64尋址模式的直接字段,它不受ELF開發人員的控制。

+0

感謝您的回答,它確實增加了@awoodland提供的鏈接 - 尤其是承認它可以完成,但在某一點變得愚蠢。 澄清:fvisibility = hidden意味着所有未顯式導出的函數不會通過PLT調用,因此間接級別被刪除? –

+0

是的,fvisibility = hidden刪除PLT間接。 – servn

相關問題