⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irixelf.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	*name = NULL;	for(i = 0; i < pnum; i++, epp++) {		if (epp->p_type != PT_INTERP)			continue;		/* It is illegal to have two interpreters for one executable. */		if (*name != NULL)			goto out;		*name = (char *) kmalloc((epp->p_filesz +					  strlen(IRIX_INTERP_PREFIX)),					 GFP_KERNEL);		if (!*name)			return -ENOMEM;		strcpy(*name, IRIX_INTERP_PREFIX);		retval = kernel_read(bprm->file, epp->p_offset, (*name + 16),		                     epp->p_filesz);		if (retval < 0)			goto out;		file = open_exec(*name);		if (IS_ERR(file)) {			retval = PTR_ERR(file);			goto out;		}		retval = kernel_read(file, 0, bprm->buf, 128);		if (retval < 0)			goto dput_and_out;		*interp_elf_ex = *(struct elfhdr *) bprm->buf;	}	*interpreter = file;	return 0;dput_and_out:	fput(file);out:	kfree(*name);	return retval;}static inline int verify_irix_interpreter(struct elfhdr *ihp){	if (memcmp(ihp->e_ident, ELFMAG, SELFMAG) != 0)		return -ELIBBAD;	return 0;}#define EXEC_MAP_FLAGS (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE)static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnum,				  unsigned int *estack, unsigned int *laddr,				  unsigned int *scode, unsigned int *ebss,				  unsigned int *ecode, unsigned int *edata,				  unsigned int *ebrk){	unsigned int tmp;	int i, prot;	for(i = 0; i < pnum; i++, epp++) {		if(epp->p_type != PT_LOAD)			continue;		/* Map it. */		prot  = (epp->p_flags & PF_R) ? PROT_READ : 0;		prot |= (epp->p_flags & PF_W) ? PROT_WRITE : 0;		prot |= (epp->p_flags & PF_X) ? PROT_EXEC : 0;	        down(&current->mm->mmap_sem);		(void) do_mmap(fp, (epp->p_vaddr & 0xfffff000),			       (epp->p_filesz + (epp->p_vaddr & 0xfff)),			       prot, EXEC_MAP_FLAGS,			       (epp->p_offset & 0xfffff000));	        up(&current->mm->mmap_sem);		/* Fixup location tracking vars. */		if((epp->p_vaddr & 0xfffff000) < *estack)			*estack = (epp->p_vaddr & 0xfffff000);		if(!*laddr)			*laddr = epp->p_vaddr - epp->p_offset;		if(epp->p_vaddr < *scode)			*scode = epp->p_vaddr;		tmp = epp->p_vaddr + epp->p_filesz;		if(tmp > *ebss)			*ebss = tmp;		if((epp->p_flags & PF_X) && *ecode < tmp)			*ecode = tmp;		if(*edata < tmp)			*edata = tmp;		tmp = epp->p_vaddr + epp->p_memsz;		if(tmp > *ebrk)			*ebrk = tmp;	}}static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp,				  struct file *interp, unsigned int *iladdr,				  int pnum, mm_segment_t old_fs,				  unsigned int *eentry){	int i;	*eentry = 0xffffffff;	for(i = 0; i < pnum; i++, epp++) {		if(epp->p_type != PT_INTERP)			continue;		/* We should have fielded this error elsewhere... */		if(*eentry != 0xffffffff)			return -1;		set_fs(old_fs);		*eentry = load_irix_interp(ihp, interp, iladdr);		old_fs = get_fs();		set_fs(get_ds());		fput(interp);		if (*eentry == 0xffffffff)			return -1;	}	return 0;}/* * IRIX maps a page at 0x200000 that holds information about the  * process and the system, here we map the page and fill the * structure */void irix_map_prda_page (void){	unsigned long v;	struct prda *pp;	v =  do_brk (PRDA_ADDRESS, PAGE_SIZE);		if (v < 0)		return;	pp = (struct prda *) v;	pp->prda_sys.t_pid  = current->pid;	pp->prda_sys.t_prid = read_32bit_cp0_register (CP0_PRID);	pp->prda_sys.t_rpid = current->pid;	/* We leave the rest set to zero */}		/* These are the functions used to load ELF style executables and shared * libraries.  There is no binary dependent code anywhere else. */static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs){	struct elfhdr elf_ex, interp_elf_ex;	struct file *interpreter;	struct elf_phdr *elf_phdata, *elf_ihdr, *elf_ephdr;	unsigned int load_addr, elf_bss, elf_brk;	unsigned int elf_entry, interp_load_addr = 0;	unsigned int start_code, end_code, end_data, elf_stack;	int retval, has_interp, has_ephdr, size, i;	char *elf_interpreter;	mm_segment_t old_fs;		load_addr = 0;	has_interp = has_ephdr = 0;	elf_ihdr = elf_ephdr = 0;	elf_ex = *((struct elfhdr *) bprm->buf);	retval = -ENOEXEC;	if (verify_binary(&elf_ex, bprm))		goto out;#ifdef DEBUG_ELF	print_elfhdr(&elf_ex);#endif	/* Now read in all of the header information */	size = elf_ex.e_phentsize * elf_ex.e_phnum;	if (size > 65536)		goto out;	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);	if (elf_phdata == NULL) {		retval = -ENOMEM;		goto out;	}	retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *)elf_phdata, size);	if (retval < 0)		goto out_free_ph;#ifdef DEBUG_ELF	dump_phdrs(elf_phdata, elf_ex.e_phnum);#endif	/* Set some things for later. */	for(i = 0; i < elf_ex.e_phnum; i++) {		switch(elf_phdata[i].p_type) {		case PT_INTERP:			has_interp = 1;			elf_ihdr = &elf_phdata[i];			break;		case PT_PHDR:			has_ephdr = 1;			elf_ephdr = &elf_phdata[i];			break;		};	}#ifdef DEBUG_ELF	printk("\n");#endif	elf_bss = 0;	elf_brk = 0;	elf_stack = 0xffffffff;	elf_interpreter = NULL;	start_code = 0xffffffff;	end_code = 0;	end_data = 0;	retval = look_for_irix_interpreter(&elf_interpreter,	                                   &interpreter,					   &interp_elf_ex, elf_phdata, bprm,					   elf_ex.e_phnum);	if (retval)		goto out_free_file;	if (elf_interpreter) {		retval = verify_irix_interpreter(&interp_elf_ex);		if(retval)			goto out_free_interp;	}	/* OK, we are done with that, now set up the arg stuff,	 * and then start this sucker up.	 */	retval = -E2BIG;	if (!bprm->sh_bang && !bprm->p)		goto out_free_interp;	/* Flush all traces of the currently running executable */	retval = flush_old_exec(bprm);	if (retval)		goto out_free_dentry;	/* OK, This is the point of no return */	current->mm->end_data = 0;	current->mm->end_code = 0;	current->mm->mmap = NULL;	current->flags &= ~PF_FORKNOEXEC;	elf_entry = (unsigned int) elf_ex.e_entry;		/* Do this so that we can load the interpreter, if need be.  We will	 * change some of these later.	 */	current->mm->rss = 0;	setup_arg_pages(bprm);	current->mm->start_stack = bprm->p;	/* At this point, we assume that the image should be loaded at	 * fixed address, not at a variable address.	 */	old_fs = get_fs();	set_fs(get_ds());	map_executable(bprm->file, elf_phdata, elf_ex.e_phnum, &elf_stack,	               &load_addr, &start_code, &elf_bss, &end_code,	               &end_data, &elf_brk);	if(elf_interpreter) {		retval = map_interpreter(elf_phdata, &interp_elf_ex,					 interpreter, &interp_load_addr,					 elf_ex.e_phnum, old_fs, &elf_entry);		kfree(elf_interpreter);		if(retval) {			set_fs(old_fs);			printk("Unable to load IRIX ELF interpreter\n");			send_sig(SIGSEGV, current, 0);			retval = 0;			goto out_free_file;		}	}	set_fs(old_fs);	kfree(elf_phdata);	set_personality(PER_IRIX32);	set_binfmt(&irix_format);	compute_creds(bprm);	current->flags &= ~PF_FORKNOEXEC;	bprm->p = (unsigned long) 	  create_irix_tables((char *)bprm->p, bprm->argc, bprm->envc,			(elf_interpreter ? &elf_ex : NULL),			load_addr, interp_load_addr, regs, elf_ephdr);	current->mm->start_brk = current->mm->brk = elf_brk;	current->mm->end_code = end_code;	current->mm->start_code = start_code;	current->mm->end_data = end_data;	current->mm->start_stack = bprm->p;	/* Calling set_brk effectively mmaps the pages that we need for the	 * bss and break sections.	 */	set_brk(elf_bss, elf_brk);	/*	 * IRIX maps a page at 0x200000 which holds some system	 * information.  Programs depend on this.	 */	irix_map_prda_page ();	padzero(elf_bss);#ifdef DEBUG_ELF	printk("(start_brk) %lx\n" , (long) current->mm->start_brk);	printk("(end_code) %lx\n" , (long) current->mm->end_code);	printk("(start_code) %lx\n" , (long) current->mm->start_code);	printk("(end_data) %lx\n" , (long) current->mm->end_data);	printk("(start_stack) %lx\n" , (long) current->mm->start_stack);	printk("(brk) %lx\n" , (long) current->mm->brk);#endif#if 0 /* XXX No fucking way dude... */	/* 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(&current->mm->mmap_sem);	(void) do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,		       MAP_FIXED | MAP_PRIVATE, 0);	up(&current->mm->mmap_sem);#endif	start_thread(regs, elf_entry, bprm->p);	if (current->ptrace & PT_PTRACED)		send_sig(SIGTRAP, current, 0);	return 0;out:	return retval;out_free_dentry:	allow_write_access(interpreter);	fput(interpreter);out_free_interp:	if (elf_interpreter)		kfree(elf_interpreter);out_free_file:out_free_ph:	kfree (elf_phdata);	goto out;}/* This is really simpleminded and specialized - we are loading an * a.out library that is given an ELF header. */static int load_irix_library(struct file *file){	struct elfhdr elf_ex;	struct elf_phdr *elf_phdata  =  NULL;	unsigned int len = 0;	int elf_bss = 0;	int retval;	unsigned int bss;	int error;	int i,j, k;	error = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex));	if (error != sizeof(elf_ex))		return -ENOEXEC;	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)		return -ENOEXEC;	/* First of all, some simple consistency checks. */	if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||	   !irix_elf_check_arch(&elf_ex) || !file->f_op->mmap)		return -ENOEXEC;		/* Now read in all of the header information. */	if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)		return -ENOEXEC;		elf_phdata =  (struct elf_phdr *) 		kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);	if (elf_phdata == NULL)		return -ENOMEM;		retval = kernel_read(file, elf_ex.e_phoff, (char *) elf_phdata,			   sizeof(struct elf_phdr) * elf_ex.e_phnum);		j = 0;	for(i=0; i<elf_ex.e_phnum; i++)		if((elf_phdata + i)->p_type == PT_LOAD) j++;		if(j != 1)  {		kfree(elf_phdata);		return -ENOEXEC;	}		while(elf_phdata->p_type != PT_LOAD) elf_phdata++;		/* Now use mmap to map the library into memory. */	down(&current->mm->mmap_sem);	error = do_mmap(file,			elf_phdata->p_vaddr & 0xfffff000,			elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),			PROT_READ | PROT_WRITE | PROT_EXEC,			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,			elf_phdata->p_offset & 0xfffff000);	up(&current->mm->mmap_sem);	k = elf_phdata->p_vaddr + elf_phdata->p_filesz;	if (k > elf_bss) elf_bss = k;	if (error != (elf_phdata->p_vaddr & 0xfffff000)) {		kfree(elf_phdata);		return error;	}	padzero(elf_bss);	len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;	if (bss > len)	  do_brk(len, bss-len);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -