对 动态链接中 Lazy_Linkage 进行调式 —— 以 func.ELF2 调用 func 函数为例
首先是用 gdb 打开 func.ELF2 中间文件,并在 main 函数处打上断点
run 起来,可以看到 <main + 0> 到 <main + 7> 是程序运行的准备工作,下一条指令是 int a = 100,对应的汇编指令是 <main + 8> mov DWORD PTR [rbp-0x4], 0x64
步过赋值语句,我们步入 func 函数
可以看到我们已经来到了 func 函数的内部
接下来不停地单步,可以看到 <func + 18> 处有对 0x7ffff7dd1fd8 的操作,最后会在 <func + 56> 的地方 ret
func 函数执行完以后,回过头看一下各地址的内容,可以看到 main 函数实际上 call 到了 PLT[2] 的第一个条目
接下来, < func@plt >会 jmp到 0x555555754fd0 处,我们查看一下这里的内容,可以看到是 0x5555d5752793 ;注意,这里应该使用 gx 查看
702823493776)]
这个位置其实是 GOT表的第五项(GOT[4]),查看得到内容为 0x00007ffff7db15da,可以发现这个地址就是 func 函数在运行时候的真实地址,也就是说动态链接过程中,< func@plt >会将地址 0x555555754fd0 与 func 函数运行的真实地址进行绑定;绑定的方法是执行 < func@plt+6 >、< func@plt +11>跳转到 0x555555554610 ,也就是PLT[0] 的第一个条目,它会先将 GOT[0] 压栈,然后调用 GOT[2](一个动态链接器的函数),从而完成符号解析和重定位工作;下次再调用 func 函数,就可以跳过绑定直接到达真实地址开始运行。