我想知道它是如何精确地工作的。 比方说,我们有下面的代码片段:延迟加载程序
0000000000400400 <[email protected]>:
400400: ff 35 02 0c 20 00 pushq 0x200c02(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
400406: ff 25 04 0c 20 00 jmpq *0x200c04(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
40040c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000400410 <[email protected]>:
400410: ff 25 02 0c 20 00 jmpq *0x200c02(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
400416: 68 00 00 00 00 pushq $0x0
40041b: e9 e0 ff ff ff jmpq 400400 <_init+0x20>
....
40053b: e8 d0 fe ff ff callq 400410 <[email protected]>
所有的printf存根(printf的@ PLT)首先被调用,那么位于0x601018(GOT的范围内)的地址是为了跳进去。
假设这是第一次调用printf:我们找到的值将是0x400416,也就是说下一条指令,对吗?
在代码之后,值0被压入堆栈,然后跳转到0x400400。这里推送一个GOT地址(0x601008),然后跳转到下一个(0x601010):为什么?那里究竟有什么?
此外:何时调用动态链接器以及如何?
您的回答缺少一些细节。特别是,* _dl_runtime_resolve是怎样得到最终指针的?整个过程的更全面的描述:http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/ – 2014-10-12 00:26:35
@EmployedRussian肯定,它不是一个完整的描述,但它回答了OP提出的具体问题。有趣的是,即使你的链接只说“_第一个PLT条目是一个调用程序例程,它位于动态加载程序本身_”,至少我找不到它提供更多细节的地方。 – Jester 2014-10-12 00:40:34