返回

iOS 静态链接器 ld64 原理解析(上)

IOS

ld64 是 iOS 平台上的静态链接器,负责将多个目标文件(.o 文件)链接成一个可执行文件(Mach-O 文件)。ld64 的工作原理较为复杂,涉及到符号解析、重定位、代码合并等多个步骤。本文将从 ld64 源码角度深入剖析 ld64 的工作原理,以帮助读者了解 ld64 如何将多个目标文件链接成一个可执行文件。

ld64 的整体架构

ld64 的整体架构可以分为以下几个部分:

  • 输入处理: ld64 首先需要读取并解析输入的目标文件,提取其中的符号信息、重定位信息和代码段等信息。
  • 符号解析: ld64 会对输入的目标文件中的符号进行解析,确定每个符号的最终地址。
  • 重定位: ld64 会对输入的目标文件中的重定位信息进行处理,将符号的地址更新为最终地址。
  • 代码合并: ld64 会将输入的目标文件中的代码段合并成一个连续的代码段,并将其写入可执行文件。
  • 输出处理: ld64 会将链接后的可执行文件写入磁盘,并生成相应的符号表和重定位表。

符号解析

符号解析是 ld64 工作中的一个重要步骤,其目的是确定每个符号的最终地址。ld64 会先对输入的目标文件中的符号进行分类,将其分为以下几类:

  • 全局符号: 这些符号在整个可执行文件中都是可见的。
  • 局部符号: 这些符号只在定义它们的源文件中可见。
  • 外部符号: 这些符号在其他文件中定义,但在当前文件中被引用。

ld64 会先解析全局符号,然后解析局部符号,最后解析外部符号。对于全局符号,ld64 会将其地址设置为它在可执行文件中的实际地址。对于局部符号,ld64 会将其地址设置为它在源文件中的相对地址。对于外部符号,ld64 会先尝试在其他文件中找到它的定义,然后将其地址设置为它在其他文件中的实际地址。如果找不到它的定义,ld64 就会报错。

重定位

重定位是 ld64 工作中的另一个重要步骤,其目的是将符号的地址更新为最终地址。ld64 会先对输入的目标文件中的重定位信息进行分类,将其分为以下几类:

  • 绝对重定位: 这些重定位信息只依赖于一个符号的地址。
  • 相对重定位: 这些重定位信息依赖于两个符号的地址。
  • PCRel重定位: 这些重定位信息依赖于程序计数器(PC)的地址。

ld64 会先处理绝对重定位信息,然后处理相对重定位信息,最后处理 PCRel 重定位信息。对于绝对重定位信息,ld64 会直接将符号的地址更新为最终地址。对于相对重定位信息,ld64 会先计算出两个符号的地址差,然后将其加上程序计数器(PC)的地址,得到最终地址。对于 PCRel 重定位信息,ld64 会先计算出程序计数器(PC)的地址,然后将其加上重定位信息的偏移量,得到最终地址。

代码合并

代码合并是 ld64 工作中的最后一步,其目的是将输入的目标文件中的代码段合并成一个连续的代码段,并将其写入可执行文件。ld64 会先将输入的目标文件中的代码段按照它们的地址排序,然后将其合并成一个连续的代码段。最后,ld64 会将合并后的代码段写入可执行文件。

Mach-O 文件格式

Mach-O 是苹果平台上的一种可执行文件格式,ld64 会将链接后的可执行文件写入 Mach-O 文件格式。Mach-O 文件格式由以下几个部分组成:

  • Mach-O 头: Mach-O 头包含了可执行文件的基本信息,例如文件的类型、架构、入口点地址等。
  • 载入命令: 载入命令了可执行文件的各个部分,例如代码段、数据段、符号表等。
  • 段: 段是可执行文件的逻辑单位,它可以包含代码、数据或其他信息。
  • 符号表: 符号表包含了可执行文件中的所有符号信息,例如符号的名称、地址、类型等。
  • 重定位表: 重定位表包含了可执行文件中的所有重定位信息,例如重定位信息的地址、类型、偏移量等。

总结

本文从 ld64 源码角度深入剖析了 ld64 的工作原理,以帮助读者了解 ld64 如何将多个目标文件链接成一个可执行文件。文章内容包括 ld64 的整体架构、符号解析、重定位、代码合并以及 Mach-O 文件格式的解析。