动态链接器可以互换吗?
假设我编译一个程序,例如使用 gcc,链接到各种动态库,该程序在运行时与 gnu 链接器一起使用来解析动态库符号。我没有使用 gnu 链接器,而是需要或想要使用另一个链接器。
这样做可行吗?为什么/为什么不行?
答案1
我假设“动态链接器”指的是动态链接器/加载器,通常称为ld.so
,而不是构建程序时使用的链接器ld
。
动态链接器/加载器与其关联的 C 库紧密耦合,甚至是其一部分。在 Linux 上,正如这里通常讨论的,通常的加载器是 GNU C 库的加载器;如果你查看它的符号,你会发现它从 C 库中提取符号:
$ nm -D /lib/ld-linux.so.2 | grep -E ' A|D '
00028898 D _dl_argv
00000000 A GLIBC_2.0
00000000 A GLIBC_2.1
00000000 A GLIBC_2.3
00000000 A GLIBC_2.4
00000000 A GLIBC_PRIVATE
00028f28 D __libc_enable_secure
00028f24 D __libc_stack_end
00029040 D _rtld_global
000288a0 D _rtld_global_ro
看动态链接器/加载器本身如何按照“文件”报告进行动态链接?了解其工作原理的详细信息。
替代 C 库提供自己的动态加载器;例如,用构建的程序穆斯勒在 x86_64 上将其“解释器”指定为/lib/ld-musl-x86_64.so.1
,这是 musl C 库本身的链接:
$ ls -l /lib/ld-musl-x86_64.so.1
lrwxrwxrwx 1 root root 25 Jan 23 2019 /lib/ld-musl-x86_64.so.1 -> x86_64-linux-musl/libc.so
加载器依赖于其关联的 C 库提供的功能,反之亦然。它会从技术上讲,可以用兼容的实现替换给定的加载器,但您至少会有效地重写现有的加载器。虽然动态加载器的基本规范是明确定义和有界的——加载 ELF 二进制文件(在 Linux 上)、关联的动态库,并执行必要的重定位等——因此人们可能会想象用另一个加载器替换任何给定的加载器,但实现细节都很重要。
请注意,只要每个动态加载器具有不同的规范名称,单个系统就可能具有不同的加载器,并由程序酌情使用。这就是为什么基于 GNU C 库的系统也可以用于构建和运行 musl 二进制文件,并为诸如llvm-libclibc.so.5
,甚至历史上,从到 的切换libc.so.6
。
答案2
它们必须是可以互换的。
ld
关于eg vs 的一个很好的讨论gold
可以在这里找到:https://stackoverflow.com/questions/3476093/replacing-ld-with-gold-any-experience
还要检查一下:https://stackoverflow.com/questions/29361801/is-the-lld-linker-a-drop-in-replacement-for-ld-and-gold
还有来自 LLVM 项目的 LLD,它有望成为最快的他们所有人中。