http://blog.chinaunix.net/uid-24774106-id-3349549.html
更多请搜索got和plt
其实都大同小异
基本思路:
代码中在调用共享库中的函数时(这里是动态延迟绑定)会call一个地址(比如0x08048454),而这个地址中存储的内容是指令
jmp *0x0804a010
0x0804a010是被调用函数在got中的位置
如果是第一次调用这个函数,则这个位置处的值为0x0804845a
jmp *0x0804a010等价于jmp 0x0804845a
而这个0x0804845a是jmp *0x0804a010的下一条指令的地址(说明第一次调用时got项中对应的地址并不是被调用函数的实际绝对地址)
0x0804845a处的指令是push $0x20(立即数0x20是被调用函数的符号在重定位表.rel.plt中的下标)
再后面的指令就是
jmp 0x08048404(这个地址是plt section的地址,每个未被绑定的函数push完标记后都会跳到plt的开头)
plt段的代码会先pushl 0x8049ff8(0x8049ff8是got[1]的地址,里面存放的内容是本模块的id)
然后jmp *0x8049ffc(0x8049ffc是got[2]的地址,而*0x8049ffc则为_dl_runtime_resolve函数的地址0x00123270),所以这条指令是去调用了_dl_runtime_resolve函数
_dl_runtime_resolve函数的调用如下
- 0x123270 <_dl_runtime_resolve>: push %eax
- 0x123271 <_dl_runtime_resolve+1>: push %ecx
- 0x123272 <_dl_runtime_resolve+2>: push %edx
- 0x123273 <_dl_runtime_resolve+3>: mov 0x10(%esp),%edx
- 0x123277 <_dl_runtime_resolve+7>: mov 0xc(%esp),%eax
- 0x12327b <_dl_runtime_resolve+11>: call 0x11d5a0 <_dl_fixup>
- 0x123280 <_dl_runtime_resolve+16>: pop %edx
- 0x123281 <_dl_runtime_resolve+17>: mov (%esp),%ecx
- 0x123284 <_dl_runtime_resolve+20>: mov %eax,(%esp)
- 0x123287 <_dl_runtime_resolve+23>: mov 0x4(%esp),%eax
然后去调用相应的被调用函数
上面是第一次,以后再调用相同的被调用函数时,由于got相应的项中存储的已经是实际地址,所以就可以直接调用了