.got和.got.plt在ELF格式中有何区别?
我的先前的评论证明是正确的:
我认为
.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部分。
.got
条目;编译器通常选择要求对它们进行早期绑定,以便它们可以从GOT中加载最终地址,而不仅仅是将PLT存根的地址作为函数指针。 - Peter Cordes
.got.plt
条目可以被惰性解析。 - ninjalj