Advertisement

计算机系统基础 第四章程序的链接

阅读量:

4.1 可重定位目标文件格式

在这里插入图片描述
  • ELF头字段编码信息则包含了诸如ELF标志位序列以及相关参数信息。
  • .text段标记表示最终生成的可执行代码块。
  • .rodata段标记则用于存储那些无法被修改的一类静态数据项。
  • .data段标记则用于标识那些已经被预先配置好的全局变量。
  • .bss段字段编码信息则表示那些尚未进行初始化的内存区域。

4.2 符号解析与重定位

.symtab 节记录符号表信息,是一个结构数组

4.2.1 符号解析

目的:通过引入映射机制实现各模块间引用符号与目标模块定义符号的有效对应关系。

符号定义:具有存储空间分配的功能特性。在具体应用中:

  • 当涉及函数名称的情形下,则指向代码所在的区域;
  • 当涉及变量名称的情形下,则指向所占有的静态数据区域。

4.2.2 强弱符号

*标识符及已被赋值的全局变量名为强静态符号 *未被赋值的全局变量名为弱动态符号

4.2.3 多重定义符号的处理规则

  • Rule 1: 强符号不能多次定义
    强符号只能被定义一次,否则链接错误

Rule 2指出:如果一个符号被定义为一次强符号与多次弱 symbol,则应遵循 strong definition principle;其引用在解析过程中被视为 strong definition symbol.

规定,在处理存在多个弱定义的全局符号的情况时,请选择其中一个进行处理。使用编译命令 gcc –fno-common进行编译操作时,在遇到具有多个弱定义的全局符号的情况下,默认会向链式反应器发出警告提示。

4.2.4 重定位

符号解析完成后,可进行重定位工作,分三步

  1. 合并相同的节点
    将集合E的功能模块中具有相同特性的节点进行整合形成新的特征节点
    例如,在可执行文件中将所有.text特征整合为单独的.text特征节点

对新节中的所有定义符号进行定位以获取其在虚拟地址空间中的具体位置。例如,在函数中首先确定首地址后可推算出各指令的内存位置,并对全局变量同样进行首地址定位。完成这一阶段后即可明确每条指令及其所有全局变量在整个内存中的具体位置。

  1. 重新定位引用符号的位置(确定具体地址)。 在修改.text节和.data节中的每个符号引用信息及其地址时,请参考(rel_data)及(rel_text)中的相关数据以确保准确无误地完成操作步骤。 其中所需的具体信息可在(rel_data)及(rel_text)节中找到相应的存储位置以供调用。

4.3程序的链接

4.3.1 动态链接共享库

静态库存在一些局限性:
以每个运行进程的代码段为基础构建了基础库函数(如printf),这种做法在处理大量并行运行的系统时会导致内存资源的巨大浪费。
这些基础函数(如printf)最终会被整合到可执行文件中,在磁盘存储空间上将导致数千份可执行文件占用大量存储空间。
开发人员需要密切关注是否有必要升级函数库,并定期重新编译和链接以获取更新。

  • 解决方案: Shared Libraries (共享库)
    是一个目标文件,在其中存储了代码和数据。
    被从程序中提取出来后,在磁盘上有一个备份副本,在内存上也有一个备份副本。
    可以在装入时或运行时动态地被加载,并且能够进行链接操作。
    Window将这一概念称为Dynamic Link Libraries(DLLs),而Linux则称之为Dynamic Shared Objects(SOs)。

4.3.2 动态链接的方式

  • 当首次调用系统服务时触发(即首次调用阶段实施负载静态链表)。
  • 一旦系统服务已进入运行状态后(即处于持续动态链表阶段),则执行动态链表链接。

总结:

1.链接处理涉及到三种目标文件格式:

具备重定位能力的目标文档、运行中的文档和共享文档。例外情况下的库文档是一种特殊的具备重定位能力的目标。

2.链接分为静态链接和动态链接两种

  • 静态链接通过将多个可重定位目标模块中的同类模块中的相同类型节合并组装成一个完整的可执行目标文件,在此过程中所有符号的引用均在虚拟地址空间内确定最终位置以便直接加载运行。
  • 动态链接下的可执行目标文件处于半连接状态其中一部分符号的引用地址尚未固定必须依赖共享库中已定义的具体符号实现位置转换因此必须由动态链接器负责调用共享库完成相关符号的位置转换工作以确保程序能够正确运行。

3.链接过程需要完成符号解析和重定位两方面的工作

  • 符号解析的目标在于将符号与其定义建立关联。
    • 重定位旨在分别整合程序代码和数据对象,并依据它们在虚拟内存地址空间中的位置确定每个符号的具体存储位置。
    • 然后根据该符号的实际内存地址对引用该符号的地方进行相应修改。

全部评论 (0)

还没有任何评论哟~