📄 binfmt_aout_cris.c
字号:
/* * linux/fs/binfmt_aout_cris.c * * Copyright (C) 1991, 1992, 1996 Linus Torvalds * Copyright (C) 2000 Axis Communications AB * */#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/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_binary(struct linux_binprm *, struct pt_regs * regs);static struct linux_binfmt aout_cris_format = {#ifndef MODULE NULL, NULL, load_aout_cris_binary, NULL, NULL#else NULL, &mod_use_count_, load_aout_cris_binary, NULL, NULL#endif};static void set_brk(unsigned long start, unsigned long end){ start = PAGE_ALIGN(start); end = PAGE_ALIGN(end); if (end <= start) return;#ifdef BDEBUG printk("set_brk start %p end %p\n", start, end);#endif do_mmap(NULL, start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0);}/* * create_aout_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_tables(char * p, struct linux_binprm * bprm){ unsigned long *argv,*envp; unsigned long * sp; int argc = bprm->argc; int envc = bprm->envc; sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p); printk("create_aout_tables sp = 0x%p\n", sp); sp -= envc+1; envp = sp; sp -= argc+1; argv = sp; /* remember where the argv and envp's start, by stacking their * addresses */ put_user(envp,--sp); put_user(argv,--sp); /* and remember argc as well. */ 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 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_binary(struct linux_binprm * bprm, struct pt_regs * regs){ struct aout_cris_exec ex; struct file * file; int fd; unsigned long error; unsigned long p = bprm->p; unsigned long fd_offset; unsigned long rlim; current->personality = PER_LINUX; fd_offset = 0; /*N_TXTOFF(ex);*/ ex = *(struct aout_cris_exec *) bprm->buf; /* exec-header */#ifdef BDEBUG printk("BINFMT_AOUT_CRIS: Loading file: %x\n", file); printk(" a_text %x, a_data %x\n", ex.a_text, ex.a_data);#endif if (memcmp(ex.magic, "\x08\x01\xff\x01", 4)) { printk("bad magic\n"); return -ENOEXEC; } if (flush_old_exec(bprm)) { printk("unable to flush\n"); return -ENOMEM; } /* adjust text length to incorporate header */ ex.a_text += 0x20; /* OK, This is the point of no return */ current->mm->end_code = ex.a_text + (current->mm->start_code = N_TXTADDR(ex)); current->mm->end_data = ex.a_data + (current->mm->start_data = N_DATADDR(ex)); current->mm->brk = ex.a_bss + (current->mm->start_brk = N_BSSADDR(ex));#ifdef BDEBUG printk(" start_code %p, end_code %p\n", current->mm->start_code, current->mm->end_code); printk(" start_data %p, end_data %p\n", current->mm->start_data, current->mm->end_data); printk(" start_brk %p, brk %p\n", current->mm->start_brk, current->mm->brk);#endif current->mm->rss = 0; current->mm->mmap = NULL; current->suid = current->euid = current->fsuid = bprm->e_uid; current->sgid = current->egid = current->fsgid = bprm->e_gid; current->flags &= ~PF_FORKNOEXEC; fd = open_inode(bprm->inode, O_RDONLY); if(fd < 0) return fd; file = current->files->fd[fd]; /* if we cant mmap the file, we need to read it in completely */ if (!file->f_op || !file->f_op->mmap) { printk(" cannot mmap - reading whole file\n"); sys_close(fd); do_mmap(NULL, 0, ex.a_text+ex.a_data, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0); goto beyond_if; }#if 0 /* for now map text+data in same segment */ error = do_mmap(file, N_TXTADDR(ex), sizeof(ex) + ex.a_text + ex.a_data, PROT_READ | PROT_EXEC | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset); sys_close(fd); if (error != N_TXTADDR(ex)) { printk(" could not mmap text+data segment: %d\n", error); send_sig(SIGKILL, current, 0); return error; }#else /* ok. mmap the text segment at the correct address */ error = do_mmap(file, N_TXTADDR(ex), ex.a_text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset); if (error != N_TXTADDR(ex)) { printk(" could not mmap text segment: %d\n", error); sys_close(fd); send_sig(SIGKILL, current, 0); return error; } #if 0 printk("%x %x %x %x %x %x\n", *(long *)0x2020, *(long *)0x2024, *(long *)0x2028, *(long *)0x202c, *(long *)0x2030, *(long *)0x2034);#endif /* and the data segment */ error = do_mmap(file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); sys_close(fd); if (error != N_DATADDR(ex)) { printk(" could not mmap data segment: %d\n", error); send_sig(SIGKILL, current, 0); return error; }#endif beyond_if: 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 = &aout_cris_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 = setup_arg_pages(p, bprm); p = (unsigned long) create_aout_tables((char *)p, bprm); current->mm->start_stack = p; /* Haven't really decided on these actual registers; have to look around. Change later, maybe. */ /* for libc initial debug output */ regs->r9 = (unsigned long) console_print_etrax; /* argc, argv and envp are on the stack. crt0.c should really * unstack them but because of legacy we do like this for now. */ regs->r3 = ((unsigned long *)p)[0]; regs->r4 = ((unsigned long *)p)[1]; regs->r5 = ((unsigned long *)p)[2]; regs->r2 = p; /* in theory, this isn't needed anymore */#ifdef BDEBUG printk("start_thread at 0x%p, usp 0x%p\n", N_TXTADDR(ex) + 32, p);#endif //TRACE_ON(); start_thread(regs, N_TXTADDR(ex) + 32, p); if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); return 0;}static intload_aout_cris_binary(struct linux_binprm * bprm, struct pt_regs * regs){ int retval; MOD_INC_USE_COUNT; retval = do_load_aout_cris_binary(bprm, regs); MOD_DEC_USE_COUNT; return retval;}int init_aout_cris_binfmt(void) { return register_binfmt(&aout_cris_format);}#ifdef MODULEint init_module(void) { return init_aout_cris_binfmt();}void cleanup_module( void) { unregister_binfmt(&aout_cris_format);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -