第一部分 课本学习

  • ELF文件(目标文件)格式主要三种:

1)可重定向文件:文件保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享目标文件。(目标文件或者静态库文件,即linux通常后缀为.a和.o的文件)

2)可执行文件:文件保存着一个用来执行的程序。(例如bash,gcc等)

3)共享目标文件:共享库。文件保存着代码和合适的数据,用来被下连接编辑器和动态链接器链接。(linux下后缀为.so的文件。)

  • 一般的 ELF 文件包括三个索引表:

1)ELF header:在文件的开始,保存了路线图,描述了该文件的组织情况。

2)Program header table:告诉系统如何创建进程映像。用来构造进程映像的目标文件必须具有程序头部表,可重定位文件不需要这个表。

3)Section header table :包含了描述文件节区的信息,每个节区在表中都有一项,每一项给出诸如节区名称、节区大小这类信息。用于链接的目标文件必须包含节区头部表,其他目标文件可以有,也可以没有这个表。

  • 从源代码到可执行程序所要经历的过程概述:



    以hello world的.c文件为例进行分析,c语言代码如下:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("hello, world!\n");
return 0;
}

编译步骤如下:

vi hello.c
gcc -E -o hello.cpp hello.c -m32 //对.c文件预处理
vi hello.cpp
gcc -x cpp-output -S -o hello.s hello.cpp -m32 //编译成汇编代码.s
vi hello.s
gcc -x assembler -c hello.s -o hello.o -m32 //汇编成目标代码.o是二进制的文件
vi hello.o
gcc -o hello hello.o -m32 //链接成可执行文件
vi hello
gcc -o hello.static hello.o -m32 -static
  • 静态链接和动态链接

    静态链接:在编译链接时直接将需要的执行代码复制到最终可执行文件中,优点是代码的装载速度快,执行速度也比较快,对外部环境依赖度低。编译时它会把需要的所有代码都链接进去,应用程序相对比较大。缺点是如果多个应用程序使用同一库函数,会被装载多次,浪费内存。

    动态链接:在编译时不直接复制可执行代码,而是通过记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统。操作系统负责将需要的动态库加载到内存中,然后程序在运行到指定的代码时,去共享执行内存中已经加载的动态库去执行代码,最终达到运行时链接的目的。优点是多个程序可以共享同一段代码,而不需要在磁盘上存储多个复制。缺点是在运行时加载,可能会影响程序的前期执行性能,而且对使用的库依赖性较高吗,在升级时特别容易出现版本不兼容的问题。

第二部分 使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve

  • 实验步骤:

    将menu目录删除,利用git命令克隆一个新的menu目录。
rm menu -rf
git clone https://github.com/mengning/menu.git

用test_exec.c将test.c覆盖,然后重新编译rootfs。可以发现,除了增加了ececlp函数外,还在Makefile中编译了hello.c,然后在生成根文件系统时把int和hello都放到rootfs.img中。在这个实验中,hello就是一个加载进来的可执行文件。

mv test_exec.c test.c
make rootfs



使用help命令可以看到增加了exec指令,执行exec指令发现比fork指令增加了一行输出“hello world!”。实际上是新加载了一个可执行程序来输出了一行语句。



启动内核到调试的状态,加载符号表并设置端口,准备单步调试。

Qemu -system-x86_64 -kernel bzImage -initrd /home/YL/rootfs.img -S -s file ../linux-3.18.6/vmlinux target remote:1234

启动新的终端窗口开始gdb调试,设置断点到“sys_exec” “load_elf_binary” “start_thread”。

b sys_exec
b load_elf_binary
b start_thread





进入“sys_exec”函数内部发现调用了“do_execve()”函数继续执行到“load_elf_binary”处的断点,此时调用这个函数进行对可执行文件格式的解析。





继续执行到“start_thread”处的断点,因为是静态链接,“elf_entry”指向了可执行文件中定义的入口地址,使用“po new_ip”指令打印其指向的地址,“new_ip”是返回到用户态的第一条指令的地址。查看hello的elf头部,查看定义的入口地址与“new_ip”所指向的地址是否一致。



使用readelf -h hello查看hello的elf头部,发现定义的入口地址与new_ip所指向的地址一致。

第三部分 总结

  • 可执行文件开始执行的起点在修改调用execeve系统调用时压入内核堆栈的EIP寄存器的值,因为此时标志着当前进程的可执行文件已经被完全替换为新的可执行文件了,但实际开始执行可执行文件中的指令还需要等到执行文件中定义的入口地址的位置,一般地址为0x8048xxx的位置。通过修改内核堆栈中EIP寄存器的值作为新程序的起点,让execve系统调用返回到用户态时执行新程序。

2018-2019-1 20189203《Linux内核原理与分析》第八周作业的更多相关文章

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

    <Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...

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

    <Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...

  3. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  4. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

  5. 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...

  6. 2017-2018-1 20179215《Linux内核原理与分析》第二周作业

    20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...

  7. 2019-2020-1 20209313《Linux内核原理与分析》第二周作业

    2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...

  8. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  9. 《Linux内核原理与分析》第一周作业 20189210

    实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...

  10. 2018-2019-1 20189221《Linux内核原理与分析》第二周作业

    读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...

随机推荐

  1. Java窗体居中显示的2种方法

    第1种方法: //setSize(300, 200); pack(); // 得到显示器屏幕的宽.高 int width = Toolkit.getDefaultToolkit().getScreen ...

  2. 《effective Go》读后记录:GO基础

    一个在线的Go编译器 如果还没来得及安装Go环境,想体验一下Go语言,可以在Go在线编译器 上运行Go程序. 格式化 让所有人都遵循一样的编码风格是一种理想,现在Go语言通过gofmt程序,让机器来处 ...

  3. 24小时学通Linux内核之向内核添加代码

    睡了个好觉,很晚才起,好久没有这么舒服过了,今天的任务不重,所以压力不大,呵呵,现在的天气真的好冷,不过实验室有空调,我还是喜欢待在这里,有一种不一样的感觉,在写了这么多天之后,自己有些不懂的页渐渐的 ...

  4. 【中间件安全】WebSphere安全加固规范

    1. 适用情况 适用于使用WebSphere进行部署的Web网站. 2. 技能要求 熟悉WebSphere安装部署,熟悉WebSphere常见漏洞利用方式,并能针对站点使用WebSphere进行安全加 ...

  5. Non-zero exit code (1)

    刚报了这个错Non-zero exit code (1) 经排查执行这个命令就好了  python -m pip install --upgrade pip 一定要多看报错,报错中有提示的

  6. shell 递归枚举文件并操作

    递归枚举文件并操作 #!/bin/bash CURDIR=$(cd $(dirname $0); pwd) export GOPATH=$CURDIR/.. echo GOPATH=$GOPATH c ...

  7. POJ 3414 pots (未解决)

    http://poj.org/problem?id=3414 #include <iostream> #include <cstdio> #include <queue& ...

  8. linux安装rabbitmq以及相关的操作命令

    1.安装rabbitmqa)进入rabbitmq文件的存放目录b)rpm -ivh rabbitmq-server-3.5.4-1.noarch.rpm2.修改配置cd /etc/rabbitmqcd ...

  9. express.js graphql express-graphql

    文档 创建应用 const l = console.log; var express = require("express"); var graphqlHTTP = require ...

  10. gnome-shell 扩展

    application menu topicons plus dash to dock native window placement netspeed no topleft hot corner o ...