内核如何获得在linux下运行的可执行二进制文件?
这似乎是一个简单的问题,但任何人都可以帮助我深入挖掘?如何将文件加载到内存以及如何启动执行代码?
任何人都可以帮助我,一步一步地告诉我们发生了什么吗?
Cir*_*四事件 29
exec
在Linux 4.0上系统调用的最佳时刻
找到所有这些的最好方法是使用QEMU GDB步骤调试内核:如何使用GDB和QEMU调试Linux内核?
fs/exec.c
定义系统调用 SYSCALL_DEFINE3(execve
简单地转发到do_execve
.
do_execve
前往do_execveat_common
.
do_execveat_common
要查找下一个主要功能,请跟踪retval
上次修改返回值的时间.
开始构建a struct linux_binprm *bprm
来描述程序,并将其传递exec_binprm
给执行.
exec_binprm
再次按照返回值查找下一个主要调用.
search_binary_handler
处理程序由可执行文件的第一个魔术字节确定.
两个最常见的处理程序是解释文件(#!
魔术)和ELF(\x7fELF
魔术)的处理程序,但内核中还有其他内置程序,例如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;
}
Run Code Online (Sandbox Code Playgroud)
并且elf_format
是struct linux_binfmt
在该文件中定义的.
__init
是魔术并将该代码放入一个魔术部分,在内核启动时调用它:__ init在Linux内核代码中意味着什么?
链接器级依赖注入!
如果解释器无限地执行自身,则还有一个递归计数器.
试试这个:
echo '#!/tmp/a' > /tmp/a
chmod +x /tmp/a
/tmp/a
Run Code Online (Sandbox Code Playgroud)我们再次按照返回值查看接下来会发生什么,并看到它来自:
retval = fmt->load_binary(bprm);
Run Code Online (Sandbox Code Playgroud)
load_binary
为struct上的每个处理程序定义where :C风格的polymorsphism.
fs/binfmt_elf.c:load_binary
实际工作是否:
struct pt_regs
,注册成a start_thread
)struct pt_regs
,这是它真正开始安排的地方TODO:继续进行源分析.我期望接下来会发生什么:
/lib64/ld-linux-x86-64.so.2
).dlopen
它们进行处理dlopen
使用可配置的搜索路径来查找这些库(ldd
和朋友),将它们映射到内存,并以某种方式通知ELF在哪里找到它缺少的符号_start
ELF来自linux内核的两个系统调用是相关的.该叉系统调用(或许或)用于创建新的进程,类似于调用一个(每个Linux用户空间的过程,除了通过创建或朋友).所述的execve系统调用用新鲜(基本上由排序的替换进程地址空间MMAP从ELF可执行和匿名的段,然后初始化寄存器,包括堆栈指针-ing段).该X86-64 ABI补充和Linux的装配HOWTO透露详情.vfork
clone
init
fork
动态链接发生在文件之后execve
并且涉及/lib/x86_64-linux-gnu/ld-2.13.so
文件,ELF被视为"解释器".
您可以从了解可执行文件格式开始,例如 ELF。 http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
ELF 文件包含多个部分,其中的标头描述了二进制文件的各个部分应如何以及在何处加载到内存中。
然后,我建议阅读 linux 加载二进制文件和处理动态链接的部分ld-linux。这也是对 ld-linux 的一个很好的描述:http://www.cs.virginia.edu/~dww4s/articles/ld_linux.html
归档时间: |
|
查看次数: |
12774 次 |
最近记录: |