程涵 

原创博客

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


可执行程序的装载

知识点梳理

一、预处理、编译、链接和目标文件的格式

可执行程序是如何得来的

  1. C源代码(.c)经过编译器预处理被编译成汇编代码(.asm)
  2. 汇编代码由汇编器被编译成目标代码(.o)
  3. 将目标代码链接成可执行文件(a.out)
  4. 可执行文件由操作系统加载到内存中执行

vi hello.c
gcc -E -o hello.cpp hello.c -m32 //预处理.c文件,预处理包括把include的文件包含进来以及宏替换等工作 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 //将汇编代码.s编译成二进制目标文件.o(不可读,含有部分机器指令但不可执行) vi hello.o
gcc -o hello hello.o -m32 //将目标文件链接成可执行二进制文件hello vi hello
gcc -o hello.static hello.o -m32 -static

目标文件的格式ELF

1. .out是最古老的可执行文件,目前Windows系统上多是PE,Linux系统上多是ELF。ELF文件已经是适应到某一种CPU体系结构的二进制兼容文件了

2. 目标文件的三种形式:

  • 可重定位文件.o,用来和其他object文件一起创建可执行文件和共享文件
  • 可执行文件,指出应该从哪里开始执行
  • 共享文件,主要是.so文件,用来被链接编辑器和动态链接器链接

3. ELF格式

  • ELF头描述了该文件的组织情况,程序投标告诉系统如何创建一个进程的内存映像,section头表包含了描述文件sections的信息。当系统要执行一个文件的时候,理论上它会把程序段拷贝到虚拟内存中某个段
  • ELF文件的头部规定了许多与二进制兼容性相关的信息。所以在加载ELF文件的时候,必须先加载头部,分析ELF的具体信息
  • entry代表刚加载过新的可执行文件之后的程序的入口地址,头部后是代码和数据,进程的地址空间是4G,上面的1G是内核用,下面的3G是程序使用。默认的ELF头加载地址是0x8048000

静态链接的ELF可执行文件和进程的地址空间

1. Entry point address:入口地址为0x8048X00(不唯一)

加载效果:将代码段数据加载到内存中,再把数据加载到内存,默认从0x8048000地址开始加载

启动一个刚加载过可执行文件的进程时,可执行文件加载到内存之后执行的第一条代码地址

一般静态链接会将所有代码放在一个代码段,而动态链接的进程会有多个代码段

2. 流程

  • 分析头部
  • 查看是否需要动态链接。如果是静态链接的ELF文件,那么直接加载文件即可。如果是动态链接的可执行文件,那么需要加载的是动态链接器
  • 装载文件,为其准备进程映像
  • 为新的代码段设定寄存器以及堆栈信息

二、可执行程序、共享库和动态链接

可执行程序的执行环境

  • 一般执行一个程序的Shell环境,实验中直接使用execve系统调用
  • Shell本身不限制命令行参数的个数,命令行参数的个数受限于命令自身,如:

    int main(int argc, char *argv[])
    
    int main(int argc, char argv[], char envp[])//envp是shell的执行环境
  • Shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数

int execve(const char * filename,char * const argv[ ],char * const envp[ ]);

可执行程序的装载

  • fork两次返回,第一次返回到父进程继续向下执行,第二次是子进程返回到ret_from_fork然后正常返回到用户态。

  • execve执行的时候陷入到内核态,用execve中加载的程序把当前正在执行的程序覆盖掉,当系统调用返回的时候也就返回到新的可执行程序起点。

(1)可执行文件开始执行的起点在哪里?如何才能让execve系统调用返回到用户态时执行新程序?

修改int 0x80压入内核堆栈的EIP,通过修改内核堆栈中EIP的值作为新程序的起点。

(2)Linux内核是如何支持多种不同的可执行文件格式

static struct linux_binfmt elf_format//声明一个全局变量 = {
.module = THIS_MODULE,
.load_binary = load_elf_binary,//观察者自动执行
.load_shlib = load_elf_library,
.core_dump = elf_core_dump,
.min_coredump = ELF_EXEC_PAGESIZE,
}; static int __iit init_elf_binfmt(void)
{n
register_binfmt(&elf_format);//把变量注册进内核链表,在链表里查找文件的格式
return ;
}

(3)动态链接

  • 可执行程序需要依赖动态链接库,而这个动态链接库可能会依赖其他的库,这样形成了一个关系图——动态链接库会生成依赖树。
  • 依赖动态链接器进行加载库并进行解析(这就是一个图的遍历),装载所有需要的动态链接库;之后ld将CPU的控制权交给可执行程序
  • 动态链接的过程主要是动态链接器在起作用,而不是内核完成的。

实验过程及截图

使用gdb跟踪sys_execve内核函数的处理过程

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

2. test.c文件中增加了exec系统调用,Makefile文件中增加了gcc -o hello hello.c -m32 -static

3. 启动内核并验证execv函数

4. 启动gdb调试

先设置sys_execve后,在menuOS里执行系统调用exec,找到第一个断点。

找到第二个断点

给新栈的栈底指针赋值后,找到第三个断点start_thread

new_ip是返回到用户态的第一条指令

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

可执行程序的装载与庄周梦蝶的故事

  庄周(调用execve的可执行程序)入睡(调用execve陷入内核),醒来(系统调用execve返回用户态)发现自己是蝴蝶(被execve加载的可执行程序)

浅析动态链接的可执行程序的装载

1. 动态链接的过程中,内核做了什么?

ldd test

ldd libfuse.so //可执行程序需要依赖动态链接库,而这个动态链接库可能会依赖其他的库,实际上动态链接库的依赖关系会形成一个图

2. 是由内核负责加载可执行程序依赖的动态链接库吗?

动态链接器负责加载这些库并进行解析当前的可执行文件,装载所有需要的动态链接库,动态链接库的装载过程是一个图的遍历(广度)
装载和链接后ld将CPU的控制权交给可执行程序
动态链接的过程主要由动态链接器完成,并不是内核

【MOOC EXP】Linux内核分析实验七报告的更多相关文章

  1. 【MOOC EXP】Linux内核分析实验八报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 进程的切换和系统的一般执行过程 知识点 ...

  2. 【MOOC EXP】Linux内核分析实验六报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 进程的描述和进程的创建 知识点梳理: ...

  3. 【MOOC EXP】Linux内核分析实验一报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  [反汇编一个简单的C程序]   实验 ...

  4. 【MOOC EXP】Linux内核分析实验二报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  [操作系统是如何工作的]   教学内 ...

  5. 【MOOC EXP】Linux内核分析实验三报告

     程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 [跟踪分析Linux内核的启动过程] ...

  6. 【MOOC EXP】Linux内核分析实验四报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 [使用库函数API和C代码中嵌入汇编代 ...

  7. 【MOOC EXP】Linux内核分析实验五报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 分析system_call中断处理过程 ...

  8. “Linux内核分析”实验一报告

    张文俊 + 原创作品转载请注明出处 + <Linux 内核分析> MOOC 课程 实验要求: 1.总结部分要求阐明自己对“计算机是如何工作的”理解: 2.博客中需要使用实验截图: 实验内容 ...

  9. “Linux内核分析”实验二报告

    张文俊 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.第二周学习内 ...

随机推荐

  1. hadoop系列 第二坑: hive hbase关联表问题

    关键词: hive创建表卡住了 创建hive和hbase关联表卡住了 其实针对这一问题在info级别的日志下是看出哪里有问题的(为什么只能在debug下才能看见呢,不太理解开发者的想法). 以调试模式 ...

  2. Java:传值还是传引用?

    这是一个Java的经典问题,大部分人从C,C++语言入门,C语言有三种传递方式:值传递,地址传递和引用传递.详细的对C语言指针,引用的我个人的理解,见链接. Java所有操作都是传值操作!都是传值操作 ...

  3. 使用pymysql(使用一)

    创建数据表 import pymysql db = pymysql.connect("localhost","root",""," ...

  4. Qt读取文件时中文乱码问题

    在默认情况下,Qt 以 Unicode 格式处理文本字符,因此,字符本身是不会有问题的.之所以出现乱码,原因在于 Qt 不知道将 Unicode 字符以何种方式显示出来.        文本文件含有简 ...

  5. [转]Win7 + Ubuntu 18.04 LTS (Bionic Beaver)双系统安装方法

    这里介绍在win7的基础上,安装ubuntu 18.04 LTS,实现双系统启动. 首先,假设你已安装了windows 7系统. 一. 制作ubuntu U盘启动盘. 方法见http://blog.p ...

  6. Linux 从网卡到TCP IP协议栈数据流跟踪与审计

    前沿 在学代码审计,然后最近做Linux协议栈的审计,发现Linux不愧是一个久经考验的系统,本来以为可以找到个DoS的,结果发现其在TCP/IP协议栈的链路层实现,利用了各种技术,用来提高性能与安全 ...

  7. WireShark抓包工具使用

    WireShark是一款网络封包分析软件,它抓取网络封包,并尽可能显示出最详细的封包资料. wireshark的准备工作 安装wireshark sudo apt-get install wiresh ...

  8. 2-(基础入门篇)Air202下载开发入门(给Air202下载第一个程序)

    http://www.cnblogs.com/yangfengwu/p/8887933.html 资料链接 链接:https://pan.baidu.com/s/1-SRfsKGQ7rZVvFmp1O ...

  9. curl命令行

    curl命令行--强大的工具.通过各种参数,支持各种方式. 写几个常用的命令: 请求到的网站html curl http://www.baidu.com 比如想在命令行上请求一个接口,post过去几个 ...

  10. SpringMVC之单/多文件上传

    1.准备jar包(图标所指必备包,其他按情况导入) 2.项目结构 3.SingleController.java(控制器代码单文件和多文件) package com.wt.uplaod; import ...