Linux操作系统--装载ELF文件

注意:本文中的大部分是阅读 《程序员的自我修养》 作 者:俞甲子,石凡,潘爱民 的读书笔记。推荐大家看看这本书。


Linux操作系统下,我们在bash进程中,输入命令后,bash进程调用fork创建新进程,新进程调用execve()系统调用执行指定ELF文件,原先的bash进程继续返回等待刚开启的进程结束,然后继续等待用户输入。新进程使用execve系统调用。这个调用的原型为:

int execve(const char *filename ,char *const argv[],char *const envp[])。参数即执行的程序文件名、执行参数和环境变量。Glibc对其进行了封装,提供了execl、execlp、execle、execv、execvp等不同形式的exec系列API。

以下是miniBash的代码。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(){

char buf[1024];

pid_t pid;

while(1){

printf("miniBash$");
scanf("%s",buf);
pid=fork();

if(pid==0){
if(execlp(buf,0)<0){

printf("exec error\n");
}

}else if(pid>0){

int status;
waitpid(pid,&status,0);

}else{


printf("fork error%d\n",pid);

}



}


return 0;


}

execve()系统调用的入口是sys_execve(),其在arch\i386\kernel\Process.c中,sys_execve进行参数检查复制后,调用do_execve()。其首先查找被执行的文件,如果找到,读取其前128字节,以判断文件是Java还是Windows PE,还是Linux ELF

等(通过魔数判断),例如ELF的头4个字节为0x7F,Java为cafe,Shell则由于其第一行一般是#!/bin/sh,所以前两个字节是#和!。

当do_execve获取这128字节文件头部后,调用search_binary_handle()搜索和匹配合适的可执行文件装载处理程序,通过上述判断魔数,获知调用对应的处理过程,比如ELF的处理过程为load_elf_binary();Shell脚本则是load_script()。

load_elf_binary被定义在fs/Binfmt_elf.c。

其主要步骤为:

1,检查ELF文件有效性

2,寻找动态链接的“.interp”段,设置动态链接器路径。

3,根据ELF程序头表,对ELF文件进行映射

4,初始化进程环境,比如EDX寄存器是否是DT_FINI的地址(动态链接)

5,将系统调用返回地址初始化为ELF文件入口地址,对于静态链接的ELF可执行文件即ELF文件头的e_entry,动态链接的ELF可执行文件,则是动态链接器。

当load_elf_binary返回、do_execve返回到sys_execve(),系统调用返回地址已经被第5步改成了ELF文件入口。sys_execve()返回到用户态,EIP寄存器是ELF程序入口,程序开始执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值