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

发布于 2024-11-18 20:28:08 字数 793 浏览 3 评论 0原文

使用 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

It 有效,但是当我链接

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

It 抱怨

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

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

为什么告诉ld以可重定位的方式链接使它成为可能突然找不到库了? 之外我还应该做什么

ld -r -lm

如果我只是想测试 -lm 是否存在,除了让它找到该库

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

Running Debian/Linux x86_64 with GNU ld 2.21.

Quite simply, if I link with

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

It works, but when I link with

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

It complains

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

I'm not actually trying to compile code this way, but rather I'm trying to figure out why someone else's test to see if a library exists is not working. (Thus I don't really understand what's going on with ld... usually I just use GCC to link)

Why would telling ld to link in a relocatable fashion make it suddenly unable to find libraries? If I just want to test that -lm exists, what should I do besides

ld -r -lm

so that it will find the library?

If you want to see the source that I'm dealing with, you can download it here: https://github.com/jeremysalwen/ESPS (note, that the first commit is the original source code, and the subsequent ones are changes I have personally made.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉城已无爱 2024-11-25 20:28:08

MacOS X

在 MacOS X 上,ld 的手册页对 -r 选项非常明确:

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

因此,如果您使用的是 MacOS X,问题在于 -lm 不是 Mach-O 目标文件,-lc 也不是。但是,理论上,如果您有目标文件 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
--可重定位

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

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

此选项与 -i 执行相同的操作。

从字里行间看,这也获取目标文件并将它们转换为目标文件;它不会添加库。如果您考虑一下,不会创建包含对库的引用的目标文件。

因此,尽管在某些平台上可以在使用 -r 选项时为链接器(加载器)指定库,但在其他平台上却不能。

解决方法

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

int main(void){return 0;}

并使用 C 编译器进行编译和链接:

cc -o main main.c -lm -lc

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

MacOS X

On MacOS X, the man page for ld is quite explicit about the -r option:

-r Merges object files to produce another mach-o object file with file type MH_OBJECT.

So, if you are on MacOS X, the trouble is that -lm is not a Mach-O object file, and neither is -lc. However, in theory, if you have object files main.o, obj1.o and obj2.o and you do:

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

then it might work. In practice, it doesn't, and amongst the errors you get:

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

However, running:

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

worked without any whingeing from the loader.

Linux

On Linux the man page for ld is less explicit, but says:

-i Perform an incremental link (same as option -r).

-r
--relocatable

Generate relocatable output---i.e., generate an output file that can in turn serve as input to ld. This is often called partial linking. As a side effect, in environments that support standard Unix magic numbers, this option also sets the output file’s magic number to "OMAGIC". If this option is not specified, an absolute file is produced. When linking C++ programs, this option will not resolve references to constructors; to do that, use -Ur.

When an input file does not have the same format as the output file, partial linking is only supported if that input file does not contain any relocations. Different output formats can have further restrictions; for example some "a.out"-based formats do not support partial linking with input files in other formats at all.

This option does the same thing as -i.

Reading between the lines, this also takes object files and converts them to object files; it does not add libraries into the mix. If you think about it, object files are not created containing references to libraries.

So, although there might be platforms where it is possible to specify libraries to the linker (loader) when using the -r option, there are others where it is not.

Workarounds

The original problem is to establish whether the libraries are present. Why not mimic what autoconf does, and create a main.c that would, for preference, contain a reference to a symbol defined in the library, but which could simply contain:

int main(void){return 0;}

and compile and link it with the C compiler:

cc -o main main.c -lm -lc

If it doesn't work, then one of the libraries is missing. If you've already checked that -lc is present, then you can infer that -lm is missing.

羁绊已千年 2024-11-25 20:28:08

echo $LD_PRELOAD 向您展示了什么?

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

What is echo $LD_PRELOAD showing you?

Perhaps the error message is saying ld is unable to find the .so of the linked libraries. You could help by setting LD_PRELOAD to point to those .so files.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文