“.got”和“.got.plt”部分有什么区别?

29

.got和.got.plt在ELF格式中有何区别?


1
根据 http://www.acsu.buffalo.edu/~charngda/elf.html,`.got` 条目永远不会被惰性解析,但 .got.plt 条目可以被惰性解析。 - ninjalj
7
我认为 .got 用于全局“变量”的重定位,而 .got.plt 是一个辅助部分,与 .plt 一起解析过程的绝对地址。 - JohnTortugo
1个回答

25

我的先前的评论证明是正确的:

我认为.got用于涉及全局“变量”的重定位,而.got.plt则是一个辅助部分,与.plt一起解析过程的绝对地址。

下面的示例使事情更加清晰。

这些是我的32位i686-linux /lib/libm.so的重定位。

Relocation section '.rel.dyn' at offset 0x32b8 contains 8 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00025030  00000008 R_386_RELATIVE   
00024fd8  00005706 R_386_GLOB_DAT    00025034   _LIB_VERSION
00024fdc  00000406 R_386_GLOB_DAT    00000000   __gmon_start__
00024fe0  00000506 R_386_GLOB_DAT    00000000   _Jv_RegisterClasses
00024fe4  00000806 R_386_GLOB_DAT    00000000   _rtld_global_ro
00024fe8  00000906 R_386_GLOB_DAT    00000000   stderr
00024fec  00013006 R_386_GLOB_DAT    0002507c   signgam
00024ff0  00000e06 R_386_GLOB_DAT    00000000   __cxa_finalize

Relocation section '.rel.plt' at offset 0x32f8 contains 12 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00025000  00000107 R_386_JUMP_SLOT   00000000   fputs
00025004  00000207 R_386_JUMP_SLOT   00000000   __errno_location
00025008  00000307 R_386_JUMP_SLOT   00000000   sprintf
0002500c  00000407 R_386_JUMP_SLOT   00000000   __gmon_start__
00025010  00000607 R_386_JUMP_SLOT   00000000   strtod
00025014  00000707 R_386_JUMP_SLOT   00000000   __assert_fail
00025018  00000a07 R_386_JUMP_SLOT   00000000   strlen
0002501c  00000b07 R_386_JUMP_SLOT   00000000   strtof
00025020  00000c07 R_386_JUMP_SLOT   00000000   fwrite
00025024  00000d07 R_386_JUMP_SLOT   00000000   strtold
00025028  00005e07 R_386_JUMP_SLOT   00005970   matherr
0002502c  00000e07 R_386_JUMP_SLOT   00000000   __cxa_finalize

注意到有两个重定位节,即.rel.dyn和.rel.plt。你可以看到.rel.plt中的所有重定位都是R_386_JUMP_SLOT类型,这意味着它们是分支重定位; 另一方面,.rel.dyn中的几乎所有重定位都是R_386_GLOB_DAT类型,这意味着它们是全局变量的重定位。

.symtab和.dynsym之间还存在另一个微妙的差别。前者包含了静态链接编辑过程中使用的所有符号的引用,而后者只包含了动态链接所需的符号。因此,上述提到的重定位仅涉及.dynsym部分。


2
如果我没记错的话,对于那些地址被获取的函数,也需要一个.got条目;编译器通常选择要求对它们进行早期绑定,以便它们可以从GOT中加载最终地址,而不仅仅是将PLT存根的地址作为函数指针。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接