我知道动态链接器使用mmap()
来加载库。我想是内核将可执行文件及其.interp
reter加载到同一地址空间,但它如何确定在哪里?我注意到ld.so
禁用ASLR的加载地址是0x555555554000
(在x86_64上) - 这个地址来自哪里?我试着遵循do_execve()
的代码路径,但它对我来说太过分枝,不会被混淆为地狱。
答案 0 :(得分:2)
详细了解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 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
。
(我猜,但我不确定,0x555555554000地址是在你的可执行文件的ELF程序头中,或者是ld-linux.so
;它也可能来自内核,因为0x55555555似乎出现在内核源代码中)