可执行程序的装载
2016-04-10 15:56
627 查看
可执行程序的装载
20135109 高艺桐
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、预处理、编译、链接和目的文件的格式
1、1可执行程序是怎么得来的
C代码经过编译器的预处理编译、编译成汇编代码、编译器将其编译成目标代码、链接成可执行文件。
预处理负责把include的文件包含进来及宏替换等工作。
预处理之后的文件编译成汇编代码。
汇编代码.s编译成.o
1、2目标文件格式的ELF
常见的文件格式:A.out(最古老的)、 COFF 、PE(windows系统)、 ELF(Linux系统)
ABI应用程序二进制接口,在目标文件中已经是二进制兼容的格式了,目标文件适应到某一种CPU体系结构
ELF格式中主要有3种可执行文件:可重定位文件.o,可执行文件,共享目标文件
一个ELF头在文件的开始,保存了路线图,描述了文件的组织情况
当创建或增加一个进程映像的时候,系统在理论上将拷贝一个文件的段到一个虚拟的内存段
1、3静态链接的ELF可执行文件和进程的地址空间
可执行文件ELF加载到内存中去:代码的数据加载到内存中去
默认ELF文件加载到0x8048000
程序的实际入口0x8048300(启动一个刚加载过可执行文件之后开始执行的入口点)
一般静态链接会将所有代码放在一个代码段
动态链接的进程会有多个代码段
二、可执行程序、共享库和动态链接
2、1装载可执行程序之前的动作
可执行程序的执行环境:shell命令行、main函数的参数和execve参数
shell本身不限制命令行参数的个数,命令行参数的个数受限于命令本身
shell会调用execve将命令行参数和环境传递给可执行程序的main函数
命令行参数和环境变量是如何保存和传递的:execve将原来的执行环境覆盖掉了,shell程序——>execve——>sys_execve然后在初始化新程序堆栈时拷贝进去
先函数调用参数传递,再系统调用参数传递
2、2装载动态链接和运行时动态链接应用举例
动态链接分为:可执行程序装载时动态链接和运行时动态链接
准备.so文件——>编译成libshlbexample.so文件(共享库)——>编译成libdllibexample.so文件(动态装载)
编译main:只提供了shellexample的-L和-l,并没有提供dllibexample的相关信息,只指明了-ldl
三、可执行程序的装载
3、1可执行程序的装载相关关键问题分析
execve和fork都是特殊的系统的调用,当前程序执行到execve系统调用时陷入到内核态,execve加载可执行文件把当前进程的可执行文件覆盖掉,execve返回新的可执行程序的执行起点。
int execve(把命令行和环境参数加载进来)
sys_execve内部会解析可执行文件格式:do_execve->do_execve_common->exec_binprm
search_binaty_handle符合文件格式,对应的解析模块(根据文件头部信息寻找对应的文件格式处理模块)
对于ELF格式的可执行文件执行的是load_elf_binary
elf_format和init_elf_binfnt是观察者模式中的观察者
寻找头文件是被观察者,出现elf格式文件,观察者自动执行elf_format模块
execve系统调用返回用户态从哪里开始执行:load_elf_binary->start_thread(通过修改内核堆栈中EIP的值作为新程序的起点)
3、2sys_execve的内部处理过程
search_binary_handler(寻找可执行文件的处理函数) fmt->load_binary(加载可执行程序的处理函数)
register_binfmt(注册结构体变量)
kernal_read读取文件信息
ELF可执行文件会被默认映射到0x8048000这个地址
需要动态链接的可执行文件先加载连接器ld这个共享库 load_elf_interp(加载动态连接器的起点)
如果是静态链接直接进入elf_entry,elf_entry是新程序的起点
start_thread(如果是静态链接,直接指向main8048000;如果可执行文件是动态链接库,指向动态连接器的起点
3、3使用gdb跟踪sys_execve的内部处理过程
自己实验截图:
(1)克隆,覆盖test.c
test.c文件代码:
(2)生成根文件系统时,将init hello放入rootfs地址中,这样在执行exec文件时,就自动加载hello文件
(二)使用gdb跟踪sys_execve内核函数的处理过程
1、加载符号表,并连接到端口1234
2、设置断点:b sys_execve(可以先停在sys_execve然后再设置其他断点),b load_elf_binary,b start_thread。
3、执行
4、输入c继续执行,输入指令exec,list查看,按s可以跟踪进行到do_execve的内部。
3、4可执行程序的装载与庄生梦蝶的故事
庄周(调用execve的可执行程序)
入睡(调用execve陷入内核)
醒来(系统调用execve返回用户态)
发现自己是蝴蝶(被execve加载的可执行程序)
3、5浅析动态链接的可执行程序装载
动态链接的过程,内核做了什么?动态链接库的依赖会形成一个图
ELF格式中的,.interp和.dynamic需要依赖动态链接器来解析
entry返回到用户态时不是返回到可执行程序规定的起点,返回到动态链接器的程序入口
装载和链接之后ld将CPU的控制权交给可执行程序
动态链接库的装载过程是一个图的遍历过程
四、总结
1、可执行程序的产生:
C语言代码-->编译器预处理-->编译成汇编代码-->汇编器编译成目标代码-->链接成可执行文件,再由操作系统加载到内存中执行。
2、ELF格式中主要有3种可执行文件:可重定位文件.o,可执行文件,共享目标文件。
3、ELF可执行文件会被默认映射到0x8048000这个地址。
4、命令行参数和环境变量是如何进入新程序的堆栈的?
Shell程序-->execve-->sys_execve,然后在初始化新程序堆栈时拷贝进去。
先函数调用参数传递,再系统调用参数传递。
5、当前程序执行到execve系统调用时陷入内核态,在内核中用execve加载可执行文件,把当前进程的可执行文件覆盖掉,execve系统调用返回到新的可执行程序的起点。
6、动态链接库的装载过程是一个图的遍历过程,
ELF格式中的.interp和.dynamic需要依赖动态链接器来解析,entry返回到用户态时不是返回到可执行程序规定的起点,返回到动态链接器的程序入口。
20135109 高艺桐
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、预处理、编译、链接和目的文件的格式
1、1可执行程序是怎么得来的
C代码经过编译器的预处理编译、编译成汇编代码、编译器将其编译成目标代码、链接成可执行文件。
预处理负责把include的文件包含进来及宏替换等工作。
预处理之后的文件编译成汇编代码。
汇编代码.s编译成.o
1、2目标文件格式的ELF
常见的文件格式:A.out(最古老的)、 COFF 、PE(windows系统)、 ELF(Linux系统)
ABI应用程序二进制接口,在目标文件中已经是二进制兼容的格式了,目标文件适应到某一种CPU体系结构
ELF格式中主要有3种可执行文件:可重定位文件.o,可执行文件,共享目标文件
一个ELF头在文件的开始,保存了路线图,描述了文件的组织情况
当创建或增加一个进程映像的时候,系统在理论上将拷贝一个文件的段到一个虚拟的内存段
1、3静态链接的ELF可执行文件和进程的地址空间
可执行文件ELF加载到内存中去:代码的数据加载到内存中去
默认ELF文件加载到0x8048000
程序的实际入口0x8048300(启动一个刚加载过可执行文件之后开始执行的入口点)
一般静态链接会将所有代码放在一个代码段
动态链接的进程会有多个代码段
二、可执行程序、共享库和动态链接
2、1装载可执行程序之前的动作
可执行程序的执行环境:shell命令行、main函数的参数和execve参数
shell本身不限制命令行参数的个数,命令行参数的个数受限于命令本身
shell会调用execve将命令行参数和环境传递给可执行程序的main函数
命令行参数和环境变量是如何保存和传递的:execve将原来的执行环境覆盖掉了,shell程序——>execve——>sys_execve然后在初始化新程序堆栈时拷贝进去
先函数调用参数传递,再系统调用参数传递
2、2装载动态链接和运行时动态链接应用举例
动态链接分为:可执行程序装载时动态链接和运行时动态链接
准备.so文件——>编译成libshlbexample.so文件(共享库)——>编译成libdllibexample.so文件(动态装载)
编译main:只提供了shellexample的-L和-l,并没有提供dllibexample的相关信息,只指明了-ldl
三、可执行程序的装载
3、1可执行程序的装载相关关键问题分析
execve和fork都是特殊的系统的调用,当前程序执行到execve系统调用时陷入到内核态,execve加载可执行文件把当前进程的可执行文件覆盖掉,execve返回新的可执行程序的执行起点。
int execve(把命令行和环境参数加载进来)
sys_execve内部会解析可执行文件格式:do_execve->do_execve_common->exec_binprm
search_binaty_handle符合文件格式,对应的解析模块(根据文件头部信息寻找对应的文件格式处理模块)
对于ELF格式的可执行文件执行的是load_elf_binary
elf_format和init_elf_binfnt是观察者模式中的观察者
寻找头文件是被观察者,出现elf格式文件,观察者自动执行elf_format模块
execve系统调用返回用户态从哪里开始执行:load_elf_binary->start_thread(通过修改内核堆栈中EIP的值作为新程序的起点)
3、2sys_execve的内部处理过程
search_binary_handler(寻找可执行文件的处理函数) fmt->load_binary(加载可执行程序的处理函数)
register_binfmt(注册结构体变量)
kernal_read读取文件信息
ELF可执行文件会被默认映射到0x8048000这个地址
需要动态链接的可执行文件先加载连接器ld这个共享库 load_elf_interp(加载动态连接器的起点)
如果是静态链接直接进入elf_entry,elf_entry是新程序的起点
start_thread(如果是静态链接,直接指向main8048000;如果可执行文件是动态链接库,指向动态连接器的起点
3、3使用gdb跟踪sys_execve的内部处理过程
自己实验截图:
(1)克隆,覆盖test.c
test.c文件代码:
(2)生成根文件系统时,将init hello放入rootfs地址中,这样在执行exec文件时,就自动加载hello文件
(二)使用gdb跟踪sys_execve内核函数的处理过程
1、加载符号表,并连接到端口1234
2、设置断点:b sys_execve(可以先停在sys_execve然后再设置其他断点),b load_elf_binary,b start_thread。
3、执行
4、输入c继续执行,输入指令exec,list查看,按s可以跟踪进行到do_execve的内部。
3、4可执行程序的装载与庄生梦蝶的故事
庄周(调用execve的可执行程序)
入睡(调用execve陷入内核)
醒来(系统调用execve返回用户态)
发现自己是蝴蝶(被execve加载的可执行程序)
3、5浅析动态链接的可执行程序装载
动态链接的过程,内核做了什么?动态链接库的依赖会形成一个图
ELF格式中的,.interp和.dynamic需要依赖动态链接器来解析
entry返回到用户态时不是返回到可执行程序规定的起点,返回到动态链接器的程序入口
装载和链接之后ld将CPU的控制权交给可执行程序
动态链接库的装载过程是一个图的遍历过程
四、总结
1、可执行程序的产生:
C语言代码-->编译器预处理-->编译成汇编代码-->汇编器编译成目标代码-->链接成可执行文件,再由操作系统加载到内存中执行。
2、ELF格式中主要有3种可执行文件:可重定位文件.o,可执行文件,共享目标文件。
3、ELF可执行文件会被默认映射到0x8048000这个地址。
4、命令行参数和环境变量是如何进入新程序的堆栈的?
Shell程序-->execve-->sys_execve,然后在初始化新程序堆栈时拷贝进去。
先函数调用参数传递,再系统调用参数传递。
5、当前程序执行到execve系统调用时陷入内核态,在内核中用execve加载可执行文件,把当前进程的可执行文件覆盖掉,execve系统调用返回到新的可执行程序的起点。
6、动态链接库的装载过程是一个图的遍历过程,
ELF格式中的.interp和.dynamic需要依赖动态链接器来解析,entry返回到用户态时不是返回到可执行程序规定的起点,返回到动态链接器的程序入口。
相关文章推荐
- *windows.event对象在ie与ff中的区别**
- 剑指offer系列之5:用两个栈来实现队列
- shell uniq 和sort 简单用法及实例
- Git入门
- 区间调度问题
- 冒泡排序、选择和插入排序、二分法查找
- servlet/filter/listener/interceptor区别与联系
- 华为OJ题目(二十一):输入n个整数,输出其中最小的k个
- email正则表达式 验证邮箱格式
- ASP.NET MVC4入门教程(四):添加一个模型
- 网站挂马解决方案
- RTSP协议、RTMP协议、HTTP协议的区别
- 1005. 继续(3n+1)猜想 (25)
- 在类中使用类成员函数创建线程
- window对象
- 第六周学习进度
- javascript冒泡排序小结
- tomcat——生命周期管理机制
- 再见 青春
- myeclipse无法创建jsp页面