【问题标题】:What does ld do when linking against dynamic shared library?链接动态共享库时 ld 会做什么?
【发布时间】:2023-12-05 17:57:01
【问题描述】:

将应用程序链接到动态共享库时,例如在

gcc -o myprog myprog.o -lmylib

我知道链接器(我的 Linux 上的 ld)使用 -l 选项在生成的 myprog ELF 可执行文件中存储将在加载和链接时使用的库的名称(在本例中为 mylib)时间(如果我们忽略惰性动态链接,程序将在何时启动)。我想知道ld(我只是说在编译时完成的静态链接步骤)关于动态共享库的其他工作是什么?

  • ld 必须检查提供的动态共享库中是否存在未定义的符号
  • 还有其他东西吗?

此外,我会对您使用的关于 ELF 格式和动态链接和加载过程的指针(书籍、在线文档)感兴趣。

【问题讨论】:

    标签: c linux linker ld


    【解决方案1】:

    一个重要的步骤是创建一个动态符号表,运行时链接器ld.so 可以使用它在运行时将可执行文件链接到库。它还将编写动态重定位表来记录需要更改哪些机器代码位置以指向动态链接的符号。查看详情:

    objdump -T myprog
    objdump -R myprog
    

    还要注意写入可执行文件的字符串实际上是库的SONAME,可能类似于mylib.so.0。这将确保即使您稍后安装更新且不兼容的mylib.so.1.42,可执行文件也将使用兼容的 ABI 版本 0。详情:

    ldd myprog
    

    当然,链接器也会将您的目标文件相互链接,但由于即使在没有动态共享库的情况下它也会这样做,我认为您对它的这部分操作不感兴趣。

    【讨论】:

      【解决方案2】:

      虽然您在链接到 ELF 共享库时遇到了 ld 需要做的最明显的事情,但您还错过了一些其他事情。我将重新陈述您提到的内容并添加更多内容:

      1. 确保解析所有未定义符号(除非输出是共享库本身,在这种情况下未定义符号有效)。

      2. 将库的引用存储在输出文件的_DYNAMIC 对象的DT_NEEDED 记录中。

      3. 如果输出不是位置独立的并且引用共享库中的对象(在数据的意义上,而不是函数),则生成复制重定位以将对象的原始图像复制到主程序的加载时的数据段,以及正确的符号表条目,以便对共享库本身中对象的引用解析为主程序中的新副本,而不是库中的原始副本。

      4. 为输出中每个函数调用的目标生成 PLT thunk,这些函数调用在 ld-time 未解析到输出中的定义。

      这些是我能想到的特定于使用共享库的任务,当然不包括链接器已经完成的所有工作,这些工作与静态链接相同。思考ld 对动态链接所做的一种方法是,它采用具有大量重定位类型(表示编译器或汇编器可以生成的任何内容)的目标文件并解析除少数之外的所有目标文件(对于静态链接,该数字将为零),其中所有剩余的重定位都适合动态链接器在加载时可解析的更有限的一组类型。

      【讨论】: