内核如何获得在Linux下运行的可执行二进制文件?
内核如何获得在Linux下运行的可执行二进制文件?
这似乎是一个简单的问题,但任何人都可以帮我深挖? 如何将文件加载到内存以及如何开始执行代码?
任何人都可以帮助我,并一步一步告诉发生了什么?
Linux 4.0上exec系统调用的最佳时刻
-
fs/exec.c在SYSCALL_DEFINE3(execve定义系统调用简单地转发到
do_execve。 -
do_execve转发到
do_execveat_common。 -
do_execveat_common要查找下一个主要函数,请跟踪返回值
retval最后修改的时间。开始构build一个
struct linux_binprm *bprm来描述程序,并将其传递给exec_binprm来执行。 -
exec_binprm再次,按照返回值来查找下一个主要调用。
-
search_binary_handler-
处理程序由可执行文件的第一个魔术字节决定。
两个最常见的处理程序是用于解释文件(
#!magic)和ELF(\x7fELFmagic)的处理程序,但还有其他内置的内核,例如a.out。 用户也可以通过/ proc / sys / fs / binfmt_misc注册自己的ELF处理程序在
fs/binfmt_elf.c定义。 -
formats列表包含所有的处理程序。每个处理程序文件包含如下所示
static int __init init_elf_binfmt(void) { register_binfmt(&elf_format); return 0; }而
elf_format是在该文件中定义的struct linux_binfmt。__init是神奇的,并将这些代码放入一个魔术部分,当内核启动时会被调用: __init在Linux内核代码中的含义是什么?链接器级别的dependency injection!
-
还有一个recursion计数器,以防解释器无限地执行。
尝试这个:
echo '#!/tmp/a' > /tmp/a chmod +x /tmp/a /tmp/a -
我们再次遵循返回值来看看接下来会发生什么,并且看到它来自:
retval = fmt->load_binary(bprm);其中
load_binary是为结构上的每个处理程序定义的:C风格的多态。
-
-
fs/binfmt_elf.c:load_binary是否实际工作:
- 根据规格parsingELF文件
- 根据parsing的ELF(内存到一个
struct linux_binprm,注册到一个struct pt_regs)设置进程的初始程序状态。 - 调用
start_thread,这是真正开始计划的地方
待办事项:进一步继续进行来源分析。 我期望接下来会发生什么:
- 内核分析ELF的
/lib64/ld-linux-x86-64.so.2头以finddynamic加载器(通常设置为/lib64/ld-linux-x86-64.so.2)。 - 内核将dynamic加载器和要执行的ELF映射到内存
- 启动dynamic加载程序,在内存中带一个指向ELF的指针。
- 现在在userland,加载器以某种方式parsing精灵标题,并且对它们进行
dlopen -
dlopen使用可configuration的searchpath来查找这些库(ldd和friends),将它们映射到内存中,并以某种方式通知ELF在哪里find其丢失的符号 - 加载器调用ELF的
_start
来自linux内核的两个系统调用是相关的。 fork系统调用(或者vfork或者clone )被用来创build一个新的进程,类似于调用的进程(除了init之外,每个Linux用户登陆进程都由fork或者朋友创build)。 execve系统调用用一个新的进程地址空间replace进程地址空间(主要是通过ELF可执行文件和匿名段的mmap-段的sorting,然后初始化寄存器,包括堆栈指针)。 x86-64 ABI补充和Linux组件如何提供细节。
dynamic链接发生在execve之后,涉及/lib/x86_64-linux-gnu/ld-2.13.so文件,ELF被视为“解释器”。
阅读已经引用的ELF文档后,您应该只是读取实际执行的内核代码 。
如果您在理解代码时遇到困难,请构build一个UML Linux ,然后您可以在debugging器中遍历该代码。
您可以从理解可执行文件格式(如ELF)开始。 http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
ELF文件包含几个标题部分,描述应该如何将部分二进制文件加载到内存中。
然后,我build议读一下加载二进制文件和处理dynamic链接的linux部分, ld-linux 。 这也是对ld-linux的一个很好的描述: http : //www.cs.virginia.edu/~dww4s/articles/ld_linux.html