符号重定位

一旦链接器完成了符号解析这一步,它就把代码中的每个符号引用和确定的符号定义(即一个输入目标文件中的符号定义)联系了起来。此时,链接器就知道它的输入目标文件中的.text section和.data section的确切大小,现在就可以开始重定位了。在这个步骤中,链接器将合并多个输入目标文件,并为每个符号分配运行时地址。

重定位操作,主要由两步组成:

  • 重定位section和符号定义:在这一步中,链接器将所有相同类型的节(section)合并为同一类型的新的聚合节。例如,来自输入目标文件的.data节将全部被合并一个节,这个节成为输出的可执行文件的.data节。然后链接器将运行时存储器地址赋值给新的聚合节,输入模块定义的的每个节、每个符号定义,也都将得到新分配的运行时地址。当这一步完成时,程序中的每个指令和全局变量都有唯一的运行时内存地址了。
  • 重定位section中的符号引用:在这一步中,链接器修改.text section和.data section中每个符号的引用,使得它们指向正确的运行时地址。为了执行这一步,链接器依赖于一种称为“重定位条目(relocation entry)”的可重定位目标模块中的数据结构,我们接下来将会描述这种数据结构。

重定位条目

当汇编器生成一个目标模块时,它并不知道数据和代码最终将存放在内存中中的什么位置。它也不知道这个模块引用的任何外部定义的函数或者全局变量的位置。所以,无论何时汇编器遇到对最终位置未知的目标引用,它就会生成一个重定位条目,告诉链接器在将目标文件合并成可执行文件时应如何修改这个引用

代码.text的重定位条目放在.rel.text中,已初始化数据.data的重定位放在.rel.data中。

下面是ELF重定位条目的格式,offset是需要被修改的引用相对于section(.text or .data)的偏移量,symbol标识被修改的引用指向的符号,type告知链接器如何修改新的引用(可重定位类型)。

ps: 简言之就是链接器此时不知道这个引用的具体值,就记下个记录,等后续链接器链接时再参考这里完成更新。

一条重定位记录的含义其实是说,嘿linker,等你链接完成之后,请在offset偏移量这个位置处给我填上正确的符号地址,符号地址的计算规则参考重定位类型。

type struct {
    int offset;        // offset of the reference to relocate
    int symbol:24;    // symbol the reference should point to
    int type:8;        // relocation type
} Elf32_Rel;

ELF定义了11种不同类型的重定位类型,有些类型相当神秘,我们只关心其中两种最基本的重定位类型即可:

  • R_386_PC32:重定位一个使用32位PC相对地址的引用,一个PC相对地址就是距程序计数器(PC)的当前运行时值的偏移量。当CPU执行一条使用PC相对寻址的指令时,它就将在指令中编码的32位值上加上PC的当前运行时值,得到有效地址(如call指令的目标),PC值通常是存储器中下一条指令的地址;
  • R_386_32:重定位一个使用32位绝对地址的引用。通过绝对寻址,CPU直接使用在指令中编码的32位值作为有效地址,不需要进一步修改;

现在我们简要总结一下:

  • 编译过程中只要碰到不认识的符号,就会生成一个重定位条目记录下待解析、待重定位的条目,当链接器解析时它会知道这里面的这些符号需要解析、需要重定位。

  • 解析完成后,链接器就知道某个符号在其定义目标文件中的各个section的大小,最终合并之后的section大小它也知道,偏移量它也知道,更新符号引用处于符号定义处的偏移量简直太简单了。

  • 只是说,约法三章,更新时要求必须按照指定的重定位类型来更新,链接器按照指定的重定位类型来计算符号引用处应该最终使用的值就可以了。

关于这部分的重定位示例,读者可以网上找些资料或者参考深入理解计算系统、Linux二进制分析中的章节。

参考内容

  1. Computer System: A Programmer's Perspective, Randal E.Bryant, David R. O'Hallaron, p450-p479

    深入理解计算机系统, 龚奕利 雷迎春 译, p450-p479

  2. Learning Linux Binary Analysis, Ryan O'Neill, p14-15, p18-19

    Linux二进制分析, 棣琦 译, p14-15, p18-19

results matching ""

    No results matching ""