ELF重定位

重定位就是将符号定义和符号引用进行连接的过程。

在重定位文件中,重定位记录保存了如何对给定的符号进行补充相关的信息

假设obj1.c代码如下

_start()
{
    foo();
    int a = 1;
    foo1();
}
gcc -c obj1.c

当经过上述编译生成 obj1.o 对象文件后,我们并不知道 foo、foo1两个函数的地址。此时,我们只能在代码段里使用占位符站着,并记录一些重定位的信息

[root@izbp1irxwqt7ei21awv6wvz reloc]# objdump -d obj1.o
Disassembly of section .text:

0000000000000000 <_start>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
   8:   b8 00 00 00 00          mov    $0x0,%eax
   d:   e8 00 00 00 00          callq  12 <_start+0x12>
  12:   c7 45 fc 01 00 00 00    movl   $0x1,-0x4(%rbp)
  19:   b8 00 00 00 00          mov    $0x0,%eax
  1e:   e8 00 00 00 00          callq  23 <_start+0x23>
  23:   c9                      leaveq 
  24:   c3                      retq

从上面反编译可以看出,foo地址和foo1地址全部为 00 00 00 00

接下来我们查看重定位段里的内容

[root@izbp1irxwqt7ei21awv6wvz reloc]# readelf -r obj1.o

Relocation section '.rela.text' at offset 0x250 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
00000000000e  000900000002 R_X86_64_PC32     0000000000000000 foo - 4
00000000001f  000a00000002 R_X86_64_PC32     0000000000000000 foo1 - 4

这里的offset代表到程序入口点的偏移量(即_start),最后的-4代表地址长度为4字节

下面是重定位条目的结构体

//重定位
typedef struct elf_internal_rela {
  unsigned long r_offset; /* Location at which to apply the action */
  unsigned long r_info;   /* Index and Type of relocation */
  unsigned long r_addend; /* Constant addend used to compute value */
} Elf_Internal_Rela;

有了上述信息,链接器在链接的时候就可以根据重定位条目的信息再相应代码段里补全相关信息即可。

可重定位对象文件需要在被链接的时候需要用到符号表,所以如果对一个可重定位对象文件使用了 strip 去符号表命令,那么该文件不能被链接成功



参考:

linux二进制分析

上一篇: ELF节头
下一篇: ELF程序头
作者邮箱: 203328517@qq.com