共享库符号冲突和静态链接(在 Linux 上)

xne*_*ang 7 linux gcc elf dynamic-linking ld

我遇到了一个问题,该问题已在一篇好文章“共享库符号冲突(在 Linux 上)”中详细阐述。问题是,当执行和.so定义了同名函数时,如果.so调用这个函数名,它会调用执行中的那个函数,而不是.so本身的这个函数。

我们来谈谈这篇文章中的案例。我了解DoLayer()中的函数在编译时layer.o具有外部函数依赖性。DoThing()layer.o

但是在编译时libconflict.so,外部函数依赖项不应该就地解析并用conflict.o/DoThing()静态地址替换吗?

为什么layer.o/DoLayer()仍然使用动态链接来查找DoThing()?这是设计好的行为吗?

Emp*_*ian 6

这是设计好的行为吗?

是的。

在 UNIX 上引入共享库时,目标是假装它们的工作方式就像代码在常规(存档)库中一样。

假设您已foo()libfooandlibbar和Callsbar()中进行了定义。libbarfoo()

设计目标是cc main.c -lfoo -lbar无论libfoolibbar是存档库还是共享库,其工作原理都是相同的。实现此目的的唯一方法是使用libbar.so动态链接bar()来解析来自to的调用foo(),尽管有本地版本的foo().

这种设计使得创建一个独立的进程变得不可能libbar.so——它的行为(最终调用哪些函数)取决于链接到该进程的其他函数。这也与 Windows DLL 的工作方式相反。

当时并没有考虑创建独立的 DSO,因为 UNIX 实际上是开源的。

您可以使用特殊的链接器标志更改规则,例如-Bsymbolic. 但规则很快就会变得复杂,并且(因为这不是默认的)您可能会在链接器或运行时加载器中遇到错误。