Linux内核如何确定ld.so的加载地址?
How does the Linux kernel determine ld.so's load address?
我知道动态链接器使用 mmap()
加载库。我猜是内核将可执行文件及其 .interp
reter 加载到同一地址 space,但它如何确定位置?我注意到禁用 ASLR 的 ld.so
的加载地址是 0x555555554000
(在 x86_64 上)——这个地址来自哪里?我尝试遵循 do_execve()
的代码路径,但它太复杂了,我不至于被搞糊涂。
阅读更多关于 ELF, in particular elf(5), and about the 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) (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) 系统调用正在使用该解释器:
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, and 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 似乎出现在内核源代码中)
我知道动态链接器使用 mmap()
加载库。我猜是内核将可执行文件及其 .interp
reter 加载到同一地址 space,但它如何确定位置?我注意到禁用 ASLR 的 ld.so
的加载地址是 0x555555554000
(在 x86_64 上)——这个地址来自哪里?我尝试遵循 do_execve()
的代码路径,但它太复杂了,我不至于被搞糊涂。
阅读更多关于 ELF, in particular elf(5), and about the 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) (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) 系统调用正在使用该解释器:
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, and 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 似乎出现在内核源代码中)