第七章

可执行程序工作原理

  • ELF概述:

    • 目标平台:它决定了编译器使用的机器命令集。
    • ABI(目标文件)
    • 目标文件和目标平台是二进制兼容的,即该目标文件已经是适应某一种CPU体系结构的二进制指令。
    • ELF即可执行的和可链接的格式,是一个目标文件格式的标准。
  • ELF文件的三种类型:

    • 可重定位文件:属于中间文件,需要继续处理。由编译器和汇编器创建。一个源代码会生成一个可重定位文件。用来和其他目标文件一起来创建一个可执行文件、静态库文件或者共享目标文件。可重定位文件后缀为.o ,最后所有.o文件会链接为一个文件。
    • 可执行文件:由多个可重定位文件结合生成,完成了所有重定位工作和符号解析的文件。文件中保存着一个用来执行的程序。
    • 共享目标文件:共享库,是指被可执行文件或其他库文件使用的目标文件。其后缀为.so
  • ELF文件的作用

    ELF文件参与程序链接(建立一个程序)和程序的执行(运行一个文件)。

    • 如果用于编译和链接(可重定位文件),则编译器和链接器将把elf文件看作是节头表描述的节的集合,程序头表可选。
    • 如果用于加载执行(可执行文件),则加载器则将把elf文件看作是程序头表描述的段的集合,一个段可能包含多个节,节头表可选。
    • 如果是共享文件,则两者都含有。
  • ELF文件格式

  • ELF文件由ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)组成。
  • ELF头(ELF header)
    • ELF Header在文件最开描述了该文件的组织情况, 他的其他部分主要说明了其他文件内容的位置、大小等信息。
    • 节头表基本定义了整个ELF文件的组成,可以说是整个ELF就是由若干个节(Section)组成的。
  • Section header结构
    • 节头表是由Section Header组成的表,包含了描述文件节区的信息,每个节区在表中都有一项,每一项给出诸如节区名称,节区大小这类信息。
    • sh_name 节名,是在字符串中的索引
    • sh_addr 该节对应的虚拟地址
    • sh_offset 该节在文件中的位置
    • h_size 该节的大小
    • sh_link 与该节连接的其他节
    • sh_addralign 对齐方式
  • Program Header结构
    • 段头(Program Header)表示和创建进程相关的,描述了连续的几个节在文件的位置,大小以及它被放进内存后的大小和位置,告诉系统如何创建进程映象,可执行文件加载器就可以按这个说明将可执行文件搬到内存中。
    • p_type 当前描述的段类型
    • p_offset 段在文件中的偏移
    • p_vaddr 段在内存中的虚拟地址
    • p_paddr 在物理内存定位相关的系统中,此项为物理地址保留
    • p_filesz 段在文件中的长度
    • p_memsz 段在内存中的长度
    • p_align 确定段在文件及内存中如何对齐
  • 相关指令操作
    • man elf:在Linux下输入“man elf”既可以查看其详细的格式定义。
    • readelf:用于显示一个或多个elf格式的目标文件的信息,可以通过它的选项来控制显示哪些信息。
    • objdump:显示二进制文件信息,用于查看目标文件或者可执行的目标文件的构成的gcc工具。
    • hexdump:用十六进制的数字来显示elf的内容。

- 预处理
- 删除所有的注释
- 删除所有#define,进行替换
- 处理所有预编译指令
- 处理#include指令,将被包含的文件插入预编译指令的位置
- 添加行号和文件名标识
- 预处理完的文件仍然是文本文件,可以用任意文本编辑器查看。
```
gcc -E hello.c -o hello.i
```

  • 编译

    • 编译首先会检查代码的规范性、语法错误等
    • 汇编结束的文件是二进制文件,可以用任意编辑器查看
gcc -S hello.i -o hello.s -m32
  • 汇编

    • 汇编结束后的文件已经是ELF格式的文件了。至少包含三个节区.text .data .bss
gcc  -c hello.s -o hello.o -m32
  • 链接(把多个文件拼接到一起,本质上是节的拼接)

    • 主要工作将有关的目标文件彼此相连,使得所有目标文件能够成为一个能够被操作系统装入执行的统一整体。将各种代码和数据部分收集起来并组合成一个单一文件的过程,这个文件可以被加载或复制到内存中并执行。
gcc hello.o -o hello -m32 -static


- **.bss**段:BSS段通常是指用来存放程序中未初始化的群居变量的一块内存区域。属于静态内存分配,该节不占用文件空间。
- **.data**段:数据段通常使用来存放程序中已初始化的全局变量的一块内存区域。属于静态内存分配。
- **.text**段:代码段通常是指用来存放程序执行代码的一块内存区域。
- 符号
- 由模块定义并能被其他模块引用的全局符号。
- 由其他模块定义并能被模块引用的全局符号。
- 只被模块定义和引用的本地符号。
- 重定位(是把程序的逻辑地址空间变换成内存中的实际物理地址空间的过程)
- 重定位表中记录了所有调用这些函数的代码位置
- 静态链接和动态链接
- 链接器将函数的代码从其所在地(目标文件或静态链接库中)拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。
- 在编译时不直接复制可执行代码,通过记录一系列的参数和符号,在程序运行或者加载时将这些信息传递给操作系统。操作系统将需要的动态库加载到内存中,程序在运行到指定代码时,去共享执行内存中已经加载的动态库去执行代码。
- 装载时动态链接(只需要在代码中调用对应的库函数,在编译时,将动态库的头文件路径标明)
- 运行时动态链接(运行时动态链接的本质就是程序员自己控制整个过程)
- 程序装载
- argv是以NULL结尾的命令行参数数组,envp同样是以NULL结尾的环境变量数组。
- 执行readelf -f可以查看ELF可执行文件的首部信息。
- 动态链接的过程主要是动态链接器在起作用,而不是内核完成的。
- fork与execve内核处理过程
- fork两次返回,第一次返回到父进程继续向下执行,第二次是子进程返回到ret_from_fork后正常返回到用户态。
- 当execve系统调用返回时,返回的是新的可执行文件。
- 庄周梦蝶
- 一个新的可执行文件返回到用户态之前,需要将进入内核时压入内核的eip修改掉,用新的可执行程序的起点来修改。

实验

cd LinuxKernel
rm menu -rf
git clone http://github.com/mengning/menu.git
cd menu
mv test_exec.c test.c
make rootfs

重新编译后,使用qemu命令冻结系统执行,进行调试

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

水平分割一个窗口,启动gdb加载内核,连接到target 1234

gdb
(gdb) file linux-3.18.6/vmlinux
(gdb) target remote:1234

添加断点在sys_execve和load_elf_binary和start_thread处

b sys_execve
b load_elf_binary
b start_thread

第一个断点sys_execve处



第二个断带处



第三个断点start_thread处,可以看到修改了eip的值

2019-2020-1 20199301《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. 拥抱TF2.0的时代来了

    AI = 算法 + 实现 忘掉 tf 1.0吧!!! TPU tf 加速硬件 学习建议 忘记1.0 Tensorflow 和Pytorch 选择一个主修 Keras 逐渐淡出 TF.kreas Pyt ...

  2. netty中的channelPipeline在编程中的作用

    在netty编程中我们绝大多数是要是用nio的,nio相比传统的io更加高效,而nio中核心概念离不开channel,buffer,selector三个重要的对象. 那么在netty中有一个chann ...

  3. Linux 线程间的同步与互斥

    在线程并发执行的时候,我们需要保证临界资源的安全访问,防止线程争抢资源,造成数据二义性. 线程同步: 条件变量 为什么使用条件变量? 对临界资源的时序可控性,条件满足会通知其他等待操作临界资源的线程, ...

  4. Oracle的字串處理

    Oracle的字串處理 除了寫程式之外,資料庫的應用也是蠻重要的,而SQL語法,用法大致相同,但各公司所出的資料庫還是有所差別,而ORACLE SQL給了相當多的函數應用,下面列了一些函法的名稱和用法 ...

  5. [cf 1236 E] Alice and the Unfair Game

    题意: 给定一个长度为m的序列$A$,你有一个长度为n的棋盘,可以任选一个位置x作为起点. 在时刻$[1,m+1]$你可以向左或向右移动一格. 设时刻i你移动后所在的位置为$B_i$,你需要满足对于任 ...

  6. 浅谈分词算法基于字的分词方法(HMM)

    前言 在浅谈分词算法(1)分词中的基本问题我们讨论过基于词典的分词和基于字的分词两大类,在浅谈分词算法(2)基于词典的分词方法文中我们利用n-gram实现了基于词典的分词方法.在(1)中,我们也讨论了 ...

  7. ASP.NET SignalR 系列(五)之群组推送

    在上一章介绍了 一对一推送的方式,这章重点介绍下群组推送和多人推送 群组主要就是用到了方法:Groups.Add(Context.ConnectionId, groupName); 将不同的连接id加 ...

  8. Vue 项目 VSCode 调试

    调试Vue搭建的前端项目 在项目根目录下的vue.config.js中添加: module.exports = { lintOnSave: false, //关闭eslint语法校验 //填写这部分 ...

  9. Java调用Http/Https接口(3)--Commons-HttpClient调用Http/Https接口

    Commons-HttpClient原来是Apache Commons项目下的一个组件,现已被HttpComponents项目下的HttpClient组件所取代:作为调用Http接口的一种选择,本文介 ...

  10. css,对包含有子元素的元素进行flex后,会影响原有的布局。如何后续处理

    对包含有子元素的元素进行flex后,会影响原有的布局. 例如设置两个div,第一个div包含一个img(图片),第二个div包含多个p元素(对前面的img的说明).如下图 1:当对着两个两个div进行 ...