summaryrefslogtreecommitdiffstats
path: root/sys/compat/pecoff
diff options
context:
space:
mode:
authortakawata <takawata@FreeBSD.org>2000-12-20 12:51:08 +0000
committertakawata <takawata@FreeBSD.org>2000-12-20 12:51:08 +0000
commit966ad05f240b3e81b46861cef44e820d5f5c3ad7 (patch)
tree846fc606d51aa99910dd26e00f7e010f7caf967c /sys/compat/pecoff
parenta0117ce2f8cb6e610a33849619582df3d03b3b77 (diff)
downloadFreeBSD-src-966ad05f240b3e81b46861cef44e820d5f5c3ad7.zip
FreeBSD-src-966ad05f240b3e81b46861cef44e820d5f5c3ad7.tar.gz
Add PECOFF (WIN32 Execution file format) support.
To use it, some dll is needed. And currently, the dll is only for NetBSD. So one more kernel module is needed. For more infomation, http://chiharu.haun.org/peace/ . Reviewed by: bp
Diffstat (limited to 'sys/compat/pecoff')
-rw-r--r--sys/compat/pecoff/imgact_pecoff.c641
-rw-r--r--sys/compat/pecoff/imgact_pecoff.h142
2 files changed, 783 insertions, 0 deletions
diff --git a/sys/compat/pecoff/imgact_pecoff.c b/sys/compat/pecoff/imgact_pecoff.c
new file mode 100644
index 0000000..b7fcd9b
--- /dev/null
+++ b/sys/compat/pecoff/imgact_pecoff.c
@@ -0,0 +1,641 @@
+/* $NetBSD$ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2000 Masaru OKI
+ * Copyright (c) 1994, 1995, 1998 Scott Bartram
+ * Copyright (c) 1994 Adam Glass
+ * Copyright (c) 1993, 1994 Christopher G. Demetriou
+ *
+ * originally from NetBSD kern/exec_ecoff.c
+ *
+ * Copyright (c) 2000 Takanori Watanabe
+ * Copyright (c) 2000 KUROSAWA Takahiro
+ * Copyright (c) 1995-1996 Sen Schmidt
+ * Copyright (c) 1996 Peter Wemm
+ * All rights reserved.
+ *
+ * originally from FreeBSD kern/imgact_elf.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.
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/sysent.h>
+#include <sys/imgact.h>
+#include <sys/signalvar.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/vnode.h>
+#include <sys/namei.h>
+
+#include <machine/reg.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <sys/lock.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_zone.h>
+
+#include <sys/user.h>
+#include <sys/exec.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/cpu.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <machine/md_var.h>
+#include <machine/pecoff_machdep.h>
+#include <compat/pecoff/imgact_pecoff.h>
+
+#include "opt_pecoff.h"
+
+#define PECOFF_PE_SIGNATURE "PE\0\0"
+static int pecoff_fixup(register_t **, struct image_params *);
+static int
+pecoff_coredump(register struct proc *, register struct vnode *,
+ off_t);
+#ifndef PECOFF_DEBUG
+#define DPRINTF(a)
+#else
+#define DPRINTF(a) printf a
+#endif
+static struct sysentvec pecoff_sysvec = {
+ SYS_MAXSYSCALL,
+ sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ pecoff_fixup,
+ sendsig,
+ sigcode,
+ &szsigcode,
+ 0,
+ "FreeBSD PECoff",
+ pecoff_coredump,
+ NULL,
+ MINSIGSTKSZ
+
+};
+
+static const char signature[] = PECOFF_PE_SIGNATURE;
+
+static int
+exec_pecoff_coff_prep_omagic(struct image_params *,
+ struct coff_filehdr *,
+ struct coff_aouthdr *, int peoffs);
+static int
+exec_pecoff_coff_prep_nmagic(struct image_params *,
+ struct coff_filehdr *,
+ struct coff_aouthdr *, int peoffs);
+static int
+exec_pecoff_coff_prep_zmagic(struct image_params *,
+ struct coff_filehdr *,
+ struct coff_aouthdr *, int peoffs);
+
+static int
+exec_pecoff_coff_makecmds(struct image_params *,
+ struct coff_filehdr *, int);
+
+static int pecoff_signature(struct proc *, struct vnode *, struct pecoff_dos_filehdr *);
+static int pecoff_read_from(struct proc *, struct vnode *, int, caddr_t, int);
+static int
+pecoff_load_section(struct proc * p,
+ struct vmspace * vmspace, struct vnode * vp,
+ vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
+ vm_prot_t prot);
+
+static int
+pecoff_fixup(register_t ** stack_base, struct image_params * imgp)
+{
+ int len = sizeof(struct pecoff_args);
+ struct pecoff_imghdr *ap;
+ register_t *pos;
+
+ pos = *stack_base + (imgp->argc + imgp->envc + 2);
+ ap = (struct pecoff_imghdr *) imgp->auxargs;
+ if (copyout(ap, pos, len)) {
+ return NULL;
+ }
+ free(ap, M_TEMP);
+ imgp->auxargs = NULL;
+ (*stack_base)--;
+ suword(*stack_base, (long) imgp->argc);
+ return 0;
+}
+
+
+static int
+pecoff_coredump(register struct proc * p, register struct vnode * vp,
+ off_t limit)
+{
+ register struct ucred *cred = p->p_ucred;
+ register struct vmspace *vm = p->p_vmspace;
+ int error;
+#ifdef PECOFF_DEBUG
+ struct vm_map *map;
+ struct vm_map_entry *ent;
+ struct reg regs;
+
+#endif
+ if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >= limit)
+ return (EFAULT);
+ fill_kinfo_proc(p, &p->p_addr->u_kproc);
+
+#if PECOFF_DEBUG
+ fill_regs(p, &regs);
+ printf("EIP%x\n", regs.r_eip);
+ printf("EAX%x EBX%x ECX%x EDI%x\n",
+ regs.r_eax, regs.r_ebx, regs.r_ecx, regs.r_edi);
+ map = &vm->vm_map;
+ ent = &map->header;
+ printf("%p %p %p\n", ent, ent->prev, ent->next);
+#endif
+ error = cpu_coredump(p, vp, cred);
+ if (error == 0)
+ error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr,
+ (int) ctob(vm->vm_dsize), (off_t) ctob(UPAGES), UIO_USERSPACE,
+ IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, p);
+ if (error == 0)
+ error = vn_rdwr(UIO_WRITE, vp,
+ (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)),
+ round_page(ctob(vm->vm_ssize)),
+ (off_t) ctob(UPAGES) + ctob(vm->vm_dsize), UIO_USERSPACE,
+ IO_NODELOCKED | IO_UNIT, cred, (int *) NULL, p);
+ return (error);
+
+}
+
+static int
+pecoff_load_section(struct proc * p, struct vmspace * vmspace, struct vnode * vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
+{
+ size_t map_len;
+ vm_offset_t map_addr;
+ int error, rv;
+ size_t copy_len;
+ size_t copy_map_len;
+ size_t copy_start;
+ vm_object_t object;
+ vm_offset_t copy_map_offset;
+ vm_offset_t file_addr;
+ vm_offset_t data_buf = 0;
+
+ object = vp->v_object;
+ error = 0;
+
+ map_addr = trunc_page((vm_offset_t) vmaddr);
+ file_addr = trunc_page(offset);
+ DPRINTF(("SECARG:%x %p %x %x\n", offset, vmaddr, memsz, filsz));
+ if (file_addr != offset) {
+ /*
+ * The section is not on page boundary. We can't use
+ * vm_map_insert(). Use copyin instead.
+ */
+ map_len = round_page(memsz);
+ copy_len = filsz;
+ copy_map_offset = file_addr;
+ copy_map_len = round_page(offset + filsz) - file_addr;
+ copy_start = offset - file_addr;
+
+ DPRINTF(("offset=%x vmaddr=%x filsz=%x memsz=%x\n",
+ offset, vmaddr, filsz, memsz));
+ DPRINTF(("map_len=%x copy_len=%x copy_map_offset=%x"
+ " copy_map_len=%x copy_start=%x\n",
+ map_len, copy_len, copy_map_offset,
+ copy_map_len, copy_start));
+ } else {
+
+ map_len = trunc_page(filsz);
+
+ if (map_len != 0) {
+ vm_object_reference(object);
+ vm_map_lock(&vmspace->vm_map);
+ rv = vm_map_insert(&vmspace->vm_map,
+ object,
+ file_addr, /* file offset */
+ map_addr, /* virtual start */
+ map_addr + map_len, /* virtual end */
+ prot,
+ VM_PROT_ALL,
+ MAP_COPY_ON_WRITE | MAP_PREFAULT);
+
+ vm_map_unlock(&vmspace->vm_map);
+ if (rv != KERN_SUCCESS) {
+ vm_object_deallocate(object);
+ return EINVAL;
+ }
+ /* we can stop now if we've covered it all */
+ if (memsz == filsz)
+ return 0;
+
+ }
+ copy_map_offset = trunc_page(offset + filsz);
+ copy_map_len = PAGE_SIZE;
+ copy_start = 0;
+ copy_len = (offset + filsz) - trunc_page(offset + filsz);
+ map_addr = trunc_page((vm_offset_t) vmaddr + filsz);
+ map_len = round_page((vm_offset_t) vmaddr + memsz) - map_addr;
+
+ }
+
+ if (map_len != 0) {
+ vm_map_lock(&vmspace->vm_map);
+ rv = vm_map_insert(&vmspace->vm_map, NULL, 0,
+ map_addr, map_addr + map_len,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ vm_map_unlock(&vmspace->vm_map);
+ DPRINTF(("EMP-rv:%d,%x %x\n", rv, map_addr, map_addr + map_len));
+ if (rv != KERN_SUCCESS) {
+ return EINVAL;
+ }
+ }
+ DPRINTF(("COPYARG %x %x\n", map_addr, copy_len));
+ if (copy_len != 0) {
+ vm_object_reference(object);
+ rv = vm_map_find(exec_map,
+ object,
+ copy_map_offset,
+ &data_buf,
+ copy_map_len,
+ TRUE,
+ VM_PROT_READ,
+ VM_PROT_ALL,
+ MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL);
+ if (rv != KERN_SUCCESS) {
+ vm_object_deallocate(object);
+ return EINVAL;
+ }
+ /* send the page fragment to user space */
+
+ error = copyout((caddr_t) data_buf + copy_start,
+ (caddr_t) map_addr, copy_len);
+ vm_map_remove(exec_map, data_buf, data_buf + copy_map_len);
+ DPRINTF(("%d\n", error));
+ if (error)
+ return (error);
+ }
+ /*
+ * set it to the specified protection
+ */
+ vm_map_protect(&vmspace->vm_map, map_addr,
+ map_addr + map_len, prot,
+ FALSE);
+ return error;
+
+}
+static int
+pecoff_load_file(struct proc * p, const char *file, u_long * addr, u_long * entry, u_long * ldexport)
+{
+
+ struct nameidata nd;
+ struct pecoff_dos_filehdr dh;
+ struct coff_filehdr *fp = 0;
+ struct coff_aouthdr *ap;
+ struct pecoff_opthdr *wp;
+ struct coff_scnhdr *sh = 0;
+ struct vmspace *vmspace = p->p_vmspace;
+ struct vattr attr;
+ struct image_params image_params, *imgp;
+ int peofs;
+ int error, i, scnsiz;
+
+ imgp = &image_params;
+ /*
+ * Initialize part of the common data
+ */
+ imgp->proc = p;
+ imgp->uap = NULL;
+ imgp->attr = &attr;
+ imgp->firstpage = NULL;
+
+ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, p);
+
+ if ((error = namei(&nd)) != 0) {
+ nd.ni_vp = NULL;
+ goto fail;
+ }
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ imgp->vp = nd.ni_vp;
+
+ /*
+ * Check permissions, modes, uid, etc on the file, and "open" it.
+ */
+ error = exec_check_permissions(imgp);
+ if (error) {
+ VOP_UNLOCK(nd.ni_vp, 0, p);
+ goto fail;
+ }
+ VOP_UNLOCK(nd.ni_vp, 0, p);
+ if (error)
+ goto fail;
+ if ((error = pecoff_read_from(p, imgp->vp, 0, (caddr_t) & dh, sizeof(dh))) != 0)
+ goto fail;
+ if ((error = pecoff_signature(p, imgp->vp, &dh) != 0))
+ goto fail;
+ fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
+ peofs = dh.d_peofs + sizeof(signature) - 1;
+ if ((error = pecoff_read_from(p, imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE) != 0))
+ goto fail;
+ if (COFF_BADMAG(fp)) {
+ error = ENOEXEC;
+ goto fail;
+ }
+ 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, imgp->vp, peofs + PECOFF_HDR_SIZE,
+ (caddr_t) sh, scnsiz)) != 0)
+ goto fail;
+
+ /*
+ * Read Section infomation and map sections.
+ */
+
+ for (i = 0; i < fp->f_nscns; i++) {
+ int prot = 0;
+
+ 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;
+
+ prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
+ prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
+ prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
+
+ sh[i].s_vaddr += wp->w_base; /* RVA --> VA */
+ if ((error = pecoff_load_section(p, vmspace, imgp->vp, sh[i].s_scnptr
+ ,(caddr_t) sh[i].s_vaddr,
+ sh[i].s_paddr, sh[i].s_size
+ ,prot)) != 0)
+ goto fail;
+
+ }
+ *entry = wp->w_base + ap->a_entry;
+ *addr = wp->w_base;
+ *ldexport = wp->w_imghdr[0].i_vaddr + wp->w_base;
+fail:
+ if (fp)
+ free(fp, M_TEMP);
+ if (sh)
+ free(sh, M_TEMP);
+ if (nd.ni_vp)
+ vrele(nd.ni_vp);
+
+ return error;
+}
+static int
+exec_pecoff_coff_prep_omagic(struct image_params * imgp,
+ struct coff_filehdr * fp,
+ struct coff_aouthdr * ap, int peofs)
+{
+ return ENOEXEC;
+}
+static int
+exec_pecoff_coff_prep_nmagic(struct image_params * imgp,
+ struct coff_filehdr * fp,
+ struct coff_aouthdr * ap, int peofs)
+{
+ return ENOEXEC;
+}
+static int
+exec_pecoff_coff_prep_zmagic(struct image_params * imgp,
+ struct coff_filehdr * fp,
+ struct coff_aouthdr * ap, int peofs)
+{
+ int scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
+ int error = ENOEXEC, i;
+ int prot;
+ u_long text_size = 0, data_size = 0, dsize;
+ u_long text_addr = 0, data_addr = VM_MAXUSER_ADDRESS;
+ u_long ldexport, ldbase;
+ struct pecoff_opthdr *wp;
+ struct coff_scnhdr *sh;
+ struct vmspace *vmspace;
+ struct pecoff_args *argp = NULL;
+
+ sh = malloc(scnsiz, M_TEMP, M_WAITOK);
+
+ wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
+ error = pecoff_read_from(imgp->proc, imgp->vp, peofs + PECOFF_HDR_SIZE,
+ (caddr_t) sh, scnsiz);
+ if ((error = exec_extract_strings(imgp)) != 0)
+ goto fail;
+ exec_new_vmspace(imgp);
+ vmspace = imgp->proc->p_vmspace;
+ for (i = 0; i < fp->f_nscns; i++) {
+ prot = VM_PROT_WRITE; /* XXX for relocation? */
+ prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
+ prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
+ prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
+ sh[i].s_vaddr += wp->w_base;
+ if (sh[i].s_flags & COFF_STYP_DISCARD)
+ continue;
+ if ((sh[i].s_flags & COFF_STYP_TEXT) != 0) {
+
+ error = pecoff_load_section(imgp->proc, vmspace,
+ imgp->vp, sh[i].s_scnptr
+ ,(caddr_t) sh[i].s_vaddr, sh[i].s_paddr, sh[i].s_size
+ ,prot);
+ DPRINTF(("ERROR%d\n", error));
+ if (error)
+ goto fail;
+ text_addr = trunc_page(sh[i].s_vaddr);
+ text_size = trunc_page(sh[i].s_size + sh[i].s_vaddr - text_addr);
+
+ }
+ if ((sh[i].s_flags & COFF_STYP_DATA) != 0) {
+ if (pecoff_load_section(imgp->proc,
+ vmspace, imgp->vp, sh[i].s_scnptr
+ ,(caddr_t) sh[i].s_vaddr, sh[i].s_paddr, sh[i].s_size,
+ prot) != 0)
+ goto fail;
+ data_addr = min(trunc_page(sh[i].s_vaddr), data_addr);
+ dsize = round_page(sh[i].s_vaddr + sh[i].s_paddr)
+ - data_addr;
+ data_size = max(dsize, data_size);
+
+ }
+ }
+ vmspace->vm_tsize = text_size >> PAGE_SHIFT;
+ vmspace->vm_taddr = (caddr_t) (uintptr_t) text_addr;
+ vmspace->vm_dsize = data_size >> PAGE_SHIFT;
+ vmspace->vm_daddr = (caddr_t) (uintptr_t) data_addr;
+ argp = malloc(sizeof(struct pecoff_args), M_TEMP, M_WAITOK);
+ if (argp == NULL) {
+ error = ENOMEM;
+ goto fail;
+ }
+ argp->a_base = wp->w_base;
+ argp->a_entry = wp->w_base + ap->a_entry;
+ argp->a_end = data_addr + data_size;
+ argp->a_subsystem = wp->w_subvers;
+ error = pecoff_load_file(imgp->proc, "/usr/libexec/ld.so.dll", &ldbase, &imgp->entry_addr, &ldexport);
+ if (error)
+ goto fail;
+
+ argp->a_ldbase = ldbase;
+ argp->a_ldexport = ldexport;
+ memcpy(argp->a_imghdr, wp->w_imghdr, sizeof(struct pecoff_imghdr) * 16);
+ for (i = 0; i < 16; i++) {
+ argp->a_imghdr[i].i_vaddr += wp->w_base;
+ }
+ imgp->proc->p_sysent = &pecoff_sysvec;
+ if (error)
+ goto fail;
+ imgp->auxargs = argp;
+ imgp->auxarg_size = sizeof(struct pecoff_args);
+ imgp->interpreted = 0;
+
+ imgp->vp->v_flag |= VTEXT;
+ if (sh != NULL)
+ free(sh, M_TEMP);
+ return 0;
+fail:
+ error = (error) ? error : ENOEXEC;
+ if (sh != NULL)
+ free(sh, M_TEMP);
+ if (argp != NULL)
+ free(argp, M_TEMP);
+
+ return error;
+}
+
+int
+exec_pecoff_coff_makecmds(struct image_params * imgp,
+ struct coff_filehdr * fp, int peofs)
+{
+ struct coff_aouthdr *ap;
+ int error;
+
+ if (COFF_BADMAG(fp)) {
+ return ENOEXEC;
+ }
+ ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
+ switch (ap->a_magic) {
+ case COFF_OMAGIC:
+ error = exec_pecoff_coff_prep_omagic(imgp, fp, ap, peofs);
+ break;
+ case COFF_NMAGIC:
+ error = exec_pecoff_coff_prep_nmagic(imgp, fp, ap, peofs);
+ break;
+ case COFF_ZMAGIC:
+ error = exec_pecoff_coff_prep_zmagic(imgp, fp, ap, peofs);
+ break;
+ default:
+ return ENOEXEC;
+ }
+
+ return error;
+}
+
+static int
+pecoff_signature(p, vp, dp)
+ struct proc *p;
+ struct vnode *vp;
+ struct pecoff_dos_filehdr *dp;
+{
+ int error;
+ char buf[512];
+ char *pesig;
+ if (DOS_BADMAG(dp)) {
+ return ENOEXEC;
+ }
+ error = pecoff_read_from(p, vp, dp->d_peofs, buf, sizeof(buf));
+ if (error) {
+ return error;
+ }
+ pesig = buf;
+ if (memcmp(pesig, signature, sizeof(signature) - 1) == 0) {
+ return 0;
+ }
+ return EFTYPE;
+}
+int
+pecoff_read_from(p, vp, pos, buf, siz)
+ struct proc *p;
+ struct vnode *vp;
+ int pos;
+ caddr_t buf;
+ int siz;
+{
+ int error;
+ size_t resid;
+
+ error = vn_rdwr(UIO_READ, vp, buf, siz, pos,
+ UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
+ &resid, p);
+ if (error)
+ return error;
+
+ if (resid != 0) {
+ return ENOEXEC;
+ }
+ return 0;
+}
+
+static int
+imgact_pecoff(struct image_params * imgp)
+{
+ struct pecoff_dos_filehdr *dp = (struct pecoff_dos_filehdr *)
+ imgp->image_header;
+ struct coff_filehdr *fp;
+ int error, peofs;
+ error = pecoff_signature(imgp->proc, imgp->vp, dp);
+ if (error) {
+ return -1;
+ }
+ peofs = dp->d_peofs + sizeof(signature) - 1;
+ fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
+ error = pecoff_read_from(imgp->proc, imgp->vp, peofs, (caddr_t) fp,
+ PECOFF_HDR_SIZE);
+ if (error) {
+ free(fp, M_TEMP);
+ return error;
+ }
+ error = exec_pecoff_coff_makecmds(imgp, fp, peofs);
+ free(fp, M_TEMP);
+ return error;
+}
+
+static struct execsw pecoff_execsw = {imgact_pecoff, "FreeBSD PEcoff"};
+EXEC_SET(pecoff, pecoff_execsw);
diff --git a/sys/compat/pecoff/imgact_pecoff.h b/sys/compat/pecoff/imgact_pecoff.h
new file mode 100644
index 0000000..0da3a56
--- /dev/null
+++ b/sys/compat/pecoff/imgact_pecoff.h
@@ -0,0 +1,142 @@
+/* $NetBSD$ */
+/* $FreeBSD$ */
+/*
+ * Copyright (c) 2000 Masaru OKI
+ */
+
+#ifndef _PECOFF_EXEC_H_
+#define _PECOFF_EXEC_H_
+
+struct pecoff_dos_filehdr {
+ u_int16_t d_magic;/* +0x00 'MZ' */
+ u_int8_t d_stub[0x3a];
+ u_int32_t d_peofs;/* +0x3c */
+};
+
+#define PECOFF_DOS_MAGIC 0x5a4d
+#define PECOFF_DOS_HDR_SIZE (sizeof(struct pecoff_dos_filehdr))
+
+#define DOS_BADMAG(dp) ((dp)->d_magic != PECOFF_DOS_MAGIC)
+
+/*
+ * COFF file header
+ */
+
+struct coff_filehdr {
+ u_short f_magic;/* magic number */
+ u_short f_nscns;/* # of sections */
+ long f_timdat; /* timestamp */
+ long f_symptr; /* file offset of symbol table */
+ long f_nsyms;/* # of symbol table entries */
+ u_short f_opthdr; /* size of optional header */
+ u_short f_flags;/* flags */
+};
+
+/*
+ * COFF system header
+ */
+
+struct coff_aouthdr {
+ short a_magic;
+ short a_vstamp;
+ long a_tsize;
+ long a_dsize;
+ long a_bsize;
+ long a_entry;
+ long a_tstart;
+ long a_dstart;
+};
+
+/* magic */
+#define COFF_OMAGIC 0407 /* text not write-protected; data seg is
+ * contiguous with text */
+#define COFF_NMAGIC 0410 /* text is write-protected; data starts at
+ * next seg following text */
+#define COFF_ZMAGIC 0413 /* text and data segs are aligned for direct
+ * paging */
+#define COFF_SMAGIC 0443 /* shared lib */
+
+struct pecoff_imghdr {
+ long i_vaddr;
+ long i_size;
+};
+
+struct pecoff_opthdr {
+ long w_base;
+ long w_salign;
+ long w_falign;
+ long w_osvers;
+ long w_imgvers;
+ long w_subvers;
+ long w_rsvd;
+ long w_imgsize;
+ long w_hdrsize;
+ long w_chksum;
+ u_short w_subsys;
+ u_short w_dllflags;
+ long w_ssize;
+ long w_cssize;
+ long w_hsize;
+ long w_chsize;
+ long w_lflag;
+ long w_nimghdr;
+ struct pecoff_imghdr w_imghdr[16];
+};
+
+/*
+ * COFF section header
+ */
+
+struct coff_scnhdr {
+ char s_name[8];
+ long s_paddr;
+ long s_vaddr;
+ long s_size;
+ long s_scnptr;
+ long s_relptr;
+ long s_lnnoptr;
+ u_short s_nreloc;
+ u_short s_nlnno;
+ long s_flags;
+};
+
+/* s_flags */
+#define COFF_STYP_REG 0x00
+#define COFF_STYP_DSECT 0x01
+#define COFF_STYP_NOLOAD 0x02
+#define COFF_STYP_GROUP 0x04
+#define COFF_STYP_PAD 0x08
+#define COFF_STYP_COPY 0x10
+#define COFF_STYP_TEXT 0x20
+#define COFF_STYP_DATA 0x40
+#define COFF_STYP_BSS 0x80
+#define COFF_STYP_INFO 0x200
+#define COFF_STYP_OVER 0x400
+#define COFF_STYP_SHLIB 0x800
+/* s_flags for PE */
+#define COFF_STYP_DISCARD 0x2000000
+#define COFF_STYP_EXEC 0x20000000
+#define COFF_STYP_READ 0x40000000
+#define COFF_STYP_WRITE 0x80000000
+
+struct pecoff_args {
+ u_long a_base;
+ u_long a_entry;
+ u_long a_end;
+ u_long a_subsystem;
+ struct pecoff_imghdr a_imghdr[16];
+ u_long a_ldbase;
+ u_long a_ldexport;
+};
+
+#define COFF_LDPGSZ 4096
+#define COFF_ALIGN(a) ((a) & ~(COFF_LDPGSZ - 1))
+#define COFF_ROUND(a) COFF_ALIGN((a) + COFF_LDPGSZ - 1)
+
+#define COFF_HDR_SIZE \
+ (sizeof(struct coff_filehdr) + sizeof(struct coff_aouthdr))
+
+#define PECOFF_HDR_SIZE (COFF_HDR_SIZE + sizeof(struct pecoff_opthdr))
+
+
+#endif
OpenPOWER on IntegriCloud