知识积累
ELF文件
ELF文件是linux系统下的主要可执行格式文件,就像win下的.exe文件
动态库
动态库的依赖关系会形成一个树形结构
动态链接器负责解析当前文件,看依赖哪些动态链接库
动态链接库的装载过程是一个图的广度遍历过程
动态链接不是由内核完成,是由动态链接器完成的。
动态链接器是libc的一部分
动态链接可分为
- 可执行程序装载时的动态链接 使用
dlopen
- 运行时动态链接
正常的系统调用都是陷入到内核态然后返回到用户态
当出现elf文件的时候,观察者就能自动执行
load_elf_binary -> start_thread
shell
shell本身不限制命令行的参数的个数,命令行参数的个数受限于命令本身
shell会调用execve
将命令行参数和环境参数传递给可执行程序的main
函数
exec函数
库函数exec
都是execve
的封装
exec_binprm
是可执行文件处理的关键。其中的关键函数为
- search_binary_handler (寻找可执行文件的处理函数)
- list_for_each_entry (在这个循环中,寻找能够解析可知性文件的代码)
- load_elf_binary (将文件映射到进程的空间中0x8048000)
- list_for_each_entry (在这个循环中,寻找能够解析可知性文件的代码)
编译连接的基本过程
- 预处理
- 编译
- 汇编
- 链接
readelf
用readelf -S test.o
查看一下汇编之后的文件信息表
查看可执行文件头部
在这里可以看到文件执行的入口地址
实验操作
配置环境
这一步跟之前的都是一样的,就不再写了
预备
shift+G
直接到test.c
文件末尾 可以看到多了一个函数exec
qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -s -S
开启GDB调试
file ../linux-3.18.6/vmlinux
在GDB中加载符号表文件
target remote:1234
连接调试端口
设置断点
b sys_execve
b load_elf_binary
b start_thread
可以看到在执行到this is child process
处停止,说明这个地方进行了系统调用sys_execv
这里会有一个问题, new_ip
到底是指向哪的
new_ip
是返回到用户态的第一条指令的地址
然后根据这个程序找一下内存地址看看是不是一样
总结
在调用一种exec函数时,该进程执行的程序完全被替换为新程序,而新程序则从其main函数处开始执行,因为调用exec函数并不创建新进程,所以前后的进程ID并未改变,或者说exec函数只是用了一个全新的程序替换了当前进程的正文、数据段和堆栈段