binfmt_aout_cris_flat.c

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

C
589
字号
/* *  linux/fs/binfmt_aout_cris_flat.c * *  Copyright (C) 1991, 1992, 1996  Linus Torvalds *  Copyright (C) 1998, 1999  Hans-Peter Nilsson, Axis Communications * *   Lots stolen from binfmt_flat from the uClinux project, but *   I did not find a good enough reason to go with their format. * */#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/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/a.out.h>#include <asm/svinto.h>#include <asm/eshlibld.h>#include <asm/io.h>#undef DEBUG//#define BDEBUG/* Do sanity checking.  Enable if you're paranoid or if they're after you. */#ifdef DEBUG#define SANITYCHECK_RELOC#endif#define MAX(a,b) ((a) > (b) ? (a) : (b))static int load_aout_cris_flat_binary(struct linux_binprm *, struct pt_regs * regs);static struct linux_binfmt aout_cris_flat_format = {#ifndef MODULE	NULL, NULL, load_aout_cris_flat_binary, NULL, NULL#else	NULL, &mod_use_count_, load_aout_cris_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;}/* Not the same as the "flat" one; this one stores the vector   pointer in arrayp and puts a NULL after the array too. */static unsigned long putstringarray(unsigned long p, int count,                                    char *** arrayp){        char **arrv;        char **array = *arrayp;#ifdef DEBUG	printk("putstringarray(%d)\n", count);#endif        /* First, make some room for the array itself. */        p = (unsigned long) arrv = *arrayp = ((char **) p) - count - 1;        /* Store the final NULL */        arrv[count] = NULL;        /* Loop over the strings, storing the pointer as we           store each string. */	while (count) {		p = putstring(p, array[--count]);                arrv[count] = (char *) p;#ifdef DEBUG		printk("arrv[%d] (0x%x) = %x, \n", count, &arrv[count], 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_aout_cris_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_aout_cris_flat_tables(unsigned long pp, struct linux_binprm * bprm){	unsigned long * sp;	char **argv;        char **envp;	char * p = (char*)pp;	int argc,envc;        struct mm_struct *mm = current->mm;        /* We happen to know that pp is now the address           *after* the string table (that is, p points to the           actual strings, which are located *before* the string           table in envp). */        envp = bprm->envp;        envc = bprm->envc;	p = (char *) putstringarray((unsigned long) p, envc,                                    &envp);	/* env_start and env_end are the start and end of the actual strings, not the argv */        mm->env_start = (unsigned long) p;        mm->env_end = (unsigned long) envp;#ifdef DEBUG	printk("p(envp)=%x\n", p);#endif        /* Align it for the next user: argv. */	p = (char *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);        argv = bprm->argv;        argc = bprm->argc;	p = (char *) putstringarray((unsigned long) p, argc,                                    &argv);        mm->arg_start = (unsigned long) p;        mm->arg_end = (unsigned long) argv;#ifdef DEBUG	printk("p(argv)=%x, argv = 0x%x, *argv = 0x%x, **argv = %c%c%c\n", argv, *argv, *argv[0],	       *argv[1], *argv[2]);#endif        /* Don't forget to align the actual stack.           Its alignment should not depend on the strings in argv :-) */	sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);	return (unsigned long)sp;}asmlinkage int system_call(void);void console_print_etrax(char *buf);/* * These are the functions used to load a.out style executables and shared * libraries.  There is no binary dependent code anywhere else. *//* mmap might return an error, but not all negative long's are errors, some might be  * addresses. */#define MMAP_ERRLIMIT 0xffff0000inline intdo_load_aout_cris_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs){	struct aout_cris_exec * hdr;	struct file * file;        int fd;	unsigned long startaddr, dataaddr, bssaddr, stackaddr;	unsigned long p = bprm->p;	unsigned long data_len, bss_len, stack_len, code_len;	current->personality = PER_LINUX;	        fd = open_inode(bprm->inode, O_RDONLY);	file = current->files->fd[fd];#ifdef BDEBUG	printk("BINFMT_AOUT_CRIS_FLAT: Loading file: %x\n", file);	show_free_areas();#endif	hdr = (struct aout_cris_exec *) bprm->buf;		if (memcmp(hdr->magic, "\x08\x01\xff\x01", 4)) {		printk("bad magic\n");		return -ENOEXEC;	}	if (flush_old_exec(bprm)) {		printk("unable to flush\n");		return -ENOMEM;	}		/* OK, This is the point of no return */	code_len = hdr->a_text;	data_len = hdr->a_data;	bss_len = hdr->a_bss;        /* Note: we don't have to care whether the code mapping           is to ram or rom this way (except when there are           relocs that have to be resolved; then we have to           write there, but then we say that, so then no ROM           mapping should take place). */	startaddr = do_mmap(file,                            0,                            code_len,#if 0 /* ??? FIXME: Using is_in_rom() and do_mmap(read-only) does not    work (see below on mmaping relocs), so make sure this gets    PROT_WRITE always, until is_in_rom() and that stuff *works*. */                            (hdr->a_trsize == 0 ?                             (PROT_READ|PROT_EXEC)                             : (PROT_READ|PROT_EXEC|PROT_WRITE)),#else                            (PROT_READ|PROT_EXEC|PROT_WRITE),#endif                            0, /* MAP_*:  Since binfmt_flat.c                                  does not have anything here,                                  we don't as well.  */                            /* Skip the header; it's not part of                               the text segment. */                            32);        /* Mapping failed? */        if (startaddr > MMAP_ERRLIMIT) {		printk("Couldn't mmap code, error %d.\n", -startaddr);                sys_close(fd);                send_sig(SIGKILL, current, 0);                return -ENOMEM;        }        /* Get a piece for data.  No PROT_EXEC; no reason.            You might think that we should do one single segment           for code and data; but then the code in that segment           cannot be shared.  You might think that bss+data           should be in one mmapped segment, but that would lead           to unnecessary file reads (and we have to wipe out           what was read into bss afterward).             Most of this would be better if we could use mmap to           read in the relocs (which would be in the area later           occupied by bss), and later munmap the parts we will           not use further.  But no shrinking is possible - at           all. */        dataaddr = do_mmap(file, 0,                           data_len,                           PROT_READ|PROT_WRITE, 0,                           32 + code_len);        /* Mapping failed? */        if (dataaddr > MMAP_ERRLIMIT) {		printk("Couldn't mmap data.\n");                sys_close(fd);                send_sig(SIGKILL, current, 0);                return -ENOMEM;        }        bssaddr = do_mmap(NULL, 0, bss_len,                          PROT_READ|PROT_WRITE, 0, 0);        /* Mapping failed? */        if (bssaddr > MMAP_ERRLIMIT) {		printk("Couldn't mmap bss.\n");                sys_close(fd);                send_sig(SIGKILL, current, 0);                return -ENOMEM;        }        /* Luckily, do_mmap() has cleared the area, so we don't           need to do that here.  Otherwise, there would'd been           a memset call here. */        /* Read in relocs in a segment if its own, which we           later unmap. */        if (hdr->a_trsize || hdr->a_drsize)        {

⌨️ 快捷键说明

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