【问题标题】:How does linker resolves duplicate symbols in dynamically loadable libraries?链接器如何解析动态可加载库中的重复符号?
【发布时间】:2018-05-13 20:44:05
【问题描述】:

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

现在出于某种原因,我需要静态编译所有动态可链接和可加载库并包含在可执行文件中。这样做我在链接静态库期间收到错误“multiple definition of symbol”。

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

有没有什么方法我可以静态地做与链接器在动态链接中所做的相同的事情,即在没有任何冲突的情况下将所有静态库添加到具有相同符号的可执行文件中?如果不是,为什么静态链接库的过程不同。

【问题讨论】:

    标签: c linux build linker dynamic-linking


    【解决方案1】:

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

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

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

    【讨论】:

    • 谢谢,在我的情况下,多个动态对象正在定义和使用相同的符号“协议”,但没有任何问题。所以在运行时,一个例程 process_http() 会将符号值读取为“HTTP”,而在 libsmtp.so 中定义的 process_smtp() 会将符号值读取为“SMTP”。为此,符号必须具有已解决干净并有单独的地址?如果我错了,请纠正我
    • 同一个程序中的不同模块看到全局的不同值是否被很好地描述为“没有任何问题”是值得商榷的,但我想这是想要的。是的,当然,符号必须解析为不同模块中的不同地址,因为程序的所有组件都在相同的地址空间中运行。在其中查找动态符号的最高优先级对象通常是出现正在解析的引用的对象;这可能解释了您观察到的行为。
    【解决方案2】:

    在动态链接中,一些称为“符号可见性”的工具开始发挥作用。本质上,这允许在对象(共享对象的意义上的对象)中仅公开某些符号边界。编译和链接共享对象是一种很好的风格,默认情况下隐藏符号,只公开被调用者明确需要的符号。

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

    【讨论】:

    • 如何静态链接 Cocoa 应用的可见性限制?
    猜你喜欢
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    • 2011-11-04
    • 2017-04-13
    • 2019-02-25
    • 2020-01-14
    • 2013-12-27
    相关资源
    最近更新 更多