链接器如何解析动态可加载库中的重复符号?

时间:2015-05-06 14:59:07

标签: c linux build linker dynamic-linking

我有两个可动态加载的库lib_smtp.so和libpop.so等。它们都有一个名为protocol的全局变量,它被初始化为" SMTP"和#34; POP"分别。我有另一个静态库libhttp.a,其中protocol被初始化为" HTTP"。

现在由于某种原因,我需要静态编译所有动态可链接和可加载库并包含在可执行文件中。这样做我得到错误" 符号的多重定义"在链接静态库期间。

我很想知道链接器在动态链接期间如何解析重复的符号,其中所有三个提到的库都被链接了?

有没有某些方法可以像链接器在动态链接中那样静态地执行相同操作,即没有任何冲突将所有静态库添加到具有相同符号的可执行文件中?如果没有,为什么静态链接库的过程不同。

2 个答案:

答案 0 :(得分:5)

现代Linux和其他几种操作系统中的动态链接基于ELF二进制格式。可执行文件或其他共享库所依赖的(ELF)动态库具有优先级。要解析给定的符号,动态链接器会按优先级顺序检查每个库,直到找到定义该符号的库。

当多个动态对象定义相同的符号以及多个动态对象使用该符号时,这可能会很冒险。然后可能是在不同的动态对象中以不同方式解析符号的情况。

完整的详细信息超出了SO的范围,但我不知道比Ulrich Drepper的论文“How to Write Shared Libraries”更好的技术解释。

答案 1 :(得分:2)

在动态链接中,一些称为“符号可见性”的工具启动。实际上,这允许仅在对象的对象上公开某些符号(共享对象意义上的对象)边界。编译和链接共享对象是一种很好的风格,默认情况下隐藏符号,只显示被调用者所需的那些。

符号可见性在链接期间应用,到目前为止仅在动态链接器中实现。它当然也可以在静态链接中使用,Apple的GCC变体实现了所谓的 Mach-O可重定位目标文件,它可以与应用的可见性静态链接。但我不知道香草GCC,binutils ld或黄金链接器是否可以为普通的旧ELF做到这一点。