可执行程序的装载

可执行程序的装载

                                                                                                         20135109 高艺桐

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

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

1、1可执行程序是怎么得来的

  • C代码经过编译器的预处理编译、编译成汇编代码、编译器将其编译成目标代码、链接成可执行文件。
  • 预处理负责把include的文件包含进来及宏替换等工作。
  • 预处理之后的文件编译成汇编代码。
  • 汇编代码.s编译成.o

1、2目标文件格式的ELF

  • 常见的文件格式:A.out(最古老的)、 COFF 、PE(windows系统)、 ELF(Linux系统)
  • ABI应用程序二进制接口,在目标文件中已经是二进制兼容的格式了,目标文件适应到某一种CPU体系结构
  • ELF格式中主要有3种可执行文件:可重定位文件.o,可执行文件,共享目标文件

  • 一个ELF头在文件的开始,保存了路线图,描述了文件的组织情况
  • 当创建或增加一个进程映像的时候,系统在理论上将拷贝一个文件的段到一个虚拟的内存段

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

  • 可执行文件ELF加载到内存中去:代码的数据加载到内存中去
  • 默认ELF文件加载到0x8048000
  • 程序的实际入口0x8048300(启动一个刚加载过可执行文件之后开始执行的入口点)
  • 一般静态链接会将所有代码放在一个代码段
  • 动态链接的进程会有多个代码段

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

2、1装载可执行程序之前的动作

  • 可执行程序的执行环境:shell命令行、main函数的参数和execve参数
  • shell本身不限制命令行参数的个数,命令行参数的个数受限于命令本身
  • shell会调用execve将命令行参数和环境传递给可执行程序的main函数
  • 命令行参数和环境变量是如何保存和传递的:execve将原来的执行环境覆盖掉了,shell程序——>execve——>sys_execve然后在初始化新程序堆栈时拷贝进去
  • 先函数调用参数传递,再系统调用参数传递

2、2装载动态链接和运行时动态链接应用举例

  • 动态链接分为:可执行程序装载时动态链接和运行时动态链接
  • 准备.so文件——>编译成libshlbexample.so文件(共享库)——>编译成libdllibexample.so文件(动态装载)
  • 编译main:只提供了shellexample的-L和-l,并没有提供dllibexample的相关信息,只指明了-ldl

三、可执行程序的装载

3、1可执行程序的装载相关关键问题分析

  • execve和fork都是特殊的系统的调用,当前程序执行到execve系统调用时陷入到内核态,execve加载可执行文件把当前进程的可执行文件覆盖掉,execve返回新的可执行程序的执行起点。

  • int execve(把命令行和环境参数加载进来)
  • sys_execve内部会解析可执行文件格式:do_execve->do_execve_common->exec_binprm
  • search_binaty_handle符合文件格式,对应的解析模块(根据文件头部信息寻找对应的文件格式处理模块)
  • 对于ELF格式的可执行文件执行的是load_elf_binary

  • elf_format和init_elf_binfnt是观察者模式中的观察者
  • 寻找头文件是被观察者,出现elf格式文件,观察者自动执行elf_format模块
  • execve系统调用返回用户态从哪里开始执行:load_elf_binary->start_thread(通过修改内核堆栈中EIP的值作为新程序的起点)

3、2sys_execve的内部处理过程

  • search_binary_handler(寻找可执行文件的处理函数) fmt->load_binary(加载可执行程序的处理函数)
  • register_binfmt(注册结构体变量)
  • kernal_read读取文件信息
  • ELF可执行文件会被默认映射到0x8048000这个地址
  • 需要动态链接的可执行文件先加载连接器ld这个共享库 load_elf_interp(加载动态连接器的起点)
  • 如果是静态链接直接进入elf_entry,elf_entry是新程序的起点
  • start_thread(如果是静态链接,直接指向main8048000;如果可执行文件是动态链接库,指向动态连接器的起点

3、3使用gdb跟踪sys_execve的内部处理过程

自己实验截图:

(1)克隆,覆盖test.c

test.c文件代码:

(2)生成根文件系统时,将init hello放入rootfs地址中,这样在执行exec文件时,就自动加载hello文件

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

1、加载符号表,并连接到端口1234

2、设置断点:b sys_execve(可以先停在sys_execve然后再设置其他断点),b load_elf_binary,b start_thread。

3、执行

4、输入c继续执行,输入指令exec,list查看,按s可以跟踪进行到do_execve的内部。

3、4可执行程序的装载与庄生梦蝶的故事

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

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

  • 动态链接的过程,内核做了什么?动态链接库的依赖会形成一个图
  • ELF格式中的,.interp和.dynamic需要依赖动态链接器来解析
  • entry返回到用户态时不是返回到可执行程序规定的起点,返回到动态链接器的程序入口
  • 装载和链接之后ld将CPU的控制权交给可执行程序
  • 动态链接库的装载过程是一个图的遍历过程

四、总结

1、可执行程序的产生:

C语言代码-->编译器预处理-->编译成汇编代码-->汇编器编译成目标代码-->链接成可执行文件,再由操作系统加载到内存中执行。

2、ELF格式中主要有3种可执行文件:可重定位文件.o,可执行文件,共享目标文件。

3、ELF可执行文件会被默认映射到0x8048000这个地址。

4、命令行参数和环境变量是如何进入新程序的堆栈的?

Shell程序-->execve-->sys_execve,然后在初始化新程序堆栈时拷贝进去。

先函数调用参数传递,再系统调用参数传递。

5、当前程序执行到execve系统调用时陷入内核态,在内核中用execve加载可执行文件,把当前进程的可执行文件覆盖掉,execve系统调用返回到新的可执行程序的起点。

6、动态链接库的装载过程是一个图的遍历过程,

ELF格式中的.interp和.dynamic需要依赖动态链接器来解析,entry返回到用户态时不是返回到可执行程序规定的起点,返回到动态链接器的程序入口。

时间: 2024-10-03 19:59:56

可执行程序的装载的相关文章

《Linux内核分析》第七周学习总结 可执行程序的装载

第七周.可执行程序的装载 一.可执行程序是如何产生的? (1).c文件gcc汇编形成.s和.asm汇编代码: (2)汇编代码经过gas变成.o目标文件: (3)目标文件变成可执行文件: (4)可执行文件loader之后存储. 预处理:gcc –E –o hello.cpp hello.c –m32 编译:gcc –x cpp-output –S –o hello.s hello.cpp –m32 //编译为汇编代码 gcc –x assembler –c hello.s –o hello.o –

LINUX内核分析第七周学习总结——可执行程序的装载

LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.知识概要 (一)预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 2.目标文件的格式ELF 3.静态链接的ELF可执行文件和进程的地址空间 (二)可执行程序.共享库和动态加载 1.装载可执行程序之前的工作 2.装载时动态链接和运行时动态链接应用举例 (三)

实验七 可执行程序的装载

王康 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1,预处理,编译,链接和目标文件的格式: 1, 预处理为cpp预处理文件---hello.s汇编代码--hello.o二进制目标文件(已经含有了机器指令)--链接为可执行文件如下图,hello为二进制文件(hello和hello.o都是ELF格式文件) 均是使用共享库的,如print使用lib.c 如果静态编译就加一个-sta

第七节 可执行程序的装载

第七周 可执行程序的装载 By 20135217孙小博 本周的主要内容: 可执行程序是如何得到的以及可执行程序的目标文件格式 动态库 &动态链接库 系统调用sys_exec函数的执行过程 预处理.编译.链接和目标文件的格式 可执行程序是如何得来的 预处理:gcc –E –o hello.cpp hello.c -m32 //负责把include的文件包含进来,宏替换 编 译:gcc -x cpp-output –S hello.s –o hello.cpp -m32 //gcc –S调用ccl,

20135327郭皓--Linux内核分析第七周 可执行程序的装载

第七周 可执行程序的装载 郭皓 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 一.预处理,编译,链接和目标文件格式 1.可执行程序是怎么得来的 c代码->预处理->汇编代码->汇编器->目标代码->链接成可执行文件->加载到内核执行 2.目标文件的格式ELF 符号修饰标准.变量内层布局.函数调用方式等这些跟可执行代码二进制兼容性相关的内容称为ABI

20135201李辰希 《Linux内核分析》第七周 可执行程序的装载

李辰希  原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 编译链接的过程 1.预处理阶段 gcc -E -o XX.cpp XX.c -m32 XX.cpp是预处理文件 2.编译器生成汇编代码阶段 gcc -x cpp-output -S -o hello.s hello.cpp -m32 XX.s是汇编代码 3.汇编器

作业7:可执行程序的装载 20135115臧文君

可执行程序的装载 注:作者:臧文君,原创作品转载请注明出处,<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.预处理.编译.链接和目标文件的格式 1.可执行程序是怎么来的? 例:C语言代码-->编译器预处理-->编译成汇编代码-->汇编器编译成目标代码-->链接成可执行文件,再由操作系统加载到内存中执行 (1)预处理.cpp:负责把include的文件包含进来及宏替换等工作. gcc

20135239 益西拉姆 linux内核分析 可执行程序的装载

益西拉姆 + 原创作品请勿转载 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” week 7 可执行程序的装载 1.预处理.编译.链接和目标文件的格式 从c语言到可执行程序的由来过程 可执行文件的创建——预处理.编译和链接 以helloworld为例 -s assembler 汇编 gcc -o hello hello.o -m32 是把hello.o链接成可执行文件. ELF格式的文件是怎么回事? v

LINUX内核分析第七周——可执行程序的装载

一.得到一个可执行程序 1. 预处理.编译.链接 gcc hello.c -o hello.exe gcc编译源代码生成最终可执行的二进制程序,GCC后台隐含执行了四个阶段步骤. 预处理 => 编译 => 汇编 => 链接 预处理:编译器将C源代码中包含的头文件编译进来和执行宏替换等工作. gcc -E hello.c -o hello.i 编译:gcc首先要检查代码的规范性.是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言. gcc –S hell

LINUX内核分析第七周学习总结:可执行程序的装载

一.得到一个可执行程序 1. 预处理.编译.链接 gcc hello.c -o hello.exegcc编译源代码生成最终可执行的二进制程序,GCC后台隐含执行了四个阶段步骤.预处理 => 编译 => 汇编 => 链接预处理:编译器将C源代码中包含的头文件编译进来和执行宏替换等工作.gcc -E hello.c -o hello.i编译:gcc首先要检查代码的规范性.是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言.gcc –S hello.i –o