binfmt_flat.c

来自「elinux jffs初始版本 具体了解JFFS的文件系统!」· C语言 代码 · 共 355 行

C
355
字号
/* *  linux/fs/binfmt_flat.c * *  Copyright (C) 1991, 1992, 1996  Linus Torvalds */#include <linux/module.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/a.out.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/fcntl.h>#include <linux/ptrace.h>#include <linux/user.h>#include <linux/malloc.h>#include <linux/binfmts.h>#include <linux/personality.h>#include <asm/system.h>#include <asm/segment.h>#include <asm/pgtable.h>#include <asm/flat.h>static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);extern void dump_thread(struct pt_regs *, struct user *);static struct linux_binfmt flat_format = {#ifndef MODULE	NULL, NULL, load_flat_binary, NULL, NULL#else	NULL, &mod_use_count_, load_flat_binary, NULL, NULL#endif};static unsigned long putstring(unsigned long p, char * string){	unsigned long l = strlen(string)+1;#ifdef DEBUG	printk("put_string '%s'\n", string);#endif	p -= l;	memcpy((void*)p, string, l);	return p;}static unsigned long putstringarray(unsigned long p, int count, char ** array){	/*p=putstring(p, "");*/	/*printk("p1=%x, array=%x\n", p, array);	printk("array[0]=%x\n", array[0]);*/#ifdef DEBUG	printk("putstringarray(%d)\n", count);#endif	while(count) {		p=putstring(p, array[--count]);#ifdef DEBUG		printk("p2=%x\n", p);#endif	}	return p;}static unsigned long stringarraylen(int count, char ** array){	int l = 4;	while(count) {		l += strlen(array[--count]);		l++;		l+=4;	}	return l;}/* * create_flat_tables() parses the env- and arg-strings in new user * memory and creates the pointer tables from them, and puts their * addresses on the "stack", returning the new stack pointer value. */static unsigned long create_flat_tables(unsigned long pp, struct linux_binprm * bprm){	unsigned long *argv,*envp;	unsigned long * sp;	char * p = (char*)pp;	int argc = bprm->argc;	int envc = bprm->envc;	sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);#ifdef __alpha__/* whee.. test-programs are so much fun. */	put_user(0, --sp);	put_user(0, --sp);	if (bprm->loader) {		put_user(0, --sp);		put_user(0x3eb, --sp);		put_user(bprm->loader, --sp);		put_user(0x3ea, --sp);	}	put_user(bprm->exec, --sp);	put_user(0x3e9, --sp);#endif	sp -= envc+1;	envp = sp;	sp -= argc+1;	argv = sp;#if defined(__i386__) || defined(__mc68000__)	put_user(envp,--sp);	put_user(argv,--sp);#endif	put_user(argc,--sp);	current->mm->arg_start = (unsigned long) p;	while (argc-->0) {		put_user(p,argv++);		while (get_user(p++)) /* nothing */ ;	}	put_user(NULL,argv);	current->mm->arg_end = current->mm->env_start = (unsigned long) p;	while (envc-->0) {		put_user(p,envp++);		while (get_user(p++)) /* nothing */ ;	}	put_user(NULL,envp);	current->mm->env_end = (unsigned long) p;	return (unsigned long)sp;}/* * These are the functions used to load a.out style executables and shared * libraries.  There is no binary dependent code anywhere else. */inline intdo_load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs){	struct flat_hdr * hdr;	struct file * file;	unsigned long error;	unsigned long pos;	unsigned long p = bprm->p;	unsigned long data_len, bss_len, stack_len, code_len;	current->personality = PER_LINUX;		file = current->files->fd[open_inode(bprm->inode, O_RDONLY)];	#ifdef DEBUG	printk("BINFMT_FLAT: Loading file: %x\n", file);	show_free_areas();#endif	/*for(i=0;i<16;i++) {		printk("%.2x ", ((char*)error)[i] & 0xff);	}	printk("\n");*/		hdr = (struct flat_hdr*)bprm->buf;		if (strncmp(hdr->magic, "bFLT", 4) || (hdr->rev != 1)) {		printk("bad magic/rev\n");		return -ENOEXEC;	}	if (flush_old_exec(bprm)) {		printk("unable to flush\n");		return -ENOMEM;	}		/*printk("hdr->entry = %d, hdr->data_start = %d, hdr->data_end = %d, hdr->bss_end = %d, hdr->stack_size = %d\n",		hdr->entry, hdr->data_start, hdr->data_end,		hdr->bss_end, hdr->stack_size);*/	/* OK, This is the point of no return */	code_len = hdr->data_start;	data_len = hdr->data_end - hdr->data_start;	bss_len = hdr->bss_end - hdr->data_end;	stack_len = hdr->stack_size;		/* Make room on stack for arguments & environment */	stack_len += strlen(bprm->filename) + 1;	stack_len += stringarraylen(bprm->envc, bprm->envp);	stack_len += stringarraylen(bprm->argc, bprm->argv);		/*stack_len += 4-((pos+data_len+bss_len+stack_len) & 3);*/ /* Align stack */	/*printk("Stack = %d, (%d)\n", stack_len, stack_len & 3);*/	error = do_mmap(file,		0,               code_len + data_len + bss_len + stack_len,               PROT_READ|PROT_EXEC,               0, /* MAP_* */               0);#ifdef DEBUG        printk("BINFMT_FLAT: mmap returned: %x\n", error);	show_free_areas();#endif		if (is_in_rom(error)) {#ifdef DEBUG		printk("BINFMT_FLAT: ROM mapping of file\n");#endif		/* do_mmap returned a ROM mapping, so allocate RAM for data + bss + stack */		/*pos = kmalloc(data_len+bss_len+stack_len, GFP_KERNEL);*/		pos = do_mmap(0, 0, data_len+bss_len+stack_len, PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);		#ifdef DEBUG		printk("BINFMT_FLAT: Allocated data+bss+stack: %x\n", pos);		show_free_areas();#endif		/* And then fill it in */	 	/*printk("Reading data from %d-%d to %x\n", hdr->data_start, hdr->data_end - hdr->data_start, pos);*/		read_exec(bprm->inode, hdr->data_start, (char *)pos,			  data_len, 0); 		/*printk("Clearing %x to %x\n", pos+data_len, pos+data_len+bss_len+stack_len);*/	        memset((void*)(pos + data_len), 0, bss_len + stack_len);	} else {#ifdef DEBUG		printk("BINFMT_FLAT: RAM mapping of file\n");#endif				/* Since we got a RAM mapping, mmap has already allocated a block for us, and		   read in the data. . */		pos = error + code_len;			}			current->mm->start_code = error + hdr->entry;	current->mm->end_code = error + hdr->data_start;	current->mm->start_data = pos;		current->mm->end_data = pos + data_len;	current->mm->brk = pos + data_len + bss_len;	/*printk("start_code: %x, end_code: %x\n", current->mm->start_code,current->mm->end_code);	printk("start_data: %x, end_data: %x\n", current->mm->start_data,current->mm->end_data);*/	current->mm->rss = 0;	current->suid = current->euid = current->fsuid = bprm->e_uid;	current->sgid = current->egid = current->fsgid = bprm->e_gid; 	current->flags &= ~PF_FORKNOEXEC; 	 	current->mm->executable = bprm->inode; 	        	/*for(i=0;i<16;i++) {		printk("%.2x ", ((char*)pos)[i] & 0xff);	}	printk("\n");*/		if (current->exec_domain && current->exec_domain->use_count)		(*current->exec_domain->use_count)--;	if (current->binfmt && current->binfmt->use_count)		(*current->binfmt->use_count)--;	current->exec_domain = lookup_exec_domain(current->personality);	current->binfmt = &flat_format;	if (current->exec_domain && current->exec_domain->use_count)		(*current->exec_domain->use_count)++;	if (current->binfmt && current->binfmt->use_count)		(*current->binfmt->use_count)++;	/*set_brk(current->mm->start_brk, current->mm->brk);*/	p = pos + data_len + bss_len + stack_len - 4;	#ifdef DEBUG	printk("p=%x\n", p);#endif		p = putstringarray(p, 1, &bprm->filename);#ifdef DEBUG	printk("p(filename)=%x\n", p);#endif	p = putstringarray(p, bprm->envc, bprm->envp);#ifdef DEBUG	printk("p(envp)=%x\n", p);#endif	p = putstringarray(p, bprm->argc, bprm->argv);#ifdef DEBUG	printk("p(argv)=%x\n", p);#endif	p = create_flat_tables(p, bprm);#ifdef DEBUG	printk("p(create_flat_tables)=%x\n", p);		printk("arg_start = %x\n", current->mm->arg_start);	printk("arg_end = %x\n", current->mm->arg_end);	printk("env_start = %x\n", current->mm->env_start);	printk("env_end = %x\n", current->mm->env_end);#endif	current->mm->start_stack = p;	/*printk("start_stack: %x\n", current->mm->start_stack);*/		/* FIXME, wrong number of arguments.. what is a5??	start_thread(regs, current->mm->start_code, current->mm->start_data - hdr->data_start, p);	*/	if (current->flags & PF_PTRACED)		send_sig(SIGTRAP, current, 0);	return 0;}static intload_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs){	int retval;	MOD_INC_USE_COUNT;	retval = do_load_flat_binary(bprm, regs);	MOD_DEC_USE_COUNT;	return retval;}int init_flat_binfmt(void) {	return register_binfmt(&flat_format);}#ifdef MODULEint init_module(void) {	return init_flat_binfmt();}void cleanup_module( void) {	unregister_binfmt(&flat_format);}#endif

⌨️ 快捷键说明

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