linux-cvs-patches
[Top] [All Lists]

CVS Update@linux-mips.org: linux

To: linux-cvs-patches@linux-mips.org
Subject: CVS Update@linux-mips.org: linux
From: sjhill@linux-mips.org
Date: Sat, 19 Feb 2005 05:56:58 +0000
Reply-to: linux-mips@linux-mips.org
Sender: linux-cvs-patches-bounce@linux-mips.org
CVSROOT:        /home/cvs
Module name:    linux
Changes by:     sjhill@ftp.linux-mips.org       05/02/19 05:56:51

Modified files:
        arch/mips/kernel: irixelf.c sysirix.c 
        include/asm-mips: elf.h 

Log message:
        IRIX binaries are now detected with 100% accuracy. IRIX syscalls are
        blowing up, but it's progress :).

diff -urN linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c
--- linux/arch/mips/kernel/irixelf.c    2005/01/30 19:10:05     1.63
+++ linux/arch/mips/kernel/irixelf.c    2005/02/19 05:56:51     1.64
@@ -8,7 +8,7 @@
  *
  * Copyright (C) 1993 - 1994 Eric Youngdale <ericy@cais.com>
  * Copyright (C) 1996 - 2004 David S. Miller <dm@engr.sgi.com>
- * Copyright (C) 2004 Steven J. Hill <sjhill@realitydiluted.com>
+ * Copyright (C) 2004 - 2005 Steven J. Hill <sjhill@realitydiluted.com>
  */
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -255,7 +255,6 @@
        /* 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;
@@ -396,7 +395,7 @@
 
        /* 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) {
+           !bprm->file->f_op->mmap) {
                return -ENOEXEC;
        }
 
@@ -411,62 +410,59 @@
         * 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)) {
+       if((ehp->e_flags & EF_MIPS_ABI2)) {
                return -ENOEXEC;
        }
 
        return 0; /* It's ok. */
 }
 
+/*
+ * This is where the detailed check is performed. Irix binaries
+ * use interpreters with 'libc.so' in the name, so this function
+ * can differentiate between Linux and Irix binaries.
+ */
 #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)
+                                           struct elf_phdr *ihdr,
+                                           struct linux_binprm *bprm)
 {
-       int i;
        int retval = -EINVAL;
        struct file *file = NULL;
 
-       *name = NULL;
-       for(i = 0; i < pnum; i++, epp++) {
-               if (epp->p_type != PT_INTERP)
-                       continue;
+       *name = kmalloc((ihdr->p_filesz + strlen(IRIX_INTERP_PREFIX)),
+                       GFP_KERNEL);
+       if (!*name)
+               return -ENOMEM;
 
-               /* It is illegal to have two interpreters for one executable. */
-               if (*name != NULL)
-                       goto out;
-
-               *name = kmalloc((epp->p_filesz + strlen(IRIX_INTERP_PREFIX)),
-                               GFP_KERNEL);
-               if (!*name)
-                       return -ENOMEM;
-
-               strcpy(*name, IRIX_INTERP_PREFIX);
-               retval = kernel_read(bprm->file, epp->p_offset, (*name + 16),
-                                    epp->p_filesz);
-               if (retval < 0)
-                       goto out;
-
-               file = open_exec(*name);
-               if (IS_ERR(file)) {
-                       retval = PTR_ERR(file);
-                       goto out;
-               }
-               retval = kernel_read(file, 0, bprm->buf, 128);
-               if (retval < 0)
-                       goto dput_and_out;
+       strcpy(*name, IRIX_INTERP_PREFIX);
+       retval = kernel_read(bprm->file, ihdr->p_offset, (*name + 16),
+                            ihdr->p_filesz);
+       if (retval < 0)
+               goto out;
 
-               *interp_elf_ex = *(struct elfhdr *) bprm->buf;
+       file = open_exec(*name);
+       if (IS_ERR(file)) {
+               retval = PTR_ERR(file);
+               goto out;
        }
+
+       retval = kernel_read(file, 0, bprm->buf, 128);
+       if (retval < 0)
+               goto dput_and_out;
+
+       *interp_elf_ex = *(struct elfhdr *) bprm->buf;
+
        *interpreter = file;
+
        return 0;
 
 dput_and_out:
        fput(file);
+
 out:
        kfree(*name);
        return retval;
@@ -657,12 +653,18 @@
        end_code = 0;
        end_data = 0;
 
-       retval = look_for_irix_interpreter(&elf_interpreter,
-                                          &interpreter,
-                                          &interp_elf_ex, elf_phdata, bprm,
-                                          elf_ex.e_phnum);
-       if (retval)
+       /*
+        * If we get a return value, we change the value to be ENOEXEC
+        * so that we can exit gracefully and the main binary format
+        * search loop in 'fs/exec.c' will move onto the next handler
+        * which should be the normal ELF binary handler.
+        */
+       retval = look_for_irix_interpreter(&elf_interpreter, &interpreter,
+                                          &interp_elf_ex, elf_ihdr, bprm);
+       if (retval) {
+               retval = -ENOEXEC;
                goto out_free_file;
+       }
 
        if (elf_interpreter) {
                retval = verify_irix_interpreter(&interp_elf_ex);
@@ -813,9 +815,16 @@
 
        /* First of all, some simple consistency checks. */
        if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
-          !irix_elf_check_arch(&elf_ex) || !file->f_op->mmap)
+          !file->f_op->mmap)
                return -ENOEXEC;
 
+       /*
+        * FIXME: We need to check the SGI_ONLY flag if possible,
+        *        for now we will issue a warning when this occurs
+        *        which should be investigated further.
+        */
+       printk("%s: Check SGI_ONLY flag in this library!\n", __FUNCTION__);
+
        /* Now read in all of the header information. */
        if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
                return -ENOEXEC;
@@ -1302,9 +1311,18 @@
 {
        int init_inventory(void);
        extern asmlinkage unsigned long sys_call_table;
+       extern asmlinkage unsigned long sys_call_table_irix5;
 
        init_inventory();
 
+       /*
+        * Copy the IRIX5 syscall table (8000 bytes) into the main syscall
+        * table. The IRIX5 calls are located by an offset of 8000 bytes
+        * from the beginning of the main table.
+        */
+       memcpy((void *) ((unsigned long) &sys_call_table + 8000),
+               &sys_call_table_irix5, 8000);
+
        return register_binfmt(&irix_format);
 }
 
diff -urN linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- linux/arch/mips/kernel/sysirix.c    2005/01/01 00:33:55     1.67
+++ linux/arch/mips/kernel/sysirix.c    2005/02/19 05:56:51     1.68
@@ -469,6 +469,7 @@
                int *pageno = (int *) (regs->regs[base + 6]);
                struct mm_struct *mm = current->mm;
                pgd_t *pgdp;
+               pud_t *pudp;
                pmd_t *pmdp;
                pte_t *ptep;
 
@@ -478,7 +479,8 @@
 
                down_read(&mm->mmap_sem);
                pgdp = pgd_offset(mm, addr);
-               pmdp = pmd_offset(pgdp, addr);
+               pudp = pud_offset(pgdp, addr);
+               pmdp = pmd_offset(pudp, addr);
                ptep = pte_offset(pmdp, addr);
                retval = -EINVAL;
                if (ptep) {
diff -urN linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h
--- linux/include/asm-mips/elf.h        2005/01/26 02:21:06     1.24
+++ linux/include/asm-mips/elf.h        2005/02/19 05:56:51     1.25
@@ -234,9 +234,6 @@
 
 #endif /* __KERNEL__ */
 
-/* This one accepts IRIX binaries.  */
-#define irix_elf_check_arch(hdr)       ((hdr)->e_flags & RHF_SGI_ONLY)
-
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE      PAGE_SIZE
 

<Prev in Thread] Current Thread [Next in Thread>