zoukankan      html  css  js  c++  java
  • Chap-6 6.5 ELF可执行文件的装载

    6.5 Linux装载ELF可执行文件的过程
    当我们在Linux系统的bash下输入一个命令执行某个ELF文件时,Linux是怎样装载这个ELF文件并且执行它呢?
    首先在用户层面,bash进程会调用fork()系统调用常见一个新进程,然后新的进程调用execve()系统调用执行
    指定的ELF文件,原先的bash进程继续返回等待刚才启动的新进程结束。
    在进入execve()系统调用后,Linux内核就开始进行真正的装载工作。在内核中,execve()系统调用相应的入口是
    sys_execve(),它被定义在arch/i386/kernel/process.c文件中。sys_execve()进行一些参数的检查复制后,调用
    do_execve()。do_execve()会首先查找被执行的文件,如果找到文件,则读取前128个字节。

    为什么要读取前128个字节?因为Linux支持的可执行文件不止一种,还有a.out、Java程序和以"#!"开始的脚本
    程序。这里do_execve()读取文件的前128个字节的目的是判断文件的格式,每种可执行文件开头的几个字节是
    非常特殊的,特别是开头的4个字节,常常称为魔数(Magic Number),通过对魔数的判断可以确定文件的格式
    和类型。比如ELF可执行文件格式开头的4个字节为0x7f、“e”、“l”、“f”;Java的可执行文件的前4个字节为“c”、
    “a”、“f”、“e”;如果可执行文件是shell脚本或者perl、python等解释性脚本程序,那么它的第一行往往是
    “#!/bin/sh”或者“#!/usr/bin/perl”或者“#!/usr/bin/python”,这时候前两个字节就够成了魔数,系统一旦判断
    到这两个字节,就对后面的字符串进行解析,以确定具体的解释程序的路径。

    当do_execve()读取了128字节的文件头部后,会调用search_binary_handle(),该函数会通过判断文件头部的
    魔数确定文件的格式,并且调用相应的装载处理过程。比如ELF可执行文件的装载处理过程叫做load_elf_binary(),
    它的主要步骤是:
    1.检查ELF可执行文件格式的有效性,比如魔数、程序头表中段(segment)的数量
    2.寻找动态链接的.interp段,设置动态链接器路径
    3.根据ELF可执行文件的程序头表的描述,对ELF文件进行映射、比如代码、数据、只读数据
    4.初始化ELF进程环境,比如进程启动时edx寄存器的地址应该是DT_FINI的地址
    5.将系统调用的返回地址修改成ELF可执行文件的入口点,这个入口点取决于程序的链接方式,对于静态链接
    的ELF文件,这个程序入口就是ELF文件头中e_entry所指的地址。对于动态链接的ELF可执行文件,程序入口点
    是动态链接器。
    当load_elf_binary()执行完毕,返回至do_execve()再返回至sys_execve()时,上面的第5步中已经把系统调用的
    返回地址修改为被装载ELF程序的入口地址,所以当sys_execve()系统调用从内核态返回到用户态时,EIP寄存器
    直接跳转到ELF程序的入口地址,于是新的程序开始执行,ELF可执行文件装载完成。

  • 相关阅读:
    Eclipse配置SVN的几种方法及使用详情
    重新定位svn地址的方法(windows和linux),svn switch(sw)的帮助信息
    SVN版本库修改URL路径或者IP地址
    DEA中MAVEN项目有多个子目录,如何加载构建
    DBA的40条军规
    搜索 比MySQL快10倍?这可能是目前AWS Aurora最详解读!
    HttpClient 4.5.3 get和post请求
    基于HttpClient4.5.2实现的HttpClient工具类
    httpClient使用总结
    为何只能在其关联的线程内启动timer?(Qt会检查一致性,否则就不执行)
  • 原文地址:https://www.cnblogs.com/miaoyong/p/3514599.html
Copyright © 2011-2022 走看看