【问题标题】:How does the Linux kernel determine ld.so's load address?Linux内核如何确定ld.so的加载地址?
【发布时间】:2015-04-24 19:38:16
【问题描述】:

我知道动态链接器使用mmap() 来加载库。我猜是内核将可执行文件及其.interpreter 加载到同一个地址空间,但它如何确定在哪里?我注意到ld.so 在禁用 ASLR 的情况下的加载地址是0x555555554000(在 x86_64 上)——这个地址来自哪里?我尝试遵循do_execve() 的代码路径,但它对我来说太过分了,不会被搞得一团糟。

【问题讨论】:

  • 从头开始想象,似乎地址必须由内核选择或编码在文件中。您在内核中寻找证据,您是否尝试过在文件中查找?
  • @ChrisStratton 我剖析了可执行文件和动态链接器——没有任何东西看起来像这个地址。
  • 你为什么要问?你为什么在乎?请编辑您的问题以激发它?您是否正在编写新的动态链接器?

标签: linux linux-kernel x86-64 elf dynamic-linking


【解决方案1】:

详细了解ELF,尤其是elf(5),以及execve(2) 系统调用。

ELF 文件可能包含解释器。 elf(5) 提及:

PT_INTERP 数组元素指定位置和 要调用的以 null 结尾的路径名的大小 作为翻译。此段类型是 仅对可执行文件有意义(尽管 它可能发生在共享对象上)。然而它 在一个文件中不能出现多次。如果 它存在,它必须在任何可加载的 段条目。

该解释器几乎总是ld-linux(8)(例如使用GNU glibc),更准确地说(在我的Debian/Sid 上)/lib64/ld-linux-x86-64.so.2。如果你编译musl-libc,然后用它构建一些软件,你会得到一个不同的解释器,/lib/ld-musl-x86_64.so.1。那个 ELF 解释器是 dynamic linker

execve(2) 系统调用正在使用该解释器:

如果可执行文件是动态链接的 ELF 可执行文件,则 PT_INTERP 段中命名的解释器用于加载所需的 共享库。这个解释器通常是/lib/ld-linux.so.2 对于与 glibc 链接的二进制文件。

另请参阅 Levine 关于 Linkers and loadersDrepper's paper: How To Write Shared Libraries 的书

注意execve 也在处理shebang(即第一行以#! 开头);请参阅execve(2)解释器脚本部分。顺便说一句,对于 ELF 二进制文件,execve 在某些段上与mmap(2) 进行等效

另请阅读vdso(7)proc(5)ASLR。在你的 shell 中输入 cat /proc/self/maps

(我猜,但我不确定,0x55​​5555554000 地址在可执行文件的 ELF 程序头中,或者可能是 ld-linux.so;它也可能来自内核,因为似乎出现了 0x55555555在内核源代码中)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 2021-08-17
    • 2013-07-31
    • 2013-03-10
    • 2017-11-26
    • 2020-07-01
    • 1970-01-01
    相关资源
    最近更新 更多