ELF是linux中使用最广泛的一种应用程序格式,为了弄清楚Linux内核是如何讲ELF文件精确映射到指定内存空间,上周末把内核sys_execve部分好好看了一遍,小结如下:
1. ELF格式
ELF指定了进程中text段、bss段、data段等应该放置到进程虚拟内存空间的什么位置,以及记录了进程需要用到的各种动态链接库的位置。
2. sys_execve的大致执行流程
1) 打开ELF二进制文件,读入ELF头
2) 删除从父进程继承过来的mm相关内容
3) 根据ELF头将interpreter段、text段、data段等映射进内存(由此知linux不支持压缩了的二进制程序)
设置好堆栈等,更新mm内容。
4) "伪造"好本进程的内核栈,为进程返回用户态执行做好准备。内核栈中的ip指向了interpreter段入口。
5) sys_execve系统调用返回到用户态,开始interpreter的执行(interpreter一般为linux-ld.so.2 or similar)
进入到用户态后,interpreter做了些什么呢?
6) interpreter帮助用户进程装入动态链接库,做好全部重定位映射工作。
7) interpreter返回到main开始执行。
这里面有几个问题需要深究:
1> sys_execve被调用的时候内核栈长什么样?用户态参数是如何传入到内核的?
只有弄明白了这个问题,才知道如何从内核返回到interpreter入口开始执行
A: 关于这个问题请参考linux系统调用相关章节。linux系统调用采取了一个一致的方法来处理系统调用参数问题,非常值得借鉴,将另外撰文梳理其设计思路。
2> interpreter的参数从哪里来?interpreter如何返回到main?
A: 如果从传统的C语言函数调用的角度来理解,这个问题会很费解。但是如果能从汇编的角度,动态地、有目的地调整和"伪造"调用栈,就能够做到方便地再各个函数间切换和传参。
内核会构造好interpreter所需要的参数栈,interpreter会构造好main所需要的参数栈。用户栈是在setup_arg_pages函数中构建的。
3> 内核是如何保证将各个段映射到期望的位置?
mmap函数有一个参数取MAP_FIXED参数即可。
Linux ELF文件装入与执行概述
最新推荐文章于 2024-09-03 16:00:00 发布