为什么-r选项(可重定位)使ld找不到任何库?

时间:2011-07-04 10:09:01

标签: linux ld binutils relocation

使用GNU ld 2.21运行Debian / Linux x86_64。

很简单,如果我链接

ld -o main main.o /usr/lib/crti.o /usr/lib/crt1.o /usr/lib/crtn.o -lc -lm

它有效,但当我与

链接时
ld -r -o main1.o main.o /usr/lib/crti.o /usr/lib/crt1.o /usr/lib/crtn.o -lc -lm

抱怨

ld: cannot find -lc
ld: cannot find -lm

我实际上并没有尝试以这种方式编译代码,而是我试图弄清楚为什么别人的测试看看是否存在库是不行的。 (因此我真的不明白ld发生了什么......通常我只是用GCC来链接)

为什么告诉ld以可重定位的方式链接会让它突然无法找到库?如果我只想测试-lm是否存在,除了

我还应该做些什么
ld -r -lm

以便找到图书馆?

如果你想查看我正在处理的源代码,可以在这里下载:https://github.com/jeremysalwen/ESPS(注意,第一次提交是原始源代码,后续提交是我个人所做的更改制成。)

2 个答案:

答案 0 :(得分:3)

MacOS X

在MacOS X上,ld的手册页非常清楚-r选项:

  

-r合并目标文件以生成另一个文件类型为MH_OBJECT的mach-o目标文件。

因此,如果您使用的是MacOS X,则问题是-lm不是Mach-O目标文件,-lc也不是。{1}}。但是,从理论上讲,如果您有目标文件main.oobj1.oobj2.o,那么您可以:

cp obj1.o ./-lm
cp obj2.o ./-lc
ld -r -o main1.o main.o -lm -lc

那么它可能会奏效。在实践中,它没有,并且在你得到的错误中:

ld: warning: unexpected dylib (/usr/lib/libm.dylib) on link line
ld: warning: unexpected dylib (/usr/lib/libc.dylib) on link line

然而,运行:

ld -r -o main1.o -arch x86_64 main.o obj1.o obj2.o

没有任何来自装载机的抱怨。

的Linux

在Linux上,ld的手册页不那么明确,但是说:

  

-i执行增量链接(与选项-r相同)。

     

-r
  --relocatable

     

生成可重定位输出---即生成一个输出文件,该文件又可以作为ld的输入。这通常称为部分链接。作为副作用,在支持标准Unix幻数的环境中,此选项还将输出文件的幻数设置为“OMAGIC”。如果未指定此选项,则会生成绝对文件。链接C ++程序时,此选项不会解析对构造函数的引用;要做到这一点,请使用-Ur

     

如果输入文件的格式与输出文件的格式不同,则仅当输入文件不包含任何重定位时,才支持部分链接。不同的输出格式会有进一步的限制;例如,一些基于“a.out”的格式不支持与其他格式的输入文件进行部分链接。

     

此选项与-i完全相同。

在行之间读取,这也会获取目标文件并将它们转换为目标文件;它不会将库添加到组合中。如果你考虑一下,就不会创建包含对库的引用的目标文件。

因此,尽管在使用-r选项时可能存在可以为链接器(加载器)指定库的平台,但还有一些不是。{/ p>

变通方法

最初的问题是确定库是否存在。为什么不模仿autoconf做什么,并创建一个main.c,优先包含对库中定义的符号的引用,但它可以只包含:

int main(void){return 0;}

并使用C编译器编译并链接它:

cc -o main main.c -lm -lc

如果它不起作用,则缺少其中一个库。如果您已检查-lc是否存在,那么您可以推断-lm缺失。

答案 1 :(得分:0)

echo $LD_PRELOAD显示什么?

可能错误消息是ld无法找到链接库的.so。您可以通过将LD_PRELOAD设置为指向那些.so文件来提供帮助。