关于共享库的链接,它们真的是最终的,如果是,为什么?

问题描述 投票:1回答:1

我正在尝试了解有关链接和共享库的更多信息。

最终,我想知道是否可以向共享库添加方法。例如,假设有一个源文件a.c和一个库lib.so(没有源文件)。为了简单起见,让我们进一步假设a.c声明一个方法,其名称在lib.so中不存在。我认为也许可以在链接时将ao链接到lib.so,同时指示创建newLib.so,并强制链接器将lib.so中的所有方法/变量导出到newLib.so现在基本上lib.so和a.so中添加的方法。

[一般来说,如果某个人的文件取决于共享库,那么可以创建一个不再依赖于共享库的单个输出文件(库或可执行文件吗? (也就是说,库中的所有相关方法/变量都已导出/链接/内联到新的可执行文件中,因此使依赖项无效)。如果那不可能,那么从技术上阻止它的原因是什么?

在某种程度上,有人问过类似的问题:Merge multiple .so shared libraries。答复之一包括以下文本:“如果您有权访问两个库的源文件或目标文件,则可以直接从它们编译/链接组合的SO 。:无需说明技术细节。这是错误的还是它可以容纳吗?如果可以,怎么办?

linker compiler-construction shared-libraries dynamic-library
1个回答
0
投票

一旦拥有共享库libfoo.so,便可以使用它的唯一方法在其他任何东西的链接中:-

例如链接一个动态依赖它的程序

$ gcc -o prog bar.o ... -lfoo

或者,链接另一个动态依赖于它的共享库,例如

$ gcc -shared -o libbar.so bar.o ... -lfoo

[在两种情况下,都是proglibbar.so获得对libfoo.so的动态依赖。这表示prog|libfoo.so链接器中刻有信息,该信息指示OS加载程序在运行时查找libfoo.so,将其加载到当前进程的地址空间,并将程序的引用绑定到libfoo的导出符号上其定义的地址。

因此libfoo.soprog|libbar.so必须继续存在。无法将libfoo.soprog|libbar.so这样libfoo.so会物理合并到prog|libbar.so中并且不再是运行时依赖项。

无论您是否拥有取决于bar.o ...的其他链接输入文件-libfoo.so。的您可以使用共享库执行的唯一链接是动态链接。

static library的链接完全相反

您想知道this answer中的声明:

如果您可以访问两个库的源文件或目标文件,则可以直接从它们编译/链接组合的SO。

作者只是观察到我是否有源文件

$ foo_a.c foo_b.c... bar_a.c bar_b.c

我编译为相应的目标文件:

$ foo_a.o foo_b.o... bar_a.o bar_b.o...

,如果我只是那些目标文件。然后,以及-或代替-将它们链接到两个共享库中:

$ gcc -shared -o libfoo.so foo_a.o foo_b.o...
$ gcc -shared -o libbar.so bar_a.o bar_b.o...

我可以将它们链接为一个:

$ gcc -shared -o libfoobar.so foo_a.o foo_b.o... bar_a.o bar_b.o...

即使存在libfoo.solibbar.so也不会依赖。

而且尽管可以很简单,但也可能是错误的。如果有在name中的任何一个中全局定义的任何符号foo_a.o foo_b.o...和也可以在bar_a.o bar_b.o...的任何一个中全局定义,则无所谓到libfoo.solibbar.so的链接(并且不必动态由任何一个导出)。但是libfoobar.so的链接将失败name的多重定义。

[如果我们构建一个依赖于libbar.so并具有本身被[libfoo.so链接

libfoo.so

然后我们想要将程序与$ gcc -shared -o libbar.so bar.o ... -lfoo 链接,我们可以通过这种方式我们不需要mention其依赖项libbar.so

libfoo.so

请参阅$ gcc -o prog main.o ... -lbar -Wl,-rpath=<path/to/libfoo.so> 以进行后续操作。但这不会改变this answerlibbar.so具有运行时依赖性的事实。

如果不可能,从技术上讲是什么在阻止它?

从技术上讲,是防止共享库与某些程序链接的。或共享库libfoo.so以某种方式将其合并为targ的方式是共享库(如程序)不是链接程序所知道的如何物理合并到其输出文件。

链接器可以物理合并到targ的输入文件需要具有指导链接程序进行合并的结构特性。这就是目标文件的结构。它们由标有各种属性的目标代码或数据的已命名的[[inputsection组成。粗略地说,链接器将目标文件切成段,然后将它们分发到根据输出文件的输出部分的属性,使对合并结果进行二进制修改,以解决静态符号引用或启用OS加载程序以在运行时解析动态加载程序。

这不是可逆过程。链接器无法使用程序或共享库并重建从中创建目标文件再次将它们合并成其他东西。

但是那真的很重要。当输入文件在物理上合并为targ,称为

static

链接。当输入文件只是targ中的外部引用时,使OS加载程序将它们映射到为targ启动的进程中,这称为dynamic链接。技术发展给了我们满足以下所有需求的文件格式解决方案:用于静态链接的目标文件,共享库动态链接。两者都不能用于另一个目的。
© www.soinside.com 2019 - 2024. All rights reserved.