load_elf_binary阅读(2)
来源:互联网 发布:淘宝运营论坛 编辑:程序博客网 时间:2024/05/21 05:18
/*
* Check to see if the section's size will overflow the
* allowed task size. Note that p_filesz must always be
* <= p_memsz so it is only necessary to check p_memsz.
*/
if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
elf_ppnt->p_memsz > TASK_SIZE || 判断使用的空间是否小于分配空间
TASK_SIZE - elf_ppnt->p_memsz < k) {
/* set_brk can never work. Avoid overflows. */
send_sig(SIGKILL, current, 0);
retval = -EINVAL;
goto out_free_dentry;
}
k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; 段虚拟地址加上段大小就到了段尾
if (k > elf_bss)
elf_bss = k; 后面接elf_bss
if ((elf_ppnt->p_flags & PF_X) && end_code < k) ELF 段标志可执行 并且指令段不在K
end_code = k; 指令段后面接段
if (end_data < k)
end_data = k; 数据段连接
k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; k又设为内存映像地址末尾
if (k > elf_brk)
elf_brk = k;
}
循环结束
loc->elf_ex.e_entry += load_bias; 把地址转换成内存地址
elf_bss += load_bias;
elf_brk += load_bias;
start_code += load_bias;
end_code += load_bias;
start_data += load_bias;
end_data += load_bias;
/* Calling set_brk effectively mmaps the pages that we need
* for the bss and break sections. We must do this before
* mapping in the interpreter, to make sure it doesn't wind
* up getting placed where the bss needs to go.
*/
retval = set_brk(elf_bss, elf_brk);
if (retval) {
send_sig(SIGKILL, current, 0);
goto out_free_dentry;
}
if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
send_sig(SIGSEGV, current, 0);
retval = -EFAULT; /* Nobody gets to see this, but.. */
goto out_free_dentry;
}
if (elf_interpreter) { 判断是否需要解释器
unsigned long uninitialized_var(interp_map_addr);
elf_entry = load_elf_interp(&loc->interp_elf_ex,
interpreter,
&interp_map_addr,
load_bias);
if (!IS_ERR((void *)elf_entry)) {
/*
* load_elf_interp() returns relocation
* adjustment
*/ 这个是基地址重定位?
interp_load_addr = elf_entry;
elf_entry += loc->interp_elf_ex.e_entry;
}
if (BAD_ADDR(elf_entry)) {
force_sig(SIGSEGV, current);
retval = IS_ERR((void *)elf_entry) ?
(int)elf_entry : -EINVAL;
goto out_free_dentry;
}
reloc_func_desc = interp_load_addr;
fput(interpreter); 递减file文件中的共享计数
kfree(elf_interpreter); 用完释放
} else {
elf_entry = loc->elf_ex.e_entry;
if (BAD_ADDR(elf_entry)) {
force_sig(SIGSEGV, current);
retval = -EINVAL;
goto out_free_dentry;
}
}
kfree(elf_phdata); 释放
set_binfmt(&elf_format); 设置进程的binfmt ELF格式
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
retval = arch_setup_additional_pages(bprm, !!elf_interpreter);
if (retval < 0) {
send_sig(SIGKILL, current, 0);
goto out;
}
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
retval = create_elf_tables(bprm, &loc->elf_ex,
load_addr, interp_load_addr);
if (retval < 0) {
send_sig(SIGKILL, current, 0);
goto out;
}
/* N.B. passed_fileno might not be initialized? */
current->mm->end_code = end_code; 代码段结束地址
current->mm->start_code = start_code; 代码段起始地址
current->mm->start_data = start_data; 数据段起始地址
current->mm->end_data = end_data; 数据段结束地址
current->mm->start_stack = bprm->p; 栈的起始地址
#ifdef arch_randomize_brk
if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1))
current->mm->brk = current->mm->start_brk =
arch_randomize_brk(current->mm);
#endif
if (current->personality & MMAP_PAGE_ZERO) {
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior.
Since we do not have the power to recompile these, we
emulate the SVr4 behavior. Sigh. */
down_write(¤t->mm->mmap_sem); 写信号
error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, 访问权限可读可执行
MAP_FIXED | MAP_PRIVATE, 0); 地址固定,私有
up_write(¤t->mm->mmap_sem); 写信号
}
#ifdef ELF_PLAT_INIT
/*
* The ABI may specify that certain registers be set up in special
* ways (on i386 %edx is the address of a DT_FINI function, for
* example. In addition, it may also specify (eg, PowerPC64 ELF)
* that the e_entry field is the address of the function descriptor
* for the startup routine, rather than the address of the startup
* routine itself. This macro performs whatever initialization to
* the regs structure is required as well as any relocations to the
* function descriptor entries when executing dynamically links apps.
*/
ELF_PLAT_INIT(regs, reloc_func_desc);
#endif
start_thread(regs, elf_entry, bprm->p); 开始进程
retval = 0;
out:
kfree(loc);
out_ret:
return retval;
/* error cleanup */
out_free_dentry:
allow_write_access(interpreter);
if (interpreter)
fput(interpreter);
out_free_interp:
kfree(elf_interpreter);
out_free_ph:
kfree(elf_phdata);
goto out;
}
* Check to see if the section's size will overflow the
* allowed task size. Note that p_filesz must always be
* <= p_memsz so it is only necessary to check p_memsz.
*/
if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
elf_ppnt->p_memsz > TASK_SIZE || 判断使用的空间是否小于分配空间
TASK_SIZE - elf_ppnt->p_memsz < k) {
/* set_brk can never work. Avoid overflows. */
send_sig(SIGKILL, current, 0);
retval = -EINVAL;
goto out_free_dentry;
}
k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; 段虚拟地址加上段大小就到了段尾
if (k > elf_bss)
elf_bss = k; 后面接elf_bss
if ((elf_ppnt->p_flags & PF_X) && end_code < k) ELF 段标志可执行 并且指令段不在K
end_code = k; 指令段后面接段
if (end_data < k)
end_data = k; 数据段连接
k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; k又设为内存映像地址末尾
if (k > elf_brk)
elf_brk = k;
}
循环结束
loc->elf_ex.e_entry += load_bias; 把地址转换成内存地址
elf_bss += load_bias;
elf_brk += load_bias;
start_code += load_bias;
end_code += load_bias;
start_data += load_bias;
end_data += load_bias;
/* Calling set_brk effectively mmaps the pages that we need
* for the bss and break sections. We must do this before
* mapping in the interpreter, to make sure it doesn't wind
* up getting placed where the bss needs to go.
*/
retval = set_brk(elf_bss, elf_brk);
if (retval) {
send_sig(SIGKILL, current, 0);
goto out_free_dentry;
}
if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
send_sig(SIGSEGV, current, 0);
retval = -EFAULT; /* Nobody gets to see this, but.. */
goto out_free_dentry;
}
static int set_brk(unsigned long start, unsigned long end)
{
start = PAGE_ALIGN(start);
end = PAGE_ALIGN(end);
if (end > start) {
unsigned long addr;
down_write(¤t->mm->mmap_sem);
addr = do_brk(start, end - start);
up_write(¤t->mm->mmap_sem);
if (BAD_ADDR(addr))
return addr;
}
return 0;
}
if (elf_interpreter) { 判断是否需要解释器
unsigned long uninitialized_var(interp_map_addr);
elf_entry = load_elf_interp(&loc->interp_elf_ex,
interpreter,
&interp_map_addr,
load_bias);
if (!IS_ERR((void *)elf_entry)) {
/*
* load_elf_interp() returns relocation
* adjustment
*/ 这个是基地址重定位?
interp_load_addr = elf_entry;
elf_entry += loc->interp_elf_ex.e_entry;
}
if (BAD_ADDR(elf_entry)) {
force_sig(SIGSEGV, current);
retval = IS_ERR((void *)elf_entry) ?
(int)elf_entry : -EINVAL;
goto out_free_dentry;
}
reloc_func_desc = interp_load_addr;
allow_write_access(interpreter); 防止其他进程在读入可执行文件期间通过内存映射改变它的内容点击(此处)折叠或打开
- /* This is much more generalized than the library routine read function,
- so we keep this separate. Technically the library read function
- is only provided so that we can read a.out libraries that have
- an ELF header */
- static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
- struct file *interpreter, unsigned long *interp_map_addr,
- unsigned long no_base)
- {
- struct elf_phdr *elf_phdata;
- struct elf_phdr *eppnt;
- unsigned long load_addr = 0;
- int load_addr_set = 0;
- unsigned long last_bss = 0, elf_bss = 0;
- unsigned long error = ~0UL;
- unsigned long total_size;
- int retval, i, size;
- /* First of all, some simple consistency checks */
- if (interp_elf_ex->e_type != ET_EXEC &&
- interp_elf_ex->e_type != ET_DYN) 判断是否是可执行文件和共享库,否则goto out
- goto out;
- if (!elf_check_arch(interp_elf_ex)) 判断头结构
- goto out;
- if (!interpreter->f_op || !interpreter->f_op->mmap) f_op是否为脏? 是否有内存映射?
- goto out;
- /*
- * If the size of this structure has changed, then punt, since
- * we will be doing the wrong thing.
- */
- if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) 判断项是否和段大小一致
- goto out;
- if (interp_elf_ex->e_phnum < 1 ||
- interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr)) 判断是否有程序头个数是否正常1~0xffff
- goto out;
- /* Now read in all of the header information */
- size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum; 读取头
- if (size > ELF_MIN_ALIGN)
- goto out;
- elf_phdata = kmalloc(size, GFP_KERNEL); 为其分配空间
- if (!elf_phdata)
- goto out;
- retval = kernel_read(interpreter, interp_elf_ex->e_phoff,
- (char *)elf_phdata,size);
- error = -EIO;
- if (retval != size) {
- if (retval < 0)
- error = retval;
- goto out_close;
- }
- total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
- if (!total_size) {
- error = -EINVAL;
- goto out_close;
- }
- eppnt = elf_phdata;
- for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
- if (eppnt->p_type == PT_LOAD) {
- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
- int elf_prot = 0;
- unsigned long vaddr = 0;
- unsigned long k, map_addr;
- if (eppnt->p_flags & PF_R)
- elf_prot = PROT_READ;
- if (eppnt->p_flags & PF_W)
- elf_prot |= PROT_WRITE;
- if (eppnt->p_flags & PF_X)
- elf_prot |= PROT_EXEC;
- vaddr = eppnt->p_vaddr;
- if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
- elf_type |= MAP_FIXED;
- else if (no_base && interp_elf_ex->e_type == ET_DYN)
- load_addr = -vaddr;
- map_addr = elf_map(interpreter, load_addr + vaddr,
- eppnt, elf_prot, elf_type, total_size);
- total_size = 0;
- if (!*interp_map_addr)
- *interp_map_addr = map_addr;
- error = map_addr;
- if (BAD_ADDR(map_addr))
- goto out_close;
- if (!load_addr_set &&
- interp_elf_ex->e_type == ET_DYN) {
- load_addr = map_addr - ELF_PAGESTART(vaddr);
- load_addr_set = 1;
- }
- /*
- * Check to see if the section's size will overflow the
- * allowed task size. Note that p_filesz must always be
- * <= p_memsize so it's only necessary to check p_memsz.
- */
- k = load_addr + eppnt->p_vaddr;
- if (BAD_ADDR(k) ||
- eppnt->p_filesz > eppnt->p_memsz ||
- eppnt->p_memsz > TASK_SIZE ||
- TASK_SIZE - eppnt->p_memsz < k) {
- error = -ENOMEM;
- goto out_close;
- }
- /*
- * Find the end of the file mapping for this phdr, and
- * keep track of the largest address we see for this.
- */
- k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
- if (k > elf_bss)
- elf_bss = k;
- /*
- * Do the same thing for the memory mapping - between
- * elf_bss and last_bss is the bss section.
- */
- k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
- if (k > last_bss)
- last_bss = k;
- }
- }
- if (last_bss > elf_bss) {
- /*
- * Now fill out the bss section. First pad the last page up
- * to the page boundary, and then perform a mmap to make sure
- * that there are zero-mapped pages up to and including the
- * last bss page.
- */
- if (padzero(elf_bss)) {
- error = -EFAULT;
- goto out_close;
- }
- /* What we have mapped so far */
- elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);
- /* Map the last of the bss segment */
- down_write(¤t->mm->mmap_sem);
- error = do_brk(elf_bss, last_bss - elf_bss);
- up_write(¤t->mm->mmap_sem);
- if (BAD_ADDR(error))
- goto out_close;
- }
- error = load_addr;
- out_close:
- kfree(elf_phdata);
- out:
- return error;
- }
fput(interpreter); 递减file文件中的共享计数
kfree(elf_interpreter); 用完释放
} else {
elf_entry = loc->elf_ex.e_entry;
if (BAD_ADDR(elf_entry)) {
force_sig(SIGSEGV, current);
retval = -EINVAL;
goto out_free_dentry;
}
}
kfree(elf_phdata); 释放
set_binfmt(&elf_format); 设置进程的binfmt ELF格式
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
retval = arch_setup_additional_pages(bprm, !!elf_interpreter);
if (retval < 0) {
send_sig(SIGKILL, current, 0);
goto out;
}
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
retval = create_elf_tables(bprm, &loc->elf_ex,
load_addr, interp_load_addr);
if (retval < 0) {
send_sig(SIGKILL, current, 0);
goto out;
}
/* N.B. passed_fileno might not be initialized? */
current->mm->end_code = end_code; 代码段结束地址
current->mm->start_code = start_code; 代码段起始地址
current->mm->start_data = start_data; 数据段起始地址
current->mm->end_data = end_data; 数据段结束地址
current->mm->start_stack = bprm->p; 栈的起始地址
#ifdef arch_randomize_brk
if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1))
current->mm->brk = current->mm->start_brk =
arch_randomize_brk(current->mm);
#endif
if (current->personality & MMAP_PAGE_ZERO) {
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior.
Since we do not have the power to recompile these, we
emulate the SVr4 behavior. Sigh. */
down_write(¤t->mm->mmap_sem); 写信号
error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, 访问权限可读可执行
MAP_FIXED | MAP_PRIVATE, 0); 地址固定,私有
up_write(¤t->mm->mmap_sem); 写信号
}
#ifdef ELF_PLAT_INIT
/*
* The ABI may specify that certain registers be set up in special
* ways (on i386 %edx is the address of a DT_FINI function, for
* example. In addition, it may also specify (eg, PowerPC64 ELF)
* that the e_entry field is the address of the function descriptor
* for the startup routine, rather than the address of the startup
* routine itself. This macro performs whatever initialization to
* the regs structure is required as well as any relocations to the
* function descriptor entries when executing dynamically links apps.
*/
ELF_PLAT_INIT(regs, reloc_func_desc);
#endif
start_thread(regs, elf_entry, bprm->p); 开始进程
retval = 0;
out:
kfree(loc);
out_ret:
return retval;
/* error cleanup */
out_free_dentry:
allow_write_access(interpreter);
if (interpreter)
fput(interpreter);
out_free_interp:
kfree(elf_interpreter);
out_free_ph:
kfree(elf_phdata);
goto out;
}
0
上一篇:load_elf_binary阅读(1)
下一篇:main.c阅读
相关热门文章
- QEMU源码分析系列(四)...
- linux binary程序获得 运行时r...
- innobackupex 整库备份
- 查看dbms_stat源代码的取经路...
- 二叉搜索树(BinarySearchTree...
- linux 常见服务端口
- xmanager 2.0 for linux配置
- 【ROOTFS搭建】busybox的httpd...
- openwrt中luci学习笔记
- 什么是shell
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
0 0
- load_elf_binary阅读(2)
- load_elf_binary阅读(1)
- load_elf_binary中使用的内存映射机制
- ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三)
- Struts2 源码阅读(2)_扩展阅读
- Struts2 源码阅读(2)_扩展阅读
- 阅读lcc(2)
- OS161 源代码阅读-2
- PcShare2005代码阅读(2)
- 《影响力2》阅读笔记
- mudos阅读笔记2
- TCPL 阅读笔记 2
- OpenCV源码阅读(2)
- srilm 阅读文档2
- 如何阅读源代码(2)
- 《华为研发》阅读 - 2
- 源代码阅读技巧2
- 怎样阅读文献-2
- Android ActionBar隐藏修改图标和标题
- qwt 6.1.0集成进Qt creator 2.8.1步骤
- tq2440编译ARM版本的Qt4出错问题解决
- load_elf_binary阅读(1)
- 设计模式之装饰者模式
- load_elf_binary阅读(2)
- 日本“冷知识”你都知道吗?
- main.c阅读
- preloader_exec整理
- JAVA基础【3.10】《Java核心技术1》Java的基本程序设计结构-数组
- wld_start
- umask函数linux
- MFC打开文件对话框
- 文章标题
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
小腿肿胀发硬怎么办
小腿肚肿胀发硬怎么办
老人家手脚麻痹怎么办
颈椎疼痛难忍怎么办
老人手麻怎么办
老年人手脚麻木怎么办
颈椎病手发麻怎么办
晚上手麻怎么办
半夜手臂麻到醒怎么办
颈椎病头皮发麻怎么办
睡觉左手发麻怎么办
睡觉后手发麻怎么办
孕晚期手麻手胀怎么办
高血压手脚发麻怎么办
手脚发麻怎么办?
脚底发麻发热怎么办
风湿腰痛怎么办
颈椎病双手麻木怎么办
老年人手抖怎么办
突然手抖怎么办
激动手抖怎么办
低血糖犯了怎么办
我手机不见了怎么办
长得太帅被打怎么办
婚姻不合怎么办
三观崩塌怎么办
右腿比左腿粗怎么办
宝宝吃着奶睡觉怎么办
不支持gpt分区怎么办
头顶有点脱发怎么办
尿频尿不尽怎么办
夜间尿频怎么办
黑便怎么办
腹泻便血怎么办
感冒舌苔发黑怎么办
左睾丸疼怎么办
心突然疼怎么办
睾丸下垂怎么办
阴囊囊肿怎么办
睾丸疼痛肿大怎么办
睾丸发炎肿大怎么办