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

📄 irixelf.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * irixelf.c: Code to load IRIX ELF executables which conform to *            the MIPS ABI. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * * Based upon work which is: * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com). */#include <linux/module.h>#include <linux/fs.h>#include <linux/stat.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/a.out.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/signal.h>#include <linux/binfmts.h>#include <linux/string.h>#include <linux/file.h>#include <linux/fcntl.h>#include <linux/ptrace.h>#include <linux/malloc.h>#include <linux/shm.h>#include <linux/personality.h>#include <linux/elfcore.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <asm/pgalloc.h>#include <asm/mipsregs.h>#include <asm/prctl.h>#define DLINFO_ITEMS 12#include <linux/elf.h>#undef DEBUG_ELFstatic int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs);static int load_irix_library(struct file *);static int irix_core_dump(long signr, struct pt_regs * regs,                          struct file *file);extern int dump_fpu (elf_fpregset_t *);static struct linux_binfmt irix_format = {	NULL, THIS_MODULE, load_irix_binary, load_irix_library,	irix_core_dump, PAGE_SIZE};#ifndef elf_addr_t#define elf_addr_t unsigned long#define elf_caddr_t char *#endif#ifdef DEBUG_ELF/* Debugging routines. */static char *get_elf_p_type(Elf32_Word p_type){	int i = (int) p_type;	switch(i) {	case PT_NULL: return("PT_NULL"); break;	case PT_LOAD: return("PT_LOAD"); break;	case PT_DYNAMIC: return("PT_DYNAMIC"); break;	case PT_INTERP: return("PT_INTERP"); break;	case PT_NOTE: return("PT_NOTE"); break;	case PT_SHLIB: return("PT_SHLIB"); break;	case PT_PHDR: return("PT_PHDR"); break;	case PT_LOPROC: return("PT_LOPROC/REGINFO"); break;	case PT_HIPROC: return("PT_HIPROC"); break;	default: return("PT_BOGUS"); break;	}}static void print_elfhdr(struct elfhdr *ehp){	int i;	printk("ELFHDR: e_ident<");	for(i = 0; i < (EI_NIDENT - 1); i++) printk("%x ", ehp->e_ident[i]);	printk("%x>\n", ehp->e_ident[i]);	printk("        e_type[%04x] e_machine[%04x] e_version[%08lx]\n",	       (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine,	       (unsigned long) ehp->e_version);	printk("        e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] "	       "e_flags[%08lx]\n",	       (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff,	       (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags);	printk("        e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n",	       (unsigned short) ehp->e_ehsize, (unsigned short) ehp->e_phentsize,	       (unsigned short) ehp->e_phnum);	printk("        e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n",	       (unsigned short) ehp->e_shentsize, (unsigned short) ehp->e_shnum,	       (unsigned short) ehp->e_shstrndx);}static void print_phdr(int i, struct elf_phdr *ep){	printk("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] "	       "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type),	       (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr,	       (unsigned long) ep->p_paddr);	printk("         p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] "	       "p_align[%08lx]\n", (unsigned long) ep->p_filesz,	       (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags,	       (unsigned long) ep->p_align);}static void dump_phdrs(struct elf_phdr *ep, int pnum){	int i;	for(i = 0; i < pnum; i++, ep++) {		if((ep->p_type == PT_LOAD) ||		   (ep->p_type == PT_INTERP) ||		   (ep->p_type == PT_PHDR))			print_phdr(i, ep);	}}#endif /* (DEBUG_ELF) */static void set_brk(unsigned long start, unsigned long end){	start = PAGE_ALIGN(start);	end = PAGE_ALIGN(end);	if (end <= start) 		return;	do_brk(start, end - start);}/* We need to explicitly zero any fractional pages * after the data section (i.e. bss).  This would * contain the junk from the file that should not * be in memory. */static void padzero(unsigned long elf_bss){	unsigned long nbyte;	nbyte = elf_bss & (PAGE_SIZE-1);	if (nbyte) {		nbyte = PAGE_SIZE - nbyte;		clear_user((void *) elf_bss, nbyte);	}}unsigned long * create_irix_tables(char * p, int argc, int envc,				   struct elfhdr * exec, unsigned int load_addr,				   unsigned int interp_load_addr,				   struct pt_regs *regs, struct elf_phdr *ephdr){	elf_caddr_t *argv;	elf_caddr_t *envp;	elf_addr_t *sp, *csp;	#ifdef DEBUG_ELF	printk("create_irix_tables: p[%p] argc[%d] envc[%d] "	       "load_addr[%08x] interp_load_addr[%08x]\n",	       p, argc, envc, load_addr, interp_load_addr);#endif	sp = (elf_addr_t *) (~15UL & (unsigned long) p);	csp = sp;	csp -= exec ? DLINFO_ITEMS*2 : 2;	csp -= envc+1;	csp -= argc+1;	csp -= 1;		/* argc itself */	if ((unsigned long)csp & 15UL) {		sp -= (16UL - ((unsigned long)csp & 15UL)) / sizeof(*sp);	}	/*	 * Put the ELF interpreter info on the stack	 */#define NEW_AUX_ENT(nr, id, val) \	  __put_user ((id), sp+(nr*2)); \	  __put_user ((val), sp+(nr*2+1)); \	sp -= 2;	NEW_AUX_ENT(0, AT_NULL, 0);	if(exec) {		sp -= 11*2;		NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff);		NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr));		NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum);		NEW_AUX_ENT (3, AT_PAGESZ, ELF_EXEC_PAGESIZE);		NEW_AUX_ENT (4, AT_BASE, interp_load_addr);		NEW_AUX_ENT (5, AT_FLAGS, 0);		NEW_AUX_ENT (6, AT_ENTRY, (elf_addr_t) exec->e_entry);		NEW_AUX_ENT (7, AT_UID, (elf_addr_t) current->uid);		NEW_AUX_ENT (8, AT_EUID, (elf_addr_t) current->euid);		NEW_AUX_ENT (9, AT_GID, (elf_addr_t) current->gid);		NEW_AUX_ENT (10, AT_EGID, (elf_addr_t) current->egid);	}#undef NEW_AUX_ENT	sp -= envc+1;	envp = (elf_caddr_t *) sp;	sp -= argc+1;	argv = (elf_caddr_t *) sp;	__put_user((elf_addr_t)argc,--sp);	current->mm->arg_start = (unsigned long) p;	while (argc-->0) {		__put_user((elf_caddr_t)(unsigned long)p,argv++);		p += strlen_user(p);	}	__put_user(NULL, argv);	current->mm->arg_end = current->mm->env_start = (unsigned long) p;	while (envc-->0) {		__put_user((elf_caddr_t)(unsigned long)p,envp++);		p += strlen_user(p);	}	__put_user(NULL, envp);	current->mm->env_end = (unsigned long) p;	return sp;}/* This is much more generalized than the library routine read function, * so we keep this separate.  Technically the library read function * is only provided so that we can read a.out libraries that have * an ELF header. */static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,				     struct file * interpreter,				     unsigned int *interp_load_addr){	struct elf_phdr *elf_phdata  =  NULL;	struct elf_phdr *eppnt;	unsigned int len;	unsigned int load_addr;	int elf_bss;	int retval;	unsigned int last_bss;	int error;	int i;	unsigned int k;	elf_bss = 0;	last_bss = 0;	error = load_addr = 0;	#ifdef DEBUG_ELF	print_elfhdr(interp_elf_ex);#endif	/* First of all, some simple consistency checks */	if ((interp_elf_ex->e_type != ET_EXEC &&	     interp_elf_ex->e_type != ET_DYN) ||	     !irix_elf_check_arch(interp_elf_ex) ||	     !interpreter->f_op->mmap) {		printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type);		return 0xffffffff;	}	/* Now read in all of the header information */	if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) {	    printk("IRIX interp header bigger than a page (%d)\n",		   (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum));	    return 0xffffffff;	}	elf_phdata =  (struct elf_phdr *) 		kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum,			GFP_KERNEL);	if(!elf_phdata) {          printk("Cannot kmalloc phdata for IRIX interp.\n");	  return 0xffffffff;	}	/* If the size of this structure has changed, then punt, since	 * we will be doing the wrong thing.	 */	if(interp_elf_ex->e_phentsize != 32) {		printk("IRIX interp e_phentsize == %d != 32 ",		       interp_elf_ex->e_phentsize);		kfree(elf_phdata);		return 0xffffffff;	}	retval = kernel_read(interpreter, interp_elf_ex->e_phoff,			   (char *) elf_phdata,			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);#ifdef DEBUG_ELF	dump_phdrs(elf_phdata, interp_elf_ex->e_phnum);#endif	eppnt = elf_phdata;	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {	  if(eppnt->p_type == PT_LOAD) {	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;	    int elf_prot = 0;	    unsigned long vaddr = 0;	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;	    elf_type |= MAP_FIXED;	    vaddr = eppnt->p_vaddr;#ifdef DEBUG_ELF	    printk("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",		   interpreter, vaddr,		   (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)),		   (unsigned long) elf_prot, (unsigned long) elf_type,		   (unsigned long) (eppnt->p_offset & 0xfffff000));#endif	    down(&current->mm->mmap_sem);	    error = do_mmap(interpreter, vaddr,			    eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),			    elf_prot, elf_type,			    eppnt->p_offset & 0xfffff000);	    up(&current->mm->mmap_sem);	    if(error < 0 && error > -1024) {		    printk("Aieee IRIX interp mmap error=%d\n", error);		    break;  /* Real error */	    }#ifdef DEBUG_ELF	    printk("error=%08lx ", (unsigned long) error);#endif	    if(!load_addr && interp_elf_ex->e_type == ET_DYN) {	      load_addr = error;#ifdef DEBUG_ELF              printk("load_addr = error ");#endif	    }	    /* Find the end of the file  mapping for this phdr, and keep	     * track of the largest address we see for this.	     */	    k = eppnt->p_vaddr + eppnt->p_filesz;	    if(k > elf_bss) elf_bss = k;	    /* Do the same thing for the memory mapping - between	     * elf_bss and last_bss is the bss section.	     */	    k = eppnt->p_memsz + eppnt->p_vaddr;	    if(k > last_bss) last_bss = k;#ifdef DEBUG_ELF	    printk("\n");#endif	  }	}	/* Now use mmap to map the library into memory. */	if(error < 0 && error > -1024) {#ifdef DEBUG_ELF		printk("got error %d\n", error);#endif		kfree(elf_phdata);		return 0xffffffff;	}	/* Now fill out the bss section.  First pad the last page up	 * to the page boundary, and then perform a mmap to make sure	 * that there are zero-mapped pages up to and including the	 * last bss page.	 */#ifdef DEBUG_ELF	printk("padzero(%08lx) ", (unsigned long) (elf_bss));#endif	padzero(elf_bss);	len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */#ifdef DEBUG_ELF	printk("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss,	       (unsigned long) len);#endif	/* Map the last of the bss segment */	if (last_bss > len) {		do_brk(len, (last_bss - len));	}	kfree(elf_phdata);	*interp_load_addr = load_addr;	return ((unsigned int) interp_elf_ex->e_entry);}/* Check sanity of IRIX elf executable header. */static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm){	if (memcmp(ehp->e_ident, ELFMAG, SELFMAG) != 0)		return -ENOEXEC;	/* First of all, some simple consistency checks */	if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) || 	    !irix_elf_check_arch(ehp) || !bprm->file->f_op->mmap) {		return -ENOEXEC;	}	/* Only support MIPS ARCH2 or greater IRIX binaries for now. */	if(!(ehp->e_flags & EF_MIPS_ARCH) && !(ehp->e_flags & 0x04)) {		return -ENOEXEC;	}	/* XXX Don't support N32 or 64bit binaries yet because they can	 * XXX and do execute 64 bit instructions and expect all registers	 * XXX to be 64 bit as well.  We need to make the kernel save	 * XXX all registers as 64bits on cpu's capable of this at	 * XXX exception time plus frob the XTLB exception vector.	 */	if((ehp->e_flags & 0x20)) {		return -ENOEXEC;	}	return 0; /* It's ok. */}#define IRIX_INTERP_PREFIX "/usr/gnemul/irix"/* Look for an IRIX ELF interpreter. */static inline int look_for_irix_interpreter(char **name,					    struct file **interpreter,					    struct elfhdr *interp_elf_ex,					    struct elf_phdr *epp,					    struct linux_binprm *bprm, int pnum){	int i;	int retval = -EINVAL;	struct file *file = NULL;

⌨️ 快捷键说明

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