2 * This function is _not_ called directly. It is jumped to (so no return
3 * address is on the stack) when attempting to use a symbol that has not yet
4 * been resolved. The first time a jump symbol (such as a function call inside
5 * a shared library) is used (before it gets resolved) it will jump here to
6 * _dl_linux_resolve. When we get called the stack looks like this:
10 * This function saves all the registers, puts a copy of reloc_entry and tpnt
11 * on the stack (as function arguments) then make the function call
12 * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out
13 * where the jump symbol is _really_ supposed to have jumped to and returns
14 * that to us. Once we have that, we overwrite tpnt with this fixed up
15 * address. We then clean up after ourselves, put all the registers back how we
16 * found them, then we jump to where the fixed up address, which is where the
17 * jump symbol that got us here really wanted to jump to in the first place.
18 * found them, then we jump to the fixed up address, which is where the jump
19 * symbol that got us here really wanted to jump to in the first place.
23 /* more info taken from glibc/sysdeps/x86_64/dl-trampoline.S */
27 .global _dl_linux_resolve
28 .type _dl_linux_resolve,%function
32 /* Preserve registers otherwise clobbered. */
41 movq 64(%rsp), %rsi /* Copy args pushed by PLT in register. */
42 movq %rsi, %r11 /* Multiply by 24 */
46 movq 56(%rsp), %rdi /* %rdi: link_map, %rsi: reloc_offset */
47 call _dl_linux_resolver /* Call resolver. */
48 movq %rax, %r11 /* Save return value */
50 /* Get register content back. */
59 addq $72, %rsp /* Adjust stack(PLT did 2 pushes) */
60 jmp *%r11 /* Jump to function address. */
62 .size _dl_linux_resolve,.-_dl_linux_resolve