3

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

gcc -o myprog myprog.o -lmylib

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

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

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

4

2 回答 2

6

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

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

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

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

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

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

于 2013-11-02T00:02:25.067 回答
3

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

objdump -T myprog
objdump -R myprog

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

ldd myprog

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

于 2013-11-01T23:45:15.880 回答