diff options
| -rw-r--r-- | sys/compat/pecoff/imgact_pecoff.c | 641 | ||||
| -rw-r--r-- | sys/compat/pecoff/imgact_pecoff.h | 142 | ||||
| -rw-r--r-- | sys/conf/NOTES | 4 | ||||
| -rw-r--r-- | sys/conf/files.i386 | 1 | ||||
| -rw-r--r-- | sys/conf/options.i386 | 3 | ||||
| -rw-r--r-- | sys/i386/conf/NOTES | 4 | ||||
| -rw-r--r-- | sys/i386/include/pecoff_machdep.h | 60 | ||||
| -rw-r--r-- | sys/modules/pecoff/Makefile | 16 |
8 files changed, 868 insertions, 3 deletions
diff --git a/sys/compat/pecoff/imgact_pecoff.c b/sys/compat/pecoff/imgact_pecoff.c new file mode 100644 index 000000000000..b7fcd9b4a76b --- /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, ®s); + 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 000000000000..0da3a5604e30 --- /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 diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 54122aa36447..773d6daaff01 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2703,7 +2703,9 @@ options CPU_UPGRADE_HW_CACHE options DEBUG options DEBUG_LINUX - +# PECOFF module (Win32 Execution Format) +options PECOFF_SUPPORT +options PECOFF_DEBUG # Disable the 4 MByte PSE CPU feature. #options DISABLE_PSE options ENABLE_ALART diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 4f2be14c6193..872c215d0e01 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -65,6 +65,7 @@ compat/linux/linux_signal.c optional compat_linux compat/linux/linux_socket.c optional compat_linux compat/linux/linux_stats.c optional compat_linux compat/linux/linux_util.c optional compat_linux +compat/pecoff/imgact_pecoff.c optional pecoff_support compat/svr4/imgact_svr4.c optional compat_svr4 compat/svr4/svr4_fcntl.c optional compat_svr4 compat/svr4/svr4_filio.c optional compat_svr4 diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index 743c522f93ad..dbf80db7f0f4 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -30,7 +30,8 @@ COMPAT_LINUX opt_dontuse.h DEBUG_LINUX opt_linux.h COMPAT_SVR4 opt_dontuse.h DEBUG_SVR4 opt_svr4.h - +PECOFF_SUPPORT opt_dontuse.h +PECOFF_DEBUG opt_pecoff.h # i386 SMP options APIC_IO opt_global.h diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 54122aa36447..773d6daaff01 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -2703,7 +2703,9 @@ options CPU_UPGRADE_HW_CACHE options DEBUG options DEBUG_LINUX - +# PECOFF module (Win32 Execution Format) +options PECOFF_SUPPORT +options PECOFF_DEBUG # Disable the 4 MByte PSE CPU feature. #options DISABLE_PSE options ENABLE_ALART diff --git a/sys/i386/include/pecoff_machdep.h b/sys/i386/include/pecoff_machdep.h new file mode 100644 index 000000000000..b20cb711dc69 --- /dev/null +++ b/sys/i386/include/pecoff_machdep.h @@ -0,0 +1,60 @@ +/* $NetBSD: pecoff_machdep.h,v 1.5 2000/01/10 03:03:54 matt Exp $ */ +/* $FreeBSD$ */ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 FOUNDATION OR CONTRIBUTORS + * 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. + */ + +#ifndef _I386_PECOFF_MACHDEP_H_ +#define _I386_PECOFF_MACHDEP_H_ + +#define COFF_MAGIC_I386 0x14c +#define COFF_BADMAG(ex) (ex->f_magic != COFF_MAGIC_I386) + +#endif /* !_I386_PECOFF_MACHDEP_H_ */ + + + + + + + + + + + + + + + diff --git a/sys/modules/pecoff/Makefile b/sys/modules/pecoff/Makefile new file mode 100644 index 000000000000..0232d982dd9b --- /dev/null +++ b/sys/modules/pecoff/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../compat/pecoff + +MAINTAINER= takawata@FreeBSD.org + +KMOD= pecoff +SRCS= imgact_pecoff.c opt_pecoff.h vnode_if.h + + +CFLAGS+= -g -DDEBUG +#EXPORT_SYMS=_pecoff_mod + +opt_pecoff.h:Makefile + touch opt_pecoff.h +.include <bsd.kmod.mk> |
