和...之间的不同.plt
and .plt.got
就是它.plt
使用惰性绑定和.plt.got
使用非惰性绑定。
当函数的所有使用都是简单的函数调用时,延迟绑定是可能的。但是,如果有任何东西需要函数的地址,则必须使用非延迟绑定,因为绑定只能在调用函数时发生,并且我们可能需要在第一次调用之前知道地址。注意,获取地址时,直接访问GOT表项;只有函数调用经过.plt
and .plt.got
。
如果-fno-plt
使用编译器选项,则两者都不是.plt
nor .plt.got
被发出,函数调用也直接访问 GOT 条目。
在以下示例中,objdump -d
用于拆卸,并且readelf -r
用于列出重定位。
.plt
以 x64-64 为例,.plt
将包含以下条目:
0000000000014050 <_Unwind_Resume@plt>:
14050: ff 25 3a e6 0e 00 jmpq *0xee63a(%rip) # 102690 <_Unwind_Resume@GCC_3.0>
14056: 68 02 00 00 00 pushq $0x2
1405b: e9 c0 ff ff ff jmpq 14020 <.plt>
首先jmpq
是到 GOT 条目,第二个jmpq
如果 GOT 条目尚未绑定,则执行惰性绑定。
此次搬迁为.plt
的相关 GOT 条目位于.rela.plt
部分和用途R_X86_64_JUMP_SLOT
,这让动态链接器知道这些是惰性的。
0000000000102690 0000004600000007 R_X86_64_JUMP_SLOT 0000000000000000 _Unwind_Resume@GCC_3.0 + 0
.plt.got
.plt.got
包含只需要一个的条目jmpq
因为他们并不懒惰:
0000000000014060 <memset@plt>:
14060: ff 25 5a ea 0e 00 jmpq *0xeea5a(%rip) # 102ac0 <memset@GLIBC_2.2.5>
14066: 66 90 xchg %ax,%ax
此次搬迁为.plt.got
的相关 GOT 条目位于.rela.dyn
部分(以及 GOT 重定位的其余部分),动态链接器立即绑定:
0000000000102ac0 0000004b00000006 R_X86_64_GLOB_DAT 0000000000000000 memset@GLIBC_2.2.5 + 0