Linux内核如何确定ld.so的加载地址? [英] How does the Linux kernel determine ld.so's load address?

查看:466
本文介绍了Linux内核如何确定ld.so的加载地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道动态链接器使用mmap()来加载库.我猜是内核将可执行文件及其.interp reter都加载到了相同的地址空间中,但是它如何确定位置呢?我注意到在禁用了ASLR的情况下,ld.so的加载地址是0x555555554000(在x86_64上)—该地址来自何处?我尝试按照do_execve()的代码路径进行操作,但是对我来说,它的影响太大了,以至于不会混淆为地狱.

I know that the dynamic linker uses mmap() to load libraries. I guess it is the kernel who loads both the executable and its .interpreter into the same address space, but how does it determine where? I noticed that ld.so's load address with ASLR disabled is 0x555555554000 (on x86_64) — where does this address come from? I tried following do_execve()'s code path, but it is too ramified for me not to be confused as hell.

推荐答案

详细了解 ELF ,尤其是 elf(5),以及有关 execve(2) syscall.

Read more about ELF, in particular elf(5), and about the execve(2) syscall.

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

An ELF file may contain an interpreter. elf(5) mentions:

PT_INTERP数组元素指定位置和 以空值结尾的路径名的大小 作为口译员.该细分类型是 仅对可执行文件有意义(尽管 共享对象可能会发生这种情况).但是它 在一个文件中可能不会出现多次.如果 它存在,它必须在任何可加载对象之前 细分条目.

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解释器是动态链接器.

That interpreter is practically almost always ld-linux(8) (e.g. with GNU glibc), more precisely (on my Debian/Sid) /lib64/ld-linux-x86-64.so.2. If you compile musl-libc then build some software with it you'll get a different interpreter, /lib/ld-musl-x86_64.so.1. That ELF interpreter is the dynamic linker.

execve(2) syscall正在使用该解释程序:

The execve(2) syscall is using that interpreter:

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

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在 链接器和加载器 上的书,以及 Drepper的论文:如何编写共享库

See also Levine's book on Linkers and loaders, and Drepper's paper: How To Write Shared Libraries

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

Notice that execve is also handling the shebang (i.e. first line starting with #!); see the Interpreter scripts section of execve(2). BTW, for ELF binaries, execve is doing the equivalent of mmap(2) on some segments.

还请阅读有关 vdso(7) proc(5)& ASLR .在外壳程序中输入cat /proc/self/maps.

Read also about vdso(7), proc(5) & ASLR. Type cat /proc/self/maps in your shell.

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

(I guess, but I am not sure, that the 0x555555554000 address is in the ELF program header of your executable, or perhaps of ld-linux.so; it might also come from the kernel, since 0x55555555 seems to appear in the kernel source code)

这篇关于Linux内核如何确定ld.so的加载地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆