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

📄 binfmt_coff.c

📁 linux1.1源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * These are the functions used to load COFF IBSC style executables. * Information on COFF format may be obtained in either the Intel Binary * Compatibility Specification 2 or O'Rilley's book on COFF. The shared * libraries are defined only the in the Intel book. * * This file is based upon code written by Eric Youndale for the ELF object * file format. * * Author: Al Longyear (longyear@sii.com) * * Latest Revision: *    3 Feburary 1994 *      Al Longyear (longyear@sii.com) *      Cleared first page of bss section using put_fs_byte. */#include <linux/fs.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/a.out.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/binfmts.h>#include <asm/segment.h>#include <linux/string.h>#include <linux/fcntl.h>#include <linux/ptrace.h>#include <linux/coff.h>#include <linux/malloc.h>asmlinkage int sys_exit (int exit_code);asmlinkage int sys_close (unsigned fd);asmlinkage int sys_open (const char *, int, int);asmlinkage int sys_uselib(const char * library);static int preload_library (struct linux_binprm *exe_bprm,			    COFF_SCNHDR * sect,			    struct file *fp);static int load_object (struct linux_binprm *bprm,			struct pt_regs *regs,			int lib_ok);/* *  Small procedure to test for the proper file alignment. */static inline intis_properly_aligned (COFF_SCNHDR *sect){    long scnptr = COFF_LONG (sect->s_scnptr);    long vaddr  = COFF_LONG (sect->s_vaddr);/* *  Print the section information if needed */#ifdef COFF_DEBUG    printk ("%s, scnptr = %d, vaddr = %d\n",	    sect->s_name,	    scnptr, vaddr);#endif/* *  Return the error code if the section is not properly aligned. */#ifdef COFF_DEBUG    if (((vaddr - scnptr) & ~PAGE_MASK) != 0)	printk ("bad alignment in %s\n", sect->s_name);#endif    return ((((vaddr - scnptr) & ~PAGE_MASK) != 0) ? -ENOEXEC : 0);}/* *    Clear the bytes in the last page of data. */staticint clear_memory (unsigned long addr, unsigned long size){    int status;    size = (PAGE_SIZE - (addr & ~PAGE_MASK)) & ~PAGE_MASK;    if (size == 0)        status = 0;    else {      #ifdef COFF_DEBUG        printk ("un-initialized storage in last page %d\n", size);#endif	status = verify_area (VERIFY_WRITE,			      (void *) addr, size);#ifdef COFF_DEBUG	printk ("result from verify_area = %d\n", status);#endif	if (status >= 0)	    while (size-- != 0)	        put_fs_byte (0, addr++);    }    return status;}/* *  Helper function to process the load operation. */static intload_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok){    COFF_FILHDR  *coff_hdr = (COFF_FILHDR *) bprm->buf;	/* COFF Header */    COFF_SCNHDR  *sect_bufr;	/* Pointer to section table            */    COFF_SCNHDR  *text_sect;	/* Pointer to the text section         */    COFF_SCNHDR  *data_sect;	/* Pointer to the data section         */    COFF_SCNHDR  *bss_sect;	/* Pointer to the bss section          */    int text_count;		/* Number of text sections             */    int data_count;		/* Number of data sections             */    int bss_count;		/* Number of bss sections              */    int lib_count;		/* Number of lib sections              */    unsigned int start_addr = 0;/* Starting location for program       */    int status = 0;		/* Result status register              */    int fd = -1;		/* Open file descriptor                */    struct file *fp     = NULL;	/* Pointer to the file at "fd"         */    short int sections  = 0;	/* Number of sections in the file      */    short int aout_size = 0;	/* Size of the a.out header area       */    short int flags;		/* Flag bits from the COFF header      */#ifdef COFF_DEBUG    printk ("binfmt_coff entry: %s\n", bprm->filename);#endif/* *  Validate the magic value for the object file. */    do {	if (COFF_I386BADMAG (*coff_hdr)) {#ifdef COFF_DEBUG	    printk ("bad filehdr magic\n");#endif	    status = -ENOEXEC;	    break;	}/* *  The object file should have 32 BIT little endian format. Do not allow *  it to have the 16 bit object file flag set as Linux is not able to run *  on the 80286/80186/8086. */	flags = COFF_SHORT (coff_hdr->f_flags);	if ((flags & (COFF_F_AR32WR | COFF_F_AR16WR)) != COFF_F_AR32WR) {#ifdef COFF_DEBUG	    printk ("invalid f_flags bits\n");#endif	    status = -ENOEXEC;	    break;	}/* *  Extract the header information which we need. */	sections  = COFF_SHORT (coff_hdr->f_nscns);   /* Number of sections */	aout_size = COFF_SHORT (coff_hdr->f_opthdr);  /* Size of opt. headr *//* *  If the file is not executable then reject the exectution. This means *  that there must not be external references. */	if ((flags & COFF_F_EXEC) == 0) {#ifdef COFF_DEBUG	    printk ("not executable bit\n");#endif	    status = -ENOEXEC;	    break;	}/* *  There must be atleast one section. */	if (sections == 0) {#ifdef COFF_DEBUG	    printk ("no sections\n");#endif	    status = -ENOEXEC;	    break;	}/* *  Do some additional consistency checks. *  The system requires mapping for this loader. If you try *  to use a file system with no mapping, the format is not valid. */	if (!bprm->inode->i_op ||	    !bprm->inode->i_op->default_file_ops->mmap) {#ifdef COFF_DEBUG	    printk ("no mmap in fs\n");#endif	    status = -ENOEXEC;	}    }    while (0);/* *  Allocate a buffer to hold the entire coff section list. */    if (status >= 0) {	int nbytes = sections * COFF_SCNHSZ;	sect_bufr = (COFF_SCNHDR *) kmalloc (nbytes, GFP_KERNEL);	if (0 == sect_bufr) {#ifdef COFF_DEBUG	    printk ("kmalloc failed\n");#endif	    status = -ENOEXEC;	}/* *  Read the section list from the disk file. */	else {	     int old_fs = get_fs ();	     set_fs (get_ds ());  /* Make it point to the proper location    */	     status = read_exec (bprm->inode,	     /* INODE for file       */			    aout_size + COFF_FILHSZ, /* Offset in the file   */			    (char *) sect_bufr,      /* Buffer for read      */			    nbytes);                 /* Byte count reqd.     */	     set_fs (old_fs);	                     /* Restore the selector */#ifdef COFF_DEBUG	     if (status < 0)	        printk ("read aout hdr, status = %d\n", status);#endif	 }    }    else	sect_bufr = NULL;	/* Errors do not have a section buffer *//* *  Count the number of sections for the required types and store the location *  of the last section for the three primary types. */    text_count = 0;    data_count = 0;    bss_count  = 0;    lib_count  = 0;    text_sect = NULL;    data_sect = NULL;    bss_sect  = NULL;/* *  Loop through the sections and find the various types */    if (status >= 0) {	int nIndex;	COFF_SCNHDR *sect_ptr = sect_bufr;	for (nIndex = 0; nIndex < sections; ++nIndex) {	    long int sect_flags = COFF_LONG (sect_ptr->s_flags);	    switch (sect_flags) {	    case COFF_STYP_TEXT:		text_sect = sect_ptr;		++text_count;		status = is_properly_aligned (sect_ptr);		break;	    case COFF_STYP_DATA:		data_sect = sect_ptr;		++data_count;		status = is_properly_aligned (sect_ptr);		break;	    case COFF_STYP_BSS:		bss_sect = sect_ptr;		++bss_count;		break;	    case COFF_STYP_LIB:#ifdef COFF_DEBUG		printk (".lib section found\n");#endif		++lib_count;		break;	    default:		break;	    }	    sect_ptr = (COFF_SCNHDR *) & ((char *) sect_ptr)[COFF_SCNHSZ];	}/* *  Ensure that there are the required sections. There must be one text *  sections and one each of the data and bss sections for an executable. *  A library may or may not have a data / bss section. */	if (text_count != 1) {	    status = -ENOEXEC;#ifdef COFF_DEBUG	    printk ("no text sections\n");#endif	}	else {	    if (lib_ok) {		if (data_count != 1 || bss_count != 1) {		    status = -ENOEXEC;#ifdef COFF_DEBUG		    printk ("no .data nor .bss sections\n");#endif		}	    }	}    }/* *  If there is no additional header then assume the file starts at *  the first byte of the text section. This may not be the proper place, *  so the best solution is to include the optional header. A shared library *  __MUST__ have an optional header to indicate that it is a shared library. */    if (status >= 0) {	if (aout_size == 0) {	    if (!lib_ok) {		status = -ENOEXEC;#ifdef COFF_DEBUG		printk ("no header in library\n");#endif	    }	    start_addr = COFF_LONG (text_sect->s_vaddr);	}/* *  There is some header. Ensure that it is sufficient. */	else {	    if (aout_size < COFF_AOUTSZ) {		status = -ENOEXEC;#ifdef COFF_DEBUG		printk ("header too small\n");#endif	    }	    else {		COFF_AOUTHDR *aout_hdr =	/* Pointer to a.out header */		(COFF_AOUTHDR *) & ((char *) coff_hdr)[COFF_FILHSZ];		short int aout_magic = COFF_SHORT (aout_hdr->magic); /* id *//* *  Validate the magic number in the a.out header. If it is valid then *  update the starting symbol location. Do not accept these file formats *  when loading a shared library. */		switch (aout_magic) {		case COFF_OMAGIC:		case COFF_ZMAGIC:		case COFF_STMAGIC:		    if (!lib_ok) {			status = -ENOEXEC;#ifdef COFF_DEBUG			printk ("wrong a.out header magic\n");#endif		    }		    start_addr = (unsigned int) COFF_LONG (aout_hdr->entry);		    break;/* *  Magic value for a shared library. This is valid only when loading a *  shared library. (There is no need for a start_addr. It won't be used.) */		case COFF_SHMAGIC:		    if (lib_ok) {#ifdef COFF_DEBUG			printk ("wrong a.out header magic\n");#endif			status = -ENOEXEC;		    }		    break;		default:#ifdef COFF_DEBUG		    printk ("wrong a.out header magic\n");#endif		    status = -ENOEXEC;		    break;		}	    }	}    }/* *  Fetch a file pointer to the executable. */    if (status >= 0) {	fd = open_inode (bprm->inode, O_RDONLY);	if (fd < 0) {#ifdef COFF_DEBUG	    printk ("can not open inode, result = %d\n", fd);#endif	    status = fd;	}	else	    fp = current->filp[fd];    }    else	fd = -1;		/* Invalidate the open file descriptor *//* *  Generate the proper values for the text fields *

⌨️ 快捷键说明

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