攥写人:李鹏举 学号:20179203

原创作品转载请注明出处

( 学习课程:《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 )

一、实验要求:

1.理解编译链接的过程和ELF可执行文件格式,详细内容参考本周第一节;

2.编程使用exec*库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态链接,编程练习动态链接库的这两种使用方式,详细内容参考本周第二节;

3.使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve ,验证您对Linux系统加载可执行程序所需处理过程的理解,详细内容参考本周第三节;推荐在实验楼Linux虚拟机环境下完成实验。

4.特别关注新的可执行程序是从哪里开始执行的?为什么execve系统调用返回后新的可执行程序能顺利执行?对于静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时会有什么不同?

二、实验过程:

1.开始先更新内核,再用test_exec.c将test.c覆盖掉:

  1. test.c文件中增加了exec系统调用,Makefile文件中增加了gcc -o hello hello.c -m32 -static,启动内核并且检验execv函数是否正确:



  2. 最后启动gdb调试:

  3. 在sys_execve处和其他的地方设置断点,并进行单步执行:

5.最后退出调试状态后输入redelf -h hello可以查看hello的EIF头部:

三、实验分析:

1.elf头部分析:



可见elf头大小为52字节,用dump命令16进制读取前52个字节进行分析

命令:hexdump –x hello –n 52



分析:

第一行,对应e_ident[EI_NIDENT]。小端法实际表示内容为7f454c46010101000000000000000000,前四个字节为elf固定开头7f454c46(0x45,0x4c,0x46是'e','l','f'对应的ascii编码),表示这是一个ELF对象。接下来的一个字节01表示是一个32位对象,接下来的一个字节01表示是小端法表示,再接下来的一个字节01表示文件头版本。剩下的默认都设置为0.

第二行,e_type值为0x0002,表示是一个可执行文件。e_machine值为0x0003,表示是intel80386处理器体系结构。e_version值为0x00000001,表示是当前版本。e_entry值为0x04080a8d,表示入口点。e_phoff值为0x00000034,表示程序头表的偏移量为0x34即52个字节刚好是elf头大小。

第三行,e_shoff值为0x000a20f0,表示节头表的偏移地址。e_flags值为0x00000000,表示未知处理器特定标志。e_ehsize值为0x0034,表示elf文件头大小52个字节。e_phentsize表示一个程序头表中的入口(程序头)的长度,值为0x0020即32字节。e_phnum的值为0x0006,给出程序头表中的入口数目。e_shentsize值为0x0028表示节头表入口(节头)大小为40字节。

第四行,e_shnum值为0x001f,表示节头表入口有31个。e_shstrndx值为0x001c,表示节名串表的在节表中的索引号。

2.exec()函数结构分析

int do_execve(struct filename *filename,
const char __user *const __user *__argv,
const char __user *const __user *__envp)
{
return do_execve_common(filename, argv, envp);
} static int do_execve_common(struct filename *filename,
struct user_arg_ptr argv,
struct user_arg_ptr envp)
{
// 检查进程的数量限制 // 选择最小负载的CPU,以执行新程序
sched_exec(); // 填充 linux_binprm结构体
retval = prepare_binprm(bprm); // 拷贝文件名、命令行参数、环境变量
retval = copy_strings_kernel(1, &bprm->filename, bprm);
retval = copy_strings(bprm->envc, envp, bprm);
retval = copy_strings(bprm->argc, argv, bprm); // 调用里面的 search_binary_handler
retval = exec_binprm(bprm); // exec执行成功 } static int exec_binprm(struct linux_binprm *bprm)
{
// 扫描formats链表,根据不同的文本格式,选择不同的load函数
ret = search_binary_handler(bprm);
// ...
return ret;
}

上一周的学习实验中,我了解到了fork()数的单步执行过程,并且看到了fork()函数的结构。而对于本周学习的exec()函数的结构,我也进行了查看和分析。

由以上代码可知,do_ execve调用了do_ execve_ common,而do_ execve_ common又主要依靠了exec_ binprm,在exec_ binprm中又有一个至关重要的函数,叫做search_binary_ handler。这就是sys_execve的内部处理过程。 而本周学习的重点就是,文件处理的过程:

预处理:gcc –E –o hello.cpp hello.c -m32 (负责把include的文件包含进来,宏替换)

编 译:gcc -x cpp-output –S hello.s –o hello.cpp -m32(gcc –S调用ccl,编译成汇编代码)

汇 编:gcc -x assembler –c hello.s –o hello.o; (gcc -c 调用as,得到二进制文件)

链 接:gcc –o hello hello.o ;gcc -o (调用ld形成目标可执行文件)

链接分为静态链接和动态链接。静态链接生成三种主要ELF目标文件:

1.可重定位文件:保存代码和适当的数据,用来和其他object文件一起创建一个可执行文件或一个共享文件。主要是.o文件。

2.可执行文件:保存一个用来执行的程序,指出了exec(BA_OS)如何来创建程序进程映象,怎么把文件加载出来以及从哪里开始执行。

3.共享文件:保存着代码和数据用来被以下两个链接器链接。

一是链接编译器,可以和其他的可重定位和共享文件创建其他的object文件;

二是动态链接器,联合一个可执行文件和其他 共享文件来创建一个进程映象。主要是.so文件。

eip也是一个重要的概念,对于eip,如果是静态链接的可执行文件,那么eip指向该elf文件的文件头e_entry所指的入口地址;

如果是动态链接,eip指向动态链接器。而对于execve执行静态链接程序时,通过修改内核堆栈中保存的eip的值作为新进程的起点。

最新文章

  1. 如何用Unity制作自定义字体——Custom Font
  2. XE3随笔17:实例 - 模拟 Google 搜索
  3. css 文字与小图标对齐
  4. visual studio 2012 的制作ActiveX、打包和发布
  5. 小谈pointer和relation
  6. 【转】 Mybatis/Ibatis,数据库操作的返回值
  7. MyEclipse 中的各种有的没的快捷方式
  8. Twitter注册
  9. 编程之美2015初赛第一场 hihoCoder #1156 : 彩色的树(染色问题)
  10. 流量控制闸门——LimitLatch套接字连接数限制器
  11. [ABP] ASP.NET Zero 5.6.0 之 ASP.NET Zero Power Tools 上手日志
  12. KMeans算法分析以及实现
  13. STO单没有取进FP,IN_SAELS_ORDER表无,但IN_PO_STO有
  14. HDU 5701 中位数计数 百度之星初赛
  15. Android-Intent意图传递数据
  16. python multi process multi thread
  17. The Java serialization algorithm revealed---reference
  18. C# 从服务器下载文件
  19. Html编码(&#数字型)与解码小结 - 针对Puny Code(中文域名)的解码处理
  20. pocscan扫描框架的搭建

热门文章

  1. Hadoop学习笔记——Hadoop经常使用命令
  2. 安卓常用的xml控件配件的使用包含shape,declare-styleable、selector
  3. Obj-C数组以及字符串拼接与分割
  4. 使用onepage-scroll全屏滚动插件时的注意事项
  5. 学习Sharding JDBC 从入门到出门-1
  6. 像使用linux一样使用mac
  7. 20179209《Linux内核原理与分析》第十二周作
  8. linux c编程:进程控制(二)_竞争条件
  9. 创建第一个SpringBoot的demo程序
  10. (转)Javascript模块化编程(二):AMD规范