2019-2020-1 20199329《Linux内核原理与分析》第八周作业

《Linux内核原理与分析》第八周作业


一.本周内容概述:

  • 理解编译链接的过程和ELF可执行文件格式
  • 编程练习动态链接库的两种使用方式
  • 使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve

二.本周学习内容:

1.理解编译链接的过程和ELF可执行文件格式

ELF(Executable and Linking Format)是一种对象文件的格式,用于定义不同类型的对象文件(Object files)中都放了什么东西、以及都以什么样的格式去放这些东西。它自最早在 System V 系统上出现后,被 xNIX 世界所广泛接受,作为缺省的二进制文件格式来使用。
所谓对象文件(Object files)有三个种类:

  • 可重定位的对象文件(Relocatable file)
  • 可执行的对象文件(Executable file)
  • 可被共享的对象文件(Shared object file)
    ELF文件格式如图所示:

    ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。实际上,一个文件中不一定包含全部内容,而且他们的位置也未必如同所示这样安排,只有ELF头的位置是固定的,其余各部分的位置、大小等信息有ELF头中的各项值来决定。

ELF文件:ELF(Excutable and Linking Format)是一个文件格式的标准。通过readelf-h hello查看可执行文件hello的头部(-a查看全部信息,-h只查看头部信息),头部里面注明了目标文件类型ELF32。Entry point address是程序入口,地址为0x400440

2.实验楼实验内容:使用gdb跟踪分析一个execve系统调用内核处理函数

exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件,如果不是可以执行的文件,那么就解释成为一个shell文件,shell执行。

  • 更新linux/kernel下的menu,并将test_exec变成test.c
    实践截图如下:
  • 进入内核,查看exec命令是否添加进入内核
    实践截图如下:
  • 横屏打开另一个终端,进行gdb追踪
remote target:1234

实践截图如下:

  • 在sys_execve处和其他的地方设置断点,并进行单步执行
    实践截图如下:


  • 最后退出调试状态后输入redelf -h hello可以查看hello的EIF头部
    实践截图如下:
  • elf头部分析
    可见elf头大小为52字节,用dump命令16进制读取前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,表示节名串表的在节表中的索引号。


三.总结与疑难

上一周的学习实验中,我了解到了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形成目标可执行文件)

四.下周计划


2019 年 11 月 8 日

posted @ 2019-11-08 21:59  朱星帆20199329  阅读(198)  评论(0编辑  收藏  举报