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