返回

LLVM+Clang+编译器+链接器--保值【进阶之路二】

IOS

正文

前言

相信上一篇进阶之路一,对如何编译器把源代码经过一个多层次编译最终变为可执行文件的流程有了初步的认识。我们知道一个可执行文件最终是存储在硬盘磁盘中,当执行一个应用程序时,首先需要将可执行文件从硬盘复制到内存中,当程序开始执行时,这些符号是如何找到真实的地址的呢,这篇文章将会带大家一起了解。

介绍

iOS系统是基于Mach内核的,我们可以看到,链接器的作用是将许多目标文件链接为一个可执行文件,这个目标文件可以是静态库、动态库或者另一个可执行文件,在链接器的工作流程中,它会把各个目标文件的文件符号解析、去重后将这些目标文件的代码段、数据段合成在一起。在这个过程中,如果一个符号在所有目标文件都是定义过的,则该符号在整个可执行文件中只有唯一的定义,对这样的符号,链接器会确定一个符号地址,在各个目标文件中,如果出现对该符号的引用,那么引用处会修改为符号地址,否则引用者会报错。

链接流程解析

链接器是一个程序,它把多个目标文件合并成一个单一的可执行文件。链接器有两个主要任务:

  • 符号解析。链接器必须确定每个符号在可执行文件中的地址。
  • 重定位。链接器必须修改对符号的引用,使其指向正确的地址。

符号解析

符号解析是链接器的第一步。链接器从每个目标文件中读取符号表,并将其合并成一个单一的符号表。符号表是一个数据结构,其中包含每个符号的名称、类型和地址。

链接器使用符号表来确定每个符号在可执行文件中的地址。对于每个符号,链接器都会检查它是否在其他目标文件中定义过。如果符号在其他目标文件中定义过,那么链接器会选择其中一个定义作为符号的最终地址。如果符号在其他目标文件中没有定义过,那么链接器会为它分配一个新的地址。

重定位

重定位是链接器的第二步。重定位是指修改对符号的引用,使其指向正确的地址。链接器使用重定位表来执行重定位。重定位表是一个数据结构,其中包含每个对符号的引用及其相应的地址。

当链接器修改对符号的引用时,它会使用重定位表来查找正确的地址。链接器将对符号的引用修改为正确的地址,并将修改后的引用写入可执行文件。

保值链接

保值链接是链接器的一种特殊模式。在保值链接模式下,链接器不会将目标文件合并成一个单一的可执行文件。相反,链接器会将目标文件合并成一个共享库。共享库是一个二进制文件,其中包含多个目标文件的代码和数据。

共享库可以在多个程序中使用。当一个程序加载时,它会将共享库加载到内存中。然后,程序可以调用共享库中的函数和变量。

符号是如何保值的?

在保值链接模式下,符号是通过使用符号表和重定位表来保值的。符号表包含每个符号的名称、类型和地址。重定位表包含每个对符号的引用及其相应的地址。

当一个程序加载时,加载程序会将符号表和重定位表加载到内存中。然后,加载程序会使用符号表和重定位表来确定每个符号在内存中的地址。

加载程序将对符号的引用修改为正确的地址,并将修改后的引用写入内存。

总结

链接器是一个程序,它把多个目标文件合并成一个单一的可执行文件或共享库。链接器有两个主要任务:符号解析和重定位。

在保值链接模式下,链接器不会将目标文件合并成一个单一的可执行文件。相反,链接器会将目标文件合并成一个共享库。共享库可以在多个程序中使用。