ld 检查共享库中未解析的符号不是多余的吗?

Isn't ld checking for unresolved symbols in shared libraries redundant?

当link针对共享对象运行程序时,ld 将确保可以解析符号。这基本上确保了程序与其共享对象之间的接口是兼容的。阅读 Linking with dynamic library with dependencies 后,我了解到 ld 将下降到 linked 共享对象并尝试解析它们的符号。

当共享对象本身 linked 时,是否已经检查了我的共享对象的引用?

我能理解在 link 时间找出一个程序是否具有启动所需的所有部分的吸引力,但在共享对象可能单独分发的包构建上下文中它似乎无关紧要吗(例如,Debian 的 lib* 包)。它在对执行构建程序不感兴趣的系统上引入了递归构建依赖关系。

我可以相信构建共享对象时解决的依赖关系吗?如果是这样,在构建我的程序时使用 -unresolved-symbols=ignore-in-shared-libs 有多安全?

Aren't my shared object's references already checked when the shared objects are themselves linked?

好吧,共享库可能已经 link 与 -Wl,--allow-shlib-undefined 或虚拟依赖项一起编辑,因此检查它们仍然有意义。

Can I trust the dependencies resolved when the shared object was built?

可能不是,当前 linking 环境和用于 link 原始 shlibs 的环境可能不同。

If so, how safe is it to use -unresolved-symbols=ignore-in-shared-libs when building my program?

在这种情况下,您可能遗漏了潜在的错误(或者更确切地说,将它们延迟到运行时,这仍然很糟糕)。想象这样一种情况,共享对象所需的某些符号来自可执行文件本身或来自可执行文件 link 编辑的库之一(但 而不是 由 shlib缺少符号)。

编辑

虽然以上是正确的,但 Mike Kinghan 的回答给出了更有力的论据,支持在可执行文件期间在库中进行符号解析 link。

您想知道为什么程序的 linkage 应该费心去解析源自于的符号 link 编辑的共享库,因为:

Aren't my shared object's references already checked when the shared objects are themselves linked?

不,他们不是,除非你在 link 共享库时明确坚持,

这里我要建一个共享库libfoo.so:

foo.c

extern void bar();

void foo(void)
{
    bar();
}

例行编译和link:

$ gcc -fPIC -c foo.c
$ gcc -shared -o libfoo.so foo.o

没问题,bar未定义:

$ nm --undefined-only libfoo.so | grep bar
                U bar

我需要坚持让 linker 反对:

$ gcc --shared -o libfoo.so foo.o -Wl,--no-undefined
foo.o: In function `foo':
foo.c:(.text+0xa): undefined reference to `bar'

当然:

main.c

extern void foo(void);

int main(void)
{
    foo();
    return 0;
}

它不会让我 link libfoo 使用 程序:

$ gcc -c main.c
$ gcc -o prog main.o -L. -lfoo
./libfoo.so: undefined reference to `bar'

除非我在同一个 linkage:

中也解决了 bar

bar.c

#include <stdio.h>

void bar(void)
{
    puts("Hello world!");
}

也许可以从另一个共享库中获取:

gcc -fPIC -c bar.c
$ gcc -shared -o libbar.so bar.o
$ gcc -o prog main.o -L. -lfoo -lbar

然后一切都很好。

$ export LD_LIBRARY_PATH=.; ./prog
Hello world!

共享库的本质默认没有 在 link 时解析其所有符号。这样 program - 这 通常 需要在 link 时间内解析其所有符号 - 可以获得其所有符号 通过使用 多个 库进行 link 编辑来解决。