Linux ELF64加载程序如何知道更新.get.plt中的初始地址?

Linux ELF64加载程序如何知道更新.get.plt中的初始地址?,linux,elf,glibc,Linux,Elf,Glibc,考虑以下程序hello.c: #include <stdio.h> int main(int argc, char** argv) { printf("hello"); return 0; } 这是对应PLT条目中第二条指令相对于段开始的偏移量 用starti启动并链接程序后,p'printf@got.plt“现在给出 $2 = (<text from jump slot in .got.plt, no debug info>) 0x555555555

考虑以下程序
hello.c

#include <stdio.h>

int main(int argc, char** argv)
{
    printf("hello");
    return 0;
}
这是对应PLT条目中第二条指令相对于段开始的偏移量

starti
启动并链接程序后,
p'printf@got.plt“
现在给出

$2 = (<text from jump slot in .got.plt, no debug info>) 0x555555555036 <printf@plt+6>
readelf-r simple
显示此地址的重新定位条目

Relocation section '.rela.plt' at offset 0x550 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000004018  000200000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0
但我对第76页的理解是,这些重定位条目仅在
LD_BIND_NOW
为非空时使用。是否有我遗漏的其他搬迁条目?相对于GOT的最终地址,重定偏移量的机制是什么?

根据Drepper的说法,动态链接器重新定位两种依赖关系:

  • 相对重新定位:对同一对象内位置的依赖关系。链接器只是将对象的加载地址添加到目标的偏移量中
  • 符号重新定位:基于复杂符号解析算法的更复杂、更昂贵的过程
  • 对于PLT的GOT,Drepper在启动时声明(§1.5.5),动态链接器使用指向相应PLT条目的第二条指令的地址填充GOT插槽。阅读源代码表明链接器确实在
    R_X86_64_JUMP_SLOT
    重定位(
    elf/do rel.h:elf_dynamic_do_rel
    )中循环,并增加它们包含的偏移量(
    sysdeps/X86_64/dl machine.h:elf_machine\u lazy_rel
    ):

    使用延迟PLT绑定时(默认情况)。

    根据Drepper的说法,动态链接器会重新定位两种依赖关系:

  • 相对重新定位:对同一对象内位置的依赖关系。链接器只是将对象的加载地址添加到目标的偏移量中
  • 符号重新定位:基于复杂符号解析算法的更复杂、更昂贵的过程
  • 对于PLT的GOT,Drepper在启动时声明(§1.5.5),动态链接器使用指向相应PLT条目的第二条指令的地址填充GOT插槽。阅读源代码表明链接器确实在
    R_X86_64_JUMP_SLOT
    重定位(
    elf/do rel.h:elf_dynamic_do_rel
    )中循环,并增加它们包含的偏移量(
    sysdeps/X86_64/dl machine.h:elf_machine\u lazy_rel
    ):


    当使用延迟PLT绑定时(默认情况)。

    在进一步挖掘之后,在我看来,链接器/加载器确实使用
    R\u X86\u 64\u JUMP\u SLO
    重定位条目,在加载包含
    .PLT.get
    的段时,将偏移量重设到PLT中。相关的源代码似乎位于glibc中的
    elf/do rel.h:elf\u dynamic\u do\u rel
    sysdeps/x86\u 64/dl machine.h:elf\u machine\u lazy\u rel
    。由于我不完全理解elf加载程序代码,欢迎任何专家对此进行确认!解释得很透彻,也许没有答案能做得更好。谢谢@MaximeGroushkin。我通读了你建议的参考资料,我想你可能是对的。我已经用我目前理解的所有内容添加了一个答案。在进一步挖掘之后,在我看来,链接器/加载器确实使用了
    R\u X86\u 64\u JUMP\u SLO
    重定位条目,以便在加载包含
    .PLT.get
    的段时将偏移量重设为PLT。相关的源代码似乎位于glibc中的
    elf/do rel.h:elf\u dynamic\u do\u rel
    sysdeps/x86\u 64/dl machine.h:elf\u machine\u lazy\u rel
    。由于我不完全理解elf加载程序代码,欢迎任何专家对此进行确认!解释得很透彻,也许没有答案能做得更好。谢谢@MaximeGroushkin。我通读了你建议的参考资料,我想你可能是对的。我已经添加了一个答案,包含了我目前理解的所有内容。
    $1 = (<text from jump slot in .got.plt, no debug info> *) 0x4018 <printf@got.plt>
    
    Relocation section '.rela.plt' at offset 0x550 contains 1 entry:
      Offset          Info           Type           Sym. Value    Sym. Name + Addend
    000000004018  000200000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0
    
    if (__glibc_likely (r_type == R_X86_64_JUMP_SLOT))
      {
        /* Prelink has been deprecated.  */
        if (__glibc_likely (map->l_mach.plt == 0))
          *reloc_addr += l_addr;
        else
          ...