为什么我需要-FPIC来与 - 未分辨 - 符号=忽略对象的文件

Why do I need -fPIC for compiling with --unresolved-symbols=ignore-in-object-files?

本文关键字:符号 文件 对象 -FPIC 来与 为什么      更新时间:2023-10-16

我有以下2个文件:

main.cpp:

#include <iostream>
int f();
int main(){
  std::cout<<f();
}

functions.cpp:

int f(){
   return 42;
}

i compile functions.cpp中的libfunctions.o使用此命令:

g++ -fPIC -shared functions.cpp -o libfunctions.so

i使用此命令将main.cpp汇编为A.out:

g++ main.cpp -Wl,--unresolved-symbols=ignore-in-object-files

我在使用此命令的A. un A. out:

LD_PRELOAD=./libfunctions.so ./a.out

我会得到一个分段故障。

但是,如果我将main.cpp编译为A.

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错误,值得商but。LD产生了您要的二进制文件,忽略了错误。它确实产生了无效的搬迁。使用-fno-plt编译时,我根本没有搬迁,但是该程序仍然崩溃,因为已解决的符号似乎相对于可执行文件或文本部分具有偏移0。

我怀疑使用-fPIC,它恰好适合您,因为LD会为未知符号产生动态迁移。(不过,我无法获得Binutils 2.30来产生此搬迁。(

通常,不可能生成正确的动态迁移到未定义的符号。没有定义,在许多架构上,就无法确定目标是函数还是对象。如果使用复制重新定位,则对对象的未定义引用需要准确的尺寸信息。功能和对象引用都需要一个符号定义来获得正确的符号版本(如果有(。下连接极为问题的原因有很多。

可能值得将其报告为Binutils Linker错误,但我认为它将被视为非常低的优先级。