[英]Why do I need -fPIC for compiling with --unresolved-symbols=ignore-in-object-files?
我有以下2個文件:
main.cpp中:
#include <iostream>
int f();
int main(){
std::cout<<f();
}
functions.cpp:
int f(){
return 42;
}
我使用以下命令將functions.cpp編譯為libfunctions.so:
g++ -fPIC -shared functions.cpp -o libfunctions.so
我使用以下命令將main.cpp編譯為a.out:
g++ main.cpp -Wl,--unresolved-symbols=ignore-in-object-files
當我使用此命令運行a.out時:
LD_PRELOAD=./libfunctions.so ./a.out
我遇到了細分錯誤。
但是,如果我使用以下命令將main.cpp編譯為a.out:
g++ -fPIC main.cpp -Wl,--unresolved-symbols=ignore-in-object-files
然后就可以了。
我理解為什么必須使用-fPIC編譯共享庫,因為一個共享庫不知道在加載時將其加載到的地址。 但是我不明白為什么main.cpp
也必須編譯為PIC。 我以為,由於a.out
的加載地址是在鏈接時知道的,因此肯定不需要使用-fPIC
進行編譯。
我想念什么?
我假設您正在使用GNU工具鏈。 不幸的是,binutils ld有時會為無效輸入生成損壞的二進制文件,而不是失敗並顯示錯誤消息。
就您而言,我得到:
./a.out: error while loading shared libraries: unexpected PLT reloc type 0x00
此錯誤消息是正確的:
Relocation section '.rela.plt' at offset 0x628 contains 4 entries:
Offset Info Type Sym. Value Sym. Name + Addend
…
000000000000 000000000000 R_X86_64_NONE 0
R_X86_64_NONE
的值為零,如果遇到錯誤,有時ld會使用它而不是真正的重定位。
這是否是ld bug,仍有待商bat。 ld生成了您要求的二進制文件,而忽略了該錯誤。 它確實產生了無效的重定位。 使用-fno-plt
編譯時,我什么都沒有重定位,但是程序仍然崩潰,因為已解析的符號相對於可執行文件或文本部分的偏移量為0。
我懷疑使用-fPIC
,它可能對您-fPIC
,因為ld為未知符號生成動態重定位。 (不過,我無法使binutils 2.30產生此重定位。)
通常, 不可能對未定義的符號生成正確的動態重定位。 沒有定義,在許多體系結構上,無法確定目標是函數還是對象。 如果使用副本重定位,則對對象的未定義引用需要准確的大小信息。 函數引用和對象引用都需要符號定義才能獲得正確的符號版本(如果有)。 欠鏈接極其成問題的原因有很多。
可能值得將其報告為binutils鏈接器錯誤,但我認為它將被視為非常低的優先級。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.