20135132陈雨鑫 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”

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

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

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

过程:

​.c文件汇编成汇编代码.asm,

再汇编成目标码.o,

链接成可执行文件a.out,

最后可执行文件就可以加载到内存中执行。

2、目标文件的格式ELF

1)主要有三种目标文件

可重定位文件、可执行文件、共享文件

2)ELF文件加载到内存是如何加载的呢?

代码、数据都加载到内存中,默认ELF文件从0x开始加载,开始加载的是头部,会有一些信息,所以入口地址0x(这个地方就是程序的实际入口,可执行文件加载到内存中开始执行的第一行代码从这里开始)

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

入口地址为0x8048*00

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

1、使用exec*库函数加载一个可执行文件

(1)动态链接分为可执行程序转载时动态链接和运行时动态链接

1)在linux下动态链接的文件是.so

2)libshlibexample.so文件(生成一个共享库文件)

libdllibexample.so(生成可动态加载文件)

(2)若是静态链接的,elf_entry就是指向可执行文件里边规定的那个头部,即main函数对应的位置,若这个可执行文件是需要依赖其它动态链接库的话,则elf_entry就是指向动态链接器的起点

2、

(1)execve:当前的可执行程序在执行execve这个系统调用的时候,它陷入到内核态,在内核态里它用这个execve加载的这个可执行文件把当前进程的可执行程序给覆盖掉,当execve这个系统调用返回的时候,返回的不是原来的那个可执行程序了,而是新的可执行程序了,它返回的是新的可执行程序的起点,即main函数大致的位置

(2)ELF文件加载到内存是如何加载的呢?

代码、数据都加载到内存中,默认ELF文件从0x开始加载,开始加载的是头部,会有一些信息,所以入口地址0x(这个地方就是程序的实际入口,可执行文件加载到内存中开始执行的第一行代码从这里开始)

•命令行参数和shell环境,一般我们执行一个程序的Shell环境,我们的实验直接使用execve系统调用。

•$ ls -l /usr/bin 列出/usr/bin下的目录信息

•Shell本身不限制命令行参数的个数,命令行参数的个数受限于命令自身

•例如,int main(int argc, char *argv[])

•又如, int main(int argc, char *argv[], char *envp[])

•Shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数

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

•库函数exec*都是execve的封装例程

命令行参数和环境串都放在用户态堆栈中

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

动态链接分为可执行程序装载时动态链接和运行时动态链接,如下代码演示了这两种动态链接。

•准备.so文件

shlibexample.h (1.3 KB) - Interface of Shared Lib Example

shlibexample.c (1.2 KB) - Implement of Shared Lib Example

编译成libshlibexample.so文件

1.$ gcc -shared shlibexample.c -o libshlibexample.so -m32

dllibexample.h (1.3 KB) - Interface of Dynamical Loading Lib Example

dllibexample.c (1.3 KB) - Implement of Dynamical Loading Lib Example

编译成libdllibexample.so文件

1.$ gcc -shared dllibexample.c -o libdllibexample.so -m32

•分别以共享库和动态加载共享库的方式使用libshlibexample.so文件和libdllibexample.so文件

main.c  (1.9 KB) - Main program

编译main,注意这里只提供shlibexample的-L(库对应的接口头文件所在目录)和-l(库名,如libshlibexample.so去掉lib和.so的部分),并没有提供dllibexample的相关信息,只是指明了-ldl

1.$ gcc main.c -o main -L/path/to/your/dir -lshlibexample -ldl -m32

2.$ export LD_LIBRARY_PATH=$PWD #将当前目录加入默认路径,否则main找不到依赖的库文件,当然也可以将库文件copy到默认路径下。

3.$ ./main

4.This is a Main program!

5.Calling SharedLibApi() function of libshlibexample.so!

6.This is a shared libary!

7.Calling DynamicalLoadingLibApi() function of libdllibexample.so!

8.This is a Dynamical Loading libary!

三、可执行程序的装载

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

(1)可执行程序的装载实际上相当于系统调用。execve系统调用比较特殊。

(2)sys_execve内核处理过程:

  • do_execve -> do_execve_common -> exec_binprm
  • 最后根据给出的文件名加载文件头部信息寻找对应的文件格式处理模块。

(3)fmt->load_binary(bprm):用来解析ELF格式文件的执行的位置,这个位置是load_elf_binary。

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

本质上是观察者模式,通过修改内核堆栈中EIP的值作为新程序的起点。

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

2. sys_execve的内部处理过程

do_ execve调用do_ execve_ common,do_ execve_ common主要依靠exec_ binprm,其中重要的函数:search_binary_handler(bprm)。

  • 打开file文件,找到文件头部,把命令行参数和环境变量copy到结构体中:retval=copy_strings(bprm->envc, envp, bprm);
  • 寻找打开的可执行文件处理函数:ret= search_binary_handler(bprm);
  • 寻找能够解析当前可执行文件的模块,load_ binary加载这个模块,实际调用的是binfmt_ elf.c:retval=fmt->load_binary(bprm);
  • ELF可执行文件会被默认映射到0X8048000这个地址;
  • 需要动态链接的可执行文件先加载连接器ld;否则直接把ELF文件entry地址赋值给entry;
  • start_ thread(regs, elf_ entry, bprm->p)将CPU控制权交给ld来加载依赖库并完成动态链接。对于静态链接的文件elf_entry是新程序执行的起点

通过实验用gdb跟踪分析一个execve系统调用内核处理函数sys_execve ,验证对Linux系统加载可执行程序所需处理过程的理解

实验过程:

把menu删掉,重新克隆一份

进入test.c中查看:

进入makefile中查看:

开始使用gdb跟踪​:

new_ip是返回到用户态的第一条指令的地址 看该可执行程序的入口点地址,发现和new_ip的位置是一样的。

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

四、浅谈Linux内核装载和启动一个可执行程序

  检查ELF可执行文件的有效性,寻找动态链接的“.interp”段,设置动态链接器路径(与动态链接有关),根据ELF可执行文件的程序头表的描述,对ELF文件进行映射,比如代码,数据,只读数据,代码、数据都加载到内存中,默认ELF文件从0x开始加载,开始加载的是头部,会有一些信息,所以入口地址0x(这个地方就是程序的实际入口,可执行文件加载到内存中开始执行的第一行代码从这里开始),初始化ELF进程环境,比如进程启动时EDX寄存器的地址应该是DT_FINI的地址(和动态链接有关),将系统调用的返回地址修改为ELF可执行文件的入口,这个入口点取决于程序的链接方式,对于静态链接的可执行文件,若是静态链接的,elf_entry就是指向可执行文件里边规定的那个头部,即main函数对应的位置,若这个可执行文件是需要依赖其它动态链接库的话,则elf_entry就是指向动态链接器的起点。

《Linux内核分析》第七周笔记 可执行程序的装载的更多相关文章

  1. Linux内核分析第七周学习笔记——Linux内核如何装载和启动一个可执行程序

    Linux内核分析第七周学习笔记--Linux内核如何装载和启动一个可执行程序 zl + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study. ...

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

    LINUX内核分析第七周学习总结:可执行程序的装载 韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

  3. Linux内核分析 第七周 可执行程序的装载

    张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核分析 第七 ...

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

    Linux内核分析第七周---可执行程序的装载 李雪琦+原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/US ...

  5. LINUX内核分析第七周学习总结

    LINUX内核分析第七周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...

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

    LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

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

    第七周 可执行程序的装载 郭皓 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 ...

  8. linux内核分析 第七周

    一.课堂相关 (一)预处理.编译.链接和目标文件的格式 1.可执行程序是怎么得来的 C代码--预处理--汇编代码--目标代码--可执行文件 预处理负责把include的文件包含进来及宏替换工作. he ...

  9. "Linux内核分析"第七周

    可执行程序的装载 张文俊+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.预 ...

随机推荐

  1. 【PAT】B1052 卖个萌(20 分)

    实在不想写这个题,好费劲,头疼,这是粘的柳婼的代码 ,等我有空再自己用c写吧 #include <iostream> #include <vector> using names ...

  2. 01LaTeX学习系列之---TeX的介绍与认识

    目录 01TeX的介绍与认识 目录 前言 (一)TeX 的宣传 TeX - Beauty and Fun 1. TeX 是什么? 2. TeX 是哪家公司生产的? 3. 我们今天主角的名字怎么念啊?& ...

  3. SQL查询语句,怎样查询重复数据

    SQL查询语句,怎样查询重复数据 2012-02-22 14:50神奇的马骁勇 | 浏览 0 次 有表A, 中有字段id, name, memo现在有很多id重复的数据,怎么把这些重复的都查出来?gr ...

  4. 深入浅出RxJava(二:操作符)

    看完这篇blog,我相信你肯定想立即在你的项目中使用RxJava了,这篇blog将介绍许多RxJava中的操作符,RxJava的强大性就来自于它所定义的操作符. 首先先看一个例子: 准备工作 假设我有 ...

  5. MySql常用命令集Mysql常用命令3

    MYSQL常用命令 有很多朋友虽然安装好了mysql但却不知如何使用它.在这篇文章中我们就从连接 MYSQL.修改密码.增加用户等方面来学习一些MYSQL的常用命令. 有很多朋友虽然安装好了mysql ...

  6. 从头到尾使用Geth的说明-2-cli可用命令-有2个地方标红,之后查查源码后看看能不能解决

    geth - the go-ethereum command line interface 以太坊命令行接口 格式: geth [options] command [command options] ...

  7. docker安装与卸载

    文章转自:https://www.cnblogs.com/yufeng218/p/8370670.html  (EE安装) https://blog.csdn.net/jxyzh11/article/ ...

  8. Struts 2.5.20 在Eclipse IDE中的配置和开发实例

    零.参考博客1.Struts框架入门教程2.Struts 2.5.10.1配置 3.eclipse中搭建Struts2.5.16 4.Struts2.5+eclipse+tomcat8.5配置 注意: ...

  9. [转]QT子线程与主线程的信号槽通信-亲测可用!

    近用QT做一个服务器,众所周知,QT的主线程必须保持畅通,才能刷新UI.所以,网络通信端采用新开线程的方式.在涉及到使用子线程更新Ui上的控件时遇到了点儿麻烦.网上提供了很多同一线程不同类间采用信号槽 ...

  10. ARM汇编语言基础

    ARM 与 Thumb 寄存器对应关系 PC寄存器: ARM状态为R15,Thumb状态为PC LR寄存器: ARM状态为R14,Thumb状态为LR SP寄存器: ARM状态为R13,Thumb状态 ...