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 + -
显示快捷键?