ZHCADC4A September 2011 – March 2014
静态链接 是将可重定位目标文件与静态库组合为静态链接单元(ELF 可执行文件 (.exe) 或 ELF 共享对象 (.so))的传统过程。在本文档中,我们使用术语加载模块(或简称模块)来指代静态链接单元,并使用共享库(或库)来指代共享对象。
确切来说,程序 包含一个可执行文件,以及它赖以满足任何未定义引用的其他共享库。如果多个可执行文件依赖同一个库,它们可以共享其代码的单个拷贝(因而是共享对象中共享),从而显著降低系统的存储器要求。
当加载此类包含多个对象的程序时,必须解析其组件模块(其中一些可能已作为其他应用的一部分进行加载)之间的引用。此过程称为动态链接,由一个称为动态链接器 的运行时组件处理。由于系统状态会随着在给定时间加载哪些对象而异,因此动态链接器可能希望动态控制其存储器分配和放置。分配程序位置,然后在加载时将其重定位,这一能力有时称为动态加载。尽管动态链接和动态加载在某种程度上是两种独立的功能,因为其中任何一个都可以离开对方使用,但用于实现它们的机制却密切相关。在本文档中,我们使用术语“动态链接”来指代复合功能,同时使用可互换的术语“动态链接器”和“动态加载器”,指代执行这些操作的组件。
对象自身的 函数和变量(统称符号)是在其内部定义的函数和变量。当模块(可执行文件或库)引用在该模块内未定义但在另一个模块中定义的符号时,称为导入 该符号。定义模块称为导出 符号。
一般来说,动态链接模块的代码和数据的地址在静态链接时是未知的。此外,任何导入符号的地址也是未知的,直到它们被动态链接器解析为止。因此,当动态链接器加载模块时,它可能需要根据其分配的地址以及它导入的任何符号的地址,修补它的代码和/或数据。动态链接时执行的重定位称为动态重定位。大多数动态链接机制的设计目标是,尽可能减少动态重定位的数量和复杂性。动态重定位以及关联的符号信息包含在 ELF 目标文件的特殊段中。
共享库的一个基本问题是,共享同一库的每个可执行文件仍必须有自己的专用(非共享)库数据拷贝。这意味着共享代码不能使用绝对寻址来访问数据。术语位置无关数据 (PID) 适用于以可共享方式访问数据的代码,这一访问通常通过相对寻址或基于 GOT 的寻址来实现。
广义的术语位置无关代码 (PIC) 是指不以任何方式使用绝对寻址的代码,因此与自身的放置和其他负载模块的放置无关。位置无关代码不需要对代码段进行加载时修补,从而可以加快加载时间和/或允许其位于 ROM 中。典型的 PIC 方法依赖 PC 相对寻址、虚拟存储器、间接寻址和/或来自基址指针寄存器的相对寻址,如 C60 的 DP (B14)。
对于将位于 ROM 中的模块,需要额外考虑一点。显然,ROM 中的代码无法在加载时修补,因此它具有许多相似的位置无关性要求。