当链接动态共享库时,ld会做什么?

3
当将应用程序链接到一个动态共享库时,例如在
gcc -o myprog myprog.o -lmylib

我知道连接器(在Linux上是ld)使用-l选项将库名(在这个例子中是mylib)存储在生成的myprog ELF可执行文件中,该库将在加载和链接时使用(如果我们忽略惰性动态链接,则在程序启动时)。我想知道在编译时进行静态链接步骤时,连接器ld还执行了哪些关于动态共享库的任务?
  • ld必须检查提供的动态共享库中未定义符号的存在
  • 还有其他一些东西吗?
此外,我对您正在使用的指针(书籍、在线文档)以及ELF格式和动态链接和加载过程感兴趣。
2个回答

7
当链接到ELF共享库时,您需要确保ld完成了最显而易见的事情,但还有一些您错过的内容。我将重新列出您提到的内容并添加更多内容:
  1. 确保解析所有未定义的符号(除非输出本身是共享库,在这种情况下未定义的符号是有效的)。

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

  3. 如果输出不是位置无关的,并且在共享库中引用对象(指数据,而不是函数),则生成复制重定位以将对象的原始映像复制到主程序的数据段中的加载时间,以及适当的符号表条目,使得对共享库中对象的引用被解析为主程序中的新副本,而不是库中的原始副本。

  4. 为输出中每个未在ld时间解析为输出中的定义的函数调用目标生成PLT节。

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

3

其中一个重要的步骤是创建一个 动态符号表,运行时链接器 ld.so 可以在运行时将可执行文件与库进行链接。它还会写入 动态重定位表 来记录需要更改的机器码位置,以指向动态链接符号。详细信息请参见:

objdump -T myprog
objdump -R myprog

同时请注意,写入可执行文件的字符串实际上将是库的SONAME,可能类似于mylib.so.0。这将确保即使在以后某个时刻安装了更新且不兼容的mylib.so.1.42,可执行文件仍将使用兼容的ABI版本0。详情请参阅:
ldd myprog

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接