簡體   English   中英

用 GCC 編譯時還需要使用 -fPIC 嗎?

[英]Does one still need to use -fPIC when compiling with GCC?

在 gcc 目標機器上,當你想編譯一個共享庫時,你需要指定 -fpic 或 -fPIC 以使事情正確地工作。 這是因為默認情況下使用絕對尋址,這適用於完全控制自己地址空間的可執行文件,但不適用於共享庫,共享庫可以加載到可執行文件地址空間的任何位置。

然而,現代內核現在正在實現地址空間隨機化,並且許多現代架構都支持 PC 相對尋址。 這一切似乎使絕對尋址不可用(地址空間隨機化)或不需要(PC 相對尋址)。

我還注意到 clang 沒有 -fPIC 選項,這讓我認為不再需要它。

那么 -fPIC 現在是多余的還是需要生成單獨的 .o 文件,一個用於靜態庫使用,另一個用於共享庫使用?

您仍然需要使用 -fPIC 進行編譯。 該問題無法通過 pc 相對尋址解決。 問題是如何解析外部符號。 在動態鏈接的程序中,解析遵循不同的規則,尤其是在地址空間隨機化的情況下,它無法在鏈接期間解析。

並且 clang 確實像 gcc 一樣具有 -fPIC 標志。

$ cat > foo.c
void foo(void);
void bar(void) { foo(); }
$ gcc -S foo.c && grep call.*foo foo.s
    call    foo
$ gcc -fPIC -S foo.c && grep call.*foo foo.s
    call    foo@PLT
$ clang -S foo.c && grep call.*foo foo.s
    callq   foo
$ clang -fPIC -S foo.c && grep call.*foo foo.s
    callq   foo@PLT
$

我同意你的看法:在許多情況下 -fpic/-fPIC 選項幾乎是多余的,但我確實使用它們來確保:

  • 可移植性(永遠不確定有哪些特定的操作系統/內核可用)
  • 向后兼容性:使用這些選項可以確保您在舊內核上的行為
  • 習慣 - 很難打破:)
  • 遵守可能需要它的舊代碼庫

您永遠不需要生成單獨的.o文件。 始終指定編譯器選項以生成可移植代碼(通常為-fPIC )。

在某些系統上,編譯器可能被配置為強制打開此選項,或默認設置它。 但無論如何指定它並沒有什么壞處。

注意:人們希望在支持 PC 相對尋址且性能良好的情況下-fPIC使用該模式而不是專用一個額外的寄存器。

gcc面向許多平台和體系結構,但並非所有平台和體系結構都像 x86 體系結構一樣支持本機 PIC。 在某些情況下,創建 PIC 意味着額外的開銷,這可能是不受歡迎的,您是否想要或需要這取決於您的項目和目標平台。

這取決於目標。 默認情況下,某些目標(如 x86_64)與位置無關,sp -fpic是一個 noop,對生成的代碼沒有影響。 因此,在這些情況下,您可以省略它並且沒有任何變化。 默認情況下,其他目標(如 x86 32 位)不是位置獨立的,因此在這些機器上,如果您省略可執行文件的-fpic ,它將禁用該映像文件的 ASLR(但不會禁用它使用的共享庫)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM