ELF在Linux下的加载过程

主要函数调用:

sys_execve
   | - do_execve
|
| - search_binary_handler        
           |- linux_binfmt= elf_format
       |- elf_format-> load_elf_binary
| - elf_entry = load_elf_interp()
          |-  
| if  (BAD_ADDR(elf_entry))
                |     force_sig(SIGSEGV, current);
|     retval =-EINVAL;
 

binfmt_elf.c: line 1024

              elf_entry = loc->elf_ex.e_entry;

              if (BAD_ADDR(elf_entry)) {

                     force_sig(SIGSEGV, current);

                     retval = -EINVAL;

                     goto out_free_dentry;

              }
ELF可行档的载入:


内核中实际执行execv()或execve()系统调用的程序是do_execve(),这个函数先打开目标映像文件,并从目标文件的头部(从第一个字节开始)读入若干(128)字节,然后调用另一个函数search_binary_handler(),在那里面让各种可执行程序的处理程序前来认领和处理。内核所支持的每种可执行程序都有个struct linux_binfmt数据结构,通过向内核登记挂入一个队列。而search_binary_handler(),则扫描这个队列,让各个数据结构所提供的处理程序、即各种映像格式、逐一前来认领。如果某个格式的处理程序发现特征相符而,便执行该格式映像的装入和启动。
我们从ELF格式映像的linux_binfmt数据结构开始:

#define load_elf_binary load_elf32_binary

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
};

ELF格式的二进制映像的认领、装入和启动是由load_elf_binary()完成的。而“共享库”、即动态连接库映像的装入则由load_elf_library()完成。实际上共享库的映像也是二进制的,但是一般说“二进制”映像是指带有main()函数的、可以独立运行并构成一个进程主体的可执行程序的二进制映像。


[sys_execve() > do_execve() > search_binary_handler() > load_elf_binary()]

//ELF文件头  from Linux2.6

typedef struct elf32_hdr{
  unsigned char    e_ident[EI_NIDENT];        //Magic: Class/Data/Version/Os_ABI/ABI Version
  Elf32_Half    e_type;                    //elf文件类型: 可重定位/可执行/共享目标/coredump
  Elf32_Half    e_machine;                //elf的CPU平台属性
  Elf32_Word    e_version;                //elf的版本号
  Elf32_Addr    e_entry;  /* Entry point */    //入口地址
  Elf32_Off    e_phoff;                    //program header的起始位置
  Elf32_Off    e_shoff;                    //section header的起始位置
  Elf32_Word    e_flags;                   //标记位,标记平台相关属性
  Elf32_Half    e_ehsize;               //elf文件头的大小
  Elf32_Half    e_phentsize;            //program header的大小
  Elf32_Half    e_phnum;                //program header的数目
  Elf32_Half    e_shentsize;            //section header的大小
  Elf32_Half    e_shnum;                //section header的数量
  Elf32_Half    e_shstrndx;                //段表字符串表所在的段 在段表的 索引
} Elf32_Ehdr;

     整个ELF映像就是由文件头、区段头表、程序头表、一定数量的区段、以及一定数量的部构成,而ELF映像的装入/启动过程,则就是在各种头部信息的指引下将某些部或区段装入一个进程的用户空间,并为其运行做好准备(例如装入所需的共享库),最后(在目标进程首次受调度运行时)让CPU进入其程序入口的过程。接着是对elf_bss 、elf_brk、start_code、end_code等等变量的初始化。这些变量分别纪录着当前(到此刻为止)目标映像的bss段、代码段、数据段、以及动态分配“堆” 在用户空间的位置。除start_code的初始值为0xffffffff外,其余均为0。随着映像内容的装入,这些变量也会逐步得到调整。

//ELF的 program header 结构体    from linux 2.6

typedef struct elf32_phdr{
  Elf3
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值