Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys PE/COFF (Win32) compatible binary support (experimental).



details:   https://anonhg.NetBSD.org/src/rev/dbf9fd95405b
branches:  trunk
changeset: 487610:dbf9fd95405b
user:      oki <oki%NetBSD.org@localhost>
date:      Fri Jun 09 22:38:56 2000 +0000

description:
PE/COFF (Win32) compatible binary support (experimental).
It currentry supports only i386.

diffstat:

 sys/compat/pecoff/files.pecoff  |    4 +-
 sys/compat/pecoff/pecoff_exec.c |  573 ++++++++++++++++++++++++++++++++++++++++
 sys/compat/pecoff/pecoff_exec.h |  109 +++++++
 sys/compat/pecoff/pecoff_util.h |   87 ++++++
 sys/kern/exec_conf.c            |    4 +-
 5 files changed, 773 insertions(+), 4 deletions(-)

diffs (truncated from 809 to 300 lines):

diff -r 98f06d1e8d6f -r dbf9fd95405b sys/compat/pecoff/files.pecoff
--- a/sys/compat/pecoff/files.pecoff    Fri Jun 09 22:06:25 2000 +0000
+++ b/sys/compat/pecoff/files.pecoff    Fri Jun 09 22:38:56 2000 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.pecoff,v 1.1 2000/06/04 16:29:25 mycroft Exp $
+#      $NetBSD: files.pecoff,v 1.2 2000/06/09 22:38:56 oki Exp $
 #
 
-#file  compat/pecoff/pecoff_exec.c     compat_pecoff
+file   compat/pecoff/pecoff_exec.c     compat_pecoff
diff -r 98f06d1e8d6f -r dbf9fd95405b sys/compat/pecoff/pecoff_exec.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/compat/pecoff/pecoff_exec.c   Fri Jun 09 22:38:56 2000 +0000
@@ -0,0 +1,573 @@
+/*     $NetBSD: pecoff_exec.c,v 1.1 2000/06/09 22:38:56 oki Exp $      */
+
+/*
+ * Copyright (c) 2000 Masaru OKI
+ * Copyright (c) 1994, 1995, 1998 Scott Bartram
+ * Copyright (c) 1994 Adam Glass
+ * Copyright (c) 1993, 1994 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * originally from kern/exec_ecoff.c
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Masaru OKI.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*#define DEBUG_PECOFF*/
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/namei.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/exec.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
+#include <sys/resourcevar.h>
+#include <sys/stat.h>
+
+#include <vm/vm.h>
+
+#include <sys/exec_coff.h>
+#include <machine/coff_machdep.h>
+
+#include <compat/pecoff/pecoff_exec.h>
+#include <compat/pecoff/pecoff_util.h>
+
+void * pecoff_copyargs __P((struct exec_package *pack,
+                          struct ps_strings *arginfo,
+                          void *stack, void *argp));
+int pecoff_signature __P((struct proc *p, struct vnode *vp,
+                           struct pecoff_dos_filehdr *dp));
+int pecoff_load_file __P((struct proc *p, struct exec_package *epp,
+                        char *path, struct exec_vmcmd_set *vcset,
+                        u_long *entry, struct pecoff_args *argp));
+void pecoff_load_section __P((struct exec_vmcmd_set *vcset, struct vnode *vp,
+                            struct coff_scnhdr *sh, long *addr,
+                            u_long *size, int *prot));
+int exec_pecoff_makecmds __P((struct proc *p, struct exec_package *epp));
+int exec_pecoff_coff_makecmds __P((struct proc *p, struct exec_package *epp,
+                                 struct coff_filehdr *fp, int peofs));
+int exec_pecoff_setup_stack __P((struct proc *p, struct exec_package *epp));
+int exec_pecoff_prep_omagic __P((struct proc *p, struct exec_package *epp,
+                                    struct coff_filehdr *fp,
+                                    struct coff_aouthdr *ap, int peofs));
+int exec_pecoff_prep_nmagic __P((struct proc *p, struct exec_package *epp,
+                                    struct coff_filehdr *fp,
+                                    struct coff_aouthdr *ap, int peofs));
+int exec_pecoff_prep_zmagic __P((struct proc *p, struct exec_package *epp,
+                                    struct coff_filehdr *fp,
+                                    struct coff_aouthdr *ap, int peofs));
+int pecoff_read_from __P((struct proc *p, struct vnode *vp, int pos,
+                        caddr_t buf, int siz));
+
+
+const char pecoff_emul_path[] = "/emul/pecoff";
+extern char sigcode[], esigcode[];
+
+struct emul emul_pecoff = {
+       "pecoff",
+       0,
+       sendsig,
+       SYS_syscall,
+       SYS_MAXSYSCALL,
+       sysent,
+#ifdef SYSCALL_DEBUG
+       syscallnames,
+#else
+       0,
+#endif
+       howmany(sizeof(struct pecoff_args), sizeof(char *)),
+       pecoff_copyargs,
+       setregs,
+       sigcode,
+       esigcode,
+};
+
+
+void *
+pecoff_copyargs(pack, arginfo, stack, argp)
+       struct exec_package *pack;
+       struct ps_strings *arginfo;
+       void *stack;
+       void *argp;
+{
+       int len = sizeof(struct pecoff_args);
+       struct pecoff_imghdr *ap;
+
+       stack = copyargs(pack, arginfo, stack, argp);
+       if (!stack) {
+               return NULL;
+       }
+       ap = (struct pecoff_imghdr *)pack->ep_emul_arg;
+       if (copyout(ap, stack, len)) {
+               return NULL;
+       }
+#if 0 /*  kern_exec.c? */
+       free((char *)ap, M_TEMP);
+       pack->ep_emul_arg = 0;
+#endif
+
+       stack = (caddr_t)stack + len;
+       
+       return stack;
+}
+
+#define PECOFF_SIGNATURE "PE\0\0"
+static const char signature[] = PECOFF_SIGNATURE;
+
+/*
+ * Check PE signature.
+ */
+int
+pecoff_signature(p, vp, dp)
+       struct proc *p;
+       struct vnode *vp;
+       struct pecoff_dos_filehdr *dp;
+{
+       int error;
+       char buf[sizeof(signature) - 1];
+
+       if (DOS_BADMAG(dp)) {
+               return ENOEXEC;
+       }
+       error = pecoff_read_from(p, vp, dp->d_peofs, buf, sizeof(buf));
+       if (error) {
+               return error;
+       }
+       if (memcmp(buf, signature, sizeof(signature) - 1) == 0) {
+               return 0;
+       }
+       return EFTYPE;
+}
+
+/*
+ * load(mmap) file.  for dynamic linker (ld.so.dll)
+ */
+int
+pecoff_load_file(p, epp, path, vcset, entry, argp)
+       struct proc *p;
+       struct exec_package *epp;
+       char *path;
+       struct exec_vmcmd_set *vcset;
+       u_long *entry;
+       struct pecoff_args *argp;
+{
+       int error, peofs, scnsiz, i;
+       struct nameidata nd;
+       struct vnode *vp;
+       struct vattr attr;
+       struct pecoff_dos_filehdr dh;
+       struct coff_filehdr *fp = 0;
+       struct coff_aouthdr *ap;
+       struct pecoff_opthdr *wp;
+       struct coff_scnhdr *sh = 0;
+
+       NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
+       if ((error = namei(&nd)) != 0)
+               return error;
+       vp = nd.ni_vp;
+
+       /*
+        * Similarly, if it's not marked as executable, or it's not a regular
+        * file, we don't allow it to be used.
+        */
+       if (vp->v_type != VREG) {
+               error = EACCES;
+               goto badunlock;
+       }
+       if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0)
+               goto badunlock;
+
+       /* get attributes */
+       if ((error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) != 0)
+               goto badunlock;
+
+       /*
+        * Check mount point.  Though we're not trying to exec this binary,
+        * we will be executing code from it, so if the mount point
+        * disallows execution or set-id-ness, we punt or kill the set-id.
+        */
+       if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
+               error = EACCES;
+               goto badunlock;
+       }
+       if (vp->v_mount->mnt_flag & MNT_NOSUID)
+               epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
+
+       VOP_UNLOCK(vp, 0);
+       /*
+        * Read header.
+        */
+       error = pecoff_read_from(p, vp, 0, (caddr_t)&dh, sizeof(dh));
+       if (error != 0)
+               goto bad;
+       if ((error = pecoff_signature(p, vp, &dh)) != 0)
+               goto bad;
+       fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
+       peofs = dh.d_peofs + sizeof(signature) - 1;
+       if ((error = pecoff_read_from(p, vp, peofs, (caddr_t)fp,
+                                    PECOFF_HDR_SIZE)) != 0)
+               goto bad;
+       if (COFF_BADMAG(fp)) {
+               error = ENOEXEC;
+               goto bad;
+       }
+       ap = (void *)((char *)fp + sizeof(struct coff_filehdr));
+       wp = (void *)((char *)ap + sizeof(struct coff_aouthdr));
+       /* read section header */
+       scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
+       sh = malloc(scnsiz, M_TEMP, M_WAITOK);
+       if ((error = pecoff_read_from(p, vp, peofs + PECOFF_HDR_SIZE,
+                                    (caddr_t)sh, scnsiz)) != 0)
+               goto bad;
+
+       /*
+        * Read section header, and mmap.
+        */
+       for (i = 0; i < fp->f_nscns; i++) {
+               int prot = 0;
+               long addr, size;
+
+               if (sh[i].s_flags & COFF_STYP_DISCARD)
+                       continue;
+               /* XXX ? */
+               if ((sh[i].s_flags & COFF_STYP_TEXT) &&
+                   (sh[i].s_flags & COFF_STYP_EXEC) == 0)
+                       continue;
+               if ((sh[i].s_flags & (COFF_STYP_TEXT|
+                                     COFF_STYP_DATA|COFF_STYP_BSS)) == 0)
+                       continue;
+               sh[i].s_vaddr += wp->w_base; /* RVA --> VA */
+               pecoff_load_section(vcset, vp, &sh[i], &addr, &size, &prot);
+       }
+       *entry = wp->w_base + ap->a_entry;
+       argp->a_ldbase = wp->w_base;
+       argp->a_ldexport = wp->w_imghdr[0].i_vaddr + wp->w_base;
+
+       free((char *)fp, M_TEMP);
+       free((char *)sh, M_TEMP);
+       vrele(vp);
+       return 0;
+
+badunlock:
+       VOP_UNLOCK(vp, 0);
+
+bad:
+       if (fp != 0)
+               free((char *)fp, M_TEMP);
+       if (sh != 0)
+               free((char *)sh, M_TEMP);
+       vrele(vp);
+       return error;
+}



Home | Main Index | Thread Index | Old Index