文档章节

内核装载,启动一个可执行程序

 游园惊梦1226
发布于 2016/04/09 15:28
字数 1448
阅读 16
收藏 0
  • 预处理:(.c -> .cpp)

  • gcc -E -o hello.cpp hello.c -m32

  • 编译:(.cpp -> .s 汇编)

  • gcc -x cpp-output -S -o hello.s hello.cpp -m32

  • 编译:(.s -> .o 二进制目标代码)

  • gcc -x assembler -c hello.s -o hello.o -m32

  • 链接:(.o -> a.out)共享库

  • gcc -o hello hello.o -m32

  • 静态编译:

  • gcc -o hello.static hello.o -m32 -static

  • c语言main函数格式:

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

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

  • execve函数格式:

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

  • 装载时动态链接

  • gcc -shared shlibexample.c -o libshlibexample.so -m32

  • 运行时动态链接

  • gcc -shared dllibexample.c -o libdllibexample.so -m32

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

  • 使用qemu和gdb调试

  • sys_execve系统调用,调用了一个do_execve函数do_execve()首先会读入可执行文件,如果可执行文件不存在,会报错。然后对可执行文件的权限进行检查。接着系统调用search_binary_handler()根据可执行文件的类型,查找到相应的处理函数。系统为每种文件类型创建了一个struct linux_binfmt,并把其串在一个链表上,执行时遍历这个链表,找到相应类型的结构。然后执行相应的load_binary()函数开始加载可执行文件。

  •    对于elf文件,执行的加载elf文件的程序为load_elf_binary(),它先读入ELF文件的头部,根据ELF文件的头部信息读入各种数据。再次扫描程序段描述表,找到类型为PT_LOAD的段,将其映射(elf_map())到内存的固定地址上。如果没有动态链接器的描述段,把返回的入口地址设置成应用程序入口。start_thread()为应用程序入口地址。start_thread()并不启动一个线程,而只是用来修改了pt_regs中保存的ip,sp寄存器的值,使其指向加载的应用程序的入口。这样当内核操作结束,返回用户态的时候,接下来执行的就是应用程序了。

  •   

  •     调用execve()系统调用之后,再调用内核的入口sys_execve()。sys_execve()进行一些参数的检查复制之后,调用do_execve()。因为可执行文件不止ELF一种,还有java程序和以“#!”开始的脚本程序等,所以do_execve()会首先检查被执行文件,读取前128个字节,特别是开头4个字节的魔数,用以判断可执行文件的格式。如果是解释型语言的脚本,前两个字节“#! 就构成了魔数,系统一旦判断到这两个字节,就对后面的字符串进行解析,以确定程序解释器的路径。

  •     当do_execve()读取了这128个字节的文件头部之后,然后调用search_binary_handle()去搜索和匹配合适的可执行文件装载处理过程。Linux中所有被支持的可执行文件格式都有相应的装载处理过程,search_binary_handle()会通过判断文件头部的魔数确定文件的格式,并且调用相应的装载处理过程。如ELF用load_elf_binary(),a.out用load_aout_binary(),脚本用load_script()。其中ELF装载过程的主要步骤是:
        ①检查ELF可执行文件格式的有效性,比如魔数、程序头表中段(Segment)的数量。
        ②寻找动态链接的”.interp”段(该段保存可执行文件所需要的动态链接器的路径),设置动态链接器路径。
        ③根据ELF可执行文件的程序头表的描述,对ELF文件进行映射,比如代码、数据、只读数据。
        ④初始化ELF进程环境,比如进程启动时EDX寄存器的地址应该是DT_FINI的地址(结束代码地址)。
        ⑤将系统调用的返回地址修改成ELF可执行文件的入口点,这个入口点取决于程序的链接方式,对于静态链接的ELF可执行文件,这个程序入口就是ELF文件的文件头中e_enEry所指的地址;对于动态链接的ELF可执行文件,程序入口点是动态链接器。
        当ELF被load_elf_binary()装载完成后,函数返回至do_execve()在返回至sys_execve()。在load_elf_binary()中(第5步)系统调用的返回地址已经被改成ELF程序的入口地址了。所以当sys_execve()系统调用从内核态返回到用户态时,EIP寄存器直接跳转到了ELF程序的入口地址,于是新的程序开始执行,ELF可执行文件装载完成。
    (3)execve在内核中的执行过程

  •  execve函数在当前进程中加载并运行包含可执行目标文件的程序。以我们代码中的可执行程序/bin/ls为例,加载并运行可执行程序主要需要以下几个步骤

  • (1)删除已存在的用户区域:删除当前进程虚拟地址的用户部分中已存在的区域结构

  • (2)隐身私有区域:为新程序的文本、数据、bss和栈区域创建新的区域结构,所有这些区域都是私有的、写实拷贝的。文本和数据区被映射为ELF可执行文件中的文本和数据区,bss区域是请求二进制零的,映射到匿名文件。栈和堆区域也是请求二进制零的,初始长度为零。

  • (3)映射共享区域:如果ELF文件与共享目标链接,比如标准C中的libc.so库,那么就需要动态链接,然后映射到用户虚拟地址空间中的共享区域。

  • (4)设置程序计数器(EIP):execve做的最后一件事就是设置当前进程上下文中的程序计数器,使之指向文本区域的入口地址。


© 著作权归作者所有

粉丝 0
博文 7
码字总数 4334
作品 0
苏州
私信 提问
自己的linux系统

前言 随着接触Linux的慢慢深入、对Linux也有了一个基本认识了吧,慢慢的接触系统内核、系统配置文件、在了解Linux的系统启动流程后,现在来总结一下一个简单的Linux系统的裁减方法和步骤,一...

王洪斌
2014/08/24
0
0
浅析Linux计算机进程地址空间与内核装载ELF

简介: 本文基于Linux™系统对进程创建与加载进行分析,文中实现了Linux库函数fork、exec,剖析内核态执行过程,并进一步展示进程创建过程中进程控制块字段变化信息及ELF文件加载过程。 一、...

nop4ss
2015/10/10
197
0
文件颜色和目录

文件颜色代表含义: 蓝色表示目录; 绿色表示可执行文件; 红色表示压缩文件; 浅蓝色表示链接文件; 白色表示其他文件; 黄色是设备文件,包括block, char, fifo。 常见目录解释 Linux各种发...

linux征服者
2017/06/04
0
0
从零开始UNIX环境高级编程(7):进程环境

0. 引言 在学习进程控制前,先了解进程运行的环境,如:main函数是如何被调用的;命令行参数是如何传递给新程序的;程序在内存空间中是什么样的结构;进程的终止方式等。 1. main函数 1.1 程...

伤口不该结疤
2017/04/24
0
0
linux 目录介绍

linux 目录介绍; /bin : 包含供每个人使用的可执行程序; /sbin: 包含仅供管理员使用的可执行程序; /lib : 包含库文件; /boot:包含内核镜像 和其他相关内容; /dev : 包含硬件外设;...

韩A
2017/04/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周四乱弹 —— 当你简历注水但还是找到了工作

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @花间小酌 :#今日歌曲推荐# 分享成龙的单曲《男儿当自强》。 《男儿当自强》- 成龙 手机党少年们想听歌,请使劲儿戳(这里) @hxg2016 :刚在...

小小编辑
今天
3K
22
靠写代码赚钱的一些门路

作者 @mezod 译者 @josephchang10 如今,通过自己的代码去赚钱变得越来越简单,不过对很多人来说依然还是很难,因为他们不知道有哪些门路。 今天给大家分享一个精彩的 GitHub 库,这个库整理...

高级农民工
昨天
5
0
用好项目管理工具,人人都可以成为项目经理

现在市面上的项目管理工具越来越多了,但是大多数都是一些协同工具或轻量项目管理工具。如果是多团队、跨部门使用或者企业级的项目管理,从管理思想到工具运用,需要适应企业的业务流程体系,...

cs平台
昨天
13
0
只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。 比较通用的返回值格式如下:...

晓月寒丶
昨天
70
0
区块链应用到供应链上的好处和实际案例

区块链可以解决供应链中的很多问题,例如记录以及追踪产品。那么使用区块链应用到各产品供应链上到底有什么好处?猎头悬赏平台解优人才网小编给大家做个简单的分享: 使用区块链的最突出的优...

猎头悬赏平台
昨天
32
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部