当在Linux上执行一个动态链接的可执行文件时,动态链接器会被调用作为它的解释器(在本文档中描述的 回答). 如果我的理解没错,运行。
$ ./dynamic_elf
会导致Linux执行。
/lib64/ld-linux.so.2 ./dynamic_elf
我很难理解,这怎么能用于 /proc/self/exe
. 按照上面的逻辑,运行。
$ /proc/self/exe
将导致Linux执行。
/lib64/ld-linux.so.2 /proc/self/exe
现在,当动态链接器试图加载精灵时,在 /proc/self/exe
,这不是指向动态链接器本身吗?ld-linux.so.2
是现在正在运行的可执行文件?
我知道上面的命令是JustWorks,那么我缺少什么呢?
动态链接器得到的不仅仅是调用它的小精灵的路径吗?
这里的语义是否和 畲邦 (#!
)解释器?
正如你所指出的,内核没有将执行的二进制文件作为路径传递给解释器。
$ /lib64/ld-linux-x86-64.so.2 /proc/self/exe
loader cannot load itself
尽管glibc动态链接器支持这种调用方法(提供程序作为参数运行),但在正常执行一个被解释的ELF二进制文件的过程中,它并没有被使用。事实上,内核将execve的参数不加修改地提供给动态链接器。
动态链接器根本不 "加载 "或 "执行 "被解释的ELF二进制文件。内核加载的是 两者 解释器和被解释的二进制进入内存,并在解释器的入口处开始执行。解释二进制的入口点通过解释器的 AT_ENTRY
字段的辅助向量。
然后动态链接器会预先执行必要的运行时链接,并跳转到 "真正的 "入口点。
如果你在执行一个正常解释的ELF可执行文件时,在_start上设置一个断点,你可以在gdb中观察到这一切。使用 "show args",你会看到 "真正的 "argv,没有任何额外的值,而且进程的内存映射已经加载了解释的二进制(在解释器运行一条指令之前)。
#!
脚本的工作方式和你期望的一样(实际上是在操作argv值)。