内核如何获得在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