20135327郭皓--Linux内核分析第七周 可执行程序的装载

时间:2023-11-28 11:19:32

第七周 可执行程序的装载

郭皓 原创作品转载请注明出处 《Linux内核分析》MOOC课程 http://mooc.study.163.com/course/USTC-1000029000

一、预处理,编译,链接和目标文件格式

1.可执行程序是怎么得来的

20135327郭皓--Linux内核分析第七周 可执行程序的装载

c代码->预处理->汇编代码->汇编器->目标代码->链接成可执行文件->加载到内核执行
20135327郭皓--Linux内核分析第七周 可执行程序的装载

2.目标文件的格式ELF

符号修饰标准、变量内层布局、函数调用方式等这些跟可执行代码二进制兼容性相关的内容称为ABI(Application Binary Interface)

常见的ABI格式:

20135327郭皓--Linux内核分析第七周 可执行程序的装载

20135327郭皓--Linux内核分析第七周 可执行程序的装载

3.静态链接的ELF可执行文件和进程的地址空间

20135327郭皓--Linux内核分析第七周 可执行程序的装载

一般静态链接将会把所有代码放在同一个代码段。

20135327郭皓--Linux内核分析第七周 可执行程序的装载

动态连接的进程会有多个代码段。

20135327郭皓--Linux内核分析第七周 可执行程序的装载

二、可执行程序、共享库和动态链接

1.可执行程序的执行环境

  • 命令行参数和shell环境,一般我们执行一个程序的Shell环境,我们的实验直接使用execve系统调用。
  • Shell本身不限制命令行参数的个数,命令行参数的个数受限于命令自身。
  • shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数。
  • 命令行参数和环境串都放在用户态堆栈中。

2.装载时动态链接和运行时动态链接应用举例

  • 动态链接分为可执行程序装载时动态链接和运行时动态链接

三、可执行程序的装载

1.可执行程序的装载相关关键问题分析

execve与fork是比较特殊的系统调用

execve用它加载的可执行文件把当前的进程覆盖掉,返回之后就不是原来的程序而是新的可执行程序起点
fork函数从ret_ from_fork开始执行然后返回用户态

2.sys_execve内核处理过程

do_execve -> do_execve_common -> exec_binprm

do_execve
do_open_exec(filename)打开要加载的文件
命令行参数,结构体变量copy到bprm结构体中
exce_binprm(bprm),关键代码是寻找能解析当前文件的处理模块
register_binfmt($elf_format)注册这个格式到链表里,然后寻找能处理的模块
ELF可执行文件默认映射到0x8048000这个地址
需要动态链接的可执行文件先加载连接器ld;否则直接把elf文件entry地址赋值给entry即可。
start_thread(regs, elf_entry, bprm->p)会将CPU控制权交给ld来加载依赖库并完成动态链接;对于静态链接的文件elf_entry是新程序执行的起点

3.动态链接的可执行程序的装载

  • 动态链接库的依赖关系会形成一个图。
  • load_elf_interp实际加载动态链接器,entry返回的是动态链接器的入口,根据需求加载动态链接库,根据库的需要再加载更多的库。

四、实验 Linux内核如何装载和启动一个可执行程序

1.下载新的代码文件

20135327郭皓--Linux内核分析第七周 可执行程序的装载

20135327郭皓--Linux内核分析第七周 可执行程序的装载

2.运行和gdb跟踪断点

20135327郭皓--Linux内核分析第七周 可执行程序的装载

20135327郭皓--Linux内核分析第七周 可执行程序的装载