linux - Linux内核如何确定ld.so的加载地址?

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

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

最佳答案

阅读更多关于 ELF 的信息, 特别是 elf(5) ,以及关于 execve(2)系统调用。

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

PT_INTERP The array element specifies the location and size of a null-terminated pathname to invoke as an interpreter. This segment type is meaningful only for executable files (though it may occur for shared objects). However it may not occur more than once in a file. If it is present, it must precede any loadable segment entry.

那个解释器几乎总是 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)系统调用正在使用该解释器:

If the executable is a dynamically linked ELF executable, the interpreter named in the PT_INTERP segment is used to load the needed shared libraries. This interpreter is typically /lib/ld-linux.so.2 for binaries linked with glibc.

另请参阅 Levine 关于 Linkers and loaders 的书, 和 Drepper'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 似乎出现在内核源代码中)

关于linux - Linux内核如何确定ld.so的加载地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29856044/

相关文章:

linux - SQLite 数据库构建加速

linux - Mesa-18.1.6 'c compiler cannot create executables'

x86 - 是否可以矢量化 myNum += a[b[i]] * c[i];在 x86_64 上?

linux - 为什么在返回 MEMORY 类型时返回 %rax 中的对象地址?

linux - 为什么 lspci 会列出 pcie 设备?

linux - 如何在后台运行 eval spawn ssh 和 expect?

c - 谁在驱动代码中调用了 "probe"函数?

c - 将文件映射到内存并写入文件末尾

assembly - Yasm 与 64 位指令

linux - 未提供 http 静态目录