The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/pecoff/imgact_pecoff.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Masaru OKI
    3  * Copyright (c) 1994, 1995, 1998 Scott Bartram
    4  * Copyright (c) 1994 Adam Glass
    5  * Copyright (c) 1993, 1994 Christopher G. Demetriou
    6  *
    7  * originally from NetBSD kern/exec_ecoff.c
    8  *
    9  * Copyright (c) 2000 Takanori Watanabe
   10  * Copyright (c) 2000 KUROSAWA Takahiro
   11  * Copyright (c) 1995-1996 Sen Schmidt
   12  * Copyright (c) 1996 Peter Wemm
   13  * All rights reserved.
   14  *
   15  * originally from FreeBSD kern/imgact_elf.c
   16  *
   17  * Redistribution and use in source and binary forms, with or without
   18  * modification, are permitted provided that the following conditions
   19  * are met:
   20  * 1. Redistributions of source code must retain the above copyright
   21  *    notice, this list of conditions and the following disclaimer.
   22  * 2. Redistributions in binary form must reproduce the above copyright
   23  *    notice, this list of conditions and the following disclaimer in the
   24  *    documentation and/or other materials provided with the distribution.
   25  * 3. All advertising materials mentioning features or use of this software
   26  *    must display the following acknowledgement:
   27  *      This product includes software developed by Masaru OKI.
   28  * 4. The name of the author may not be used to endorse or promote products
   29  *    derived from this software without specific prior written permission
   30  *
   31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   34  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   36  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __FBSDID("$FreeBSD: releng/5.2/sys/compat/pecoff/imgact_pecoff.c 120422 2003-09-25 01:10:26Z peter $");
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/imgact.h>
   49 #include <sys/lock.h>
   50 #include <sys/malloc.h>
   51 #include <sys/mman.h>
   52 #include <sys/mutex.h>
   53 #include <sys/namei.h>
   54 #include <sys/proc.h>
   55 #include <sys/signalvar.h>
   56 #include <sys/sysent.h>
   57 #include <sys/vnode.h>
   58 
   59 #include <machine/reg.h>
   60 
   61 #include <vm/vm.h>
   62 #include <vm/vm_kern.h>
   63 #include <vm/vm_param.h>
   64 #include <vm/pmap.h>
   65 #include <vm/vm_map.h>
   66 #include <vm/vm_object.h>
   67 #include <vm/vm_extern.h>
   68 
   69 #include <sys/user.h>
   70 #include <sys/exec.h>
   71 #include <sys/kernel.h>
   72 #include <sys/module.h>
   73 #include <machine/cpu.h>
   74 #include <sys/syscall.h>
   75 #include <sys/sysent.h>
   76 #include <machine/md_var.h>
   77 #include <machine/pecoff_machdep.h>
   78 #include <compat/pecoff/imgact_pecoff.h>
   79 
   80 #include "opt_pecoff.h"
   81 
   82 #define PECOFF_PE_SIGNATURE "PE\0\0"
   83 static int      pecoff_fixup(register_t **, struct image_params *);
   84 static int 
   85 pecoff_coredump(register struct thread *, register struct vnode *,
   86                 off_t);
   87 #ifndef PECOFF_DEBUG
   88 #define DPRINTF(a)
   89 #else
   90 #define DPRINTF(a) printf a
   91 #endif
   92 static struct sysentvec pecoff_sysvec = {
   93         SYS_MAXSYSCALL,
   94         sysent,
   95         0,
   96         0,
   97         NULL,
   98         0,
   99         NULL,
  100         NULL,
  101         pecoff_fixup,
  102         sendsig,
  103         sigcode,
  104         &szsigcode,
  105         0,
  106         "FreeBSD PECoff",
  107         pecoff_coredump,
  108         NULL,
  109         MINSIGSTKSZ,
  110         PAGE_SIZE,
  111         VM_MIN_ADDRESS,
  112         VM_MAXUSER_ADDRESS,
  113         USRSTACK,
  114         PS_STRINGS,
  115         VM_PROT_ALL,
  116         exec_copyout_strings,
  117         exec_setregs,
  118         NULL
  119         
  120 };
  121 
  122 static const char signature[] = PECOFF_PE_SIGNATURE;
  123 
  124 static int 
  125 exec_pecoff_coff_prep_omagic(struct image_params *,
  126                              struct coff_filehdr *,
  127                              struct coff_aouthdr *, int peoffs);
  128 static int 
  129 exec_pecoff_coff_prep_nmagic(struct image_params *,
  130                              struct coff_filehdr *,
  131                              struct coff_aouthdr *, int peoffs);
  132 static int 
  133 exec_pecoff_coff_prep_zmagic(struct image_params *,
  134                              struct coff_filehdr *,
  135                              struct coff_aouthdr *, int peoffs);
  136 
  137 static int 
  138 exec_pecoff_coff_makecmds(struct image_params *,
  139                           struct coff_filehdr *, int);
  140 
  141 static int      pecoff_signature(struct thread *, struct vnode *, const struct pecoff_dos_filehdr *);
  142 static int      pecoff_read_from(struct thread *, struct vnode *, int, caddr_t, int);
  143 static int 
  144 pecoff_load_section(struct thread * td,
  145                     struct vmspace * vmspace, struct vnode * vp,
  146              vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
  147                     vm_prot_t prot);
  148 
  149 static int 
  150 pecoff_fixup(register_t ** stack_base, struct image_params * imgp)
  151 {
  152         int             len = sizeof(struct pecoff_args);
  153         struct pecoff_imghdr *ap;
  154         register_t     *pos;
  155 
  156         pos = *stack_base + (imgp->argc + imgp->envc + 2);
  157         ap = (struct pecoff_imghdr *) imgp->auxargs;
  158         if (copyout(ap, pos, len)) {
  159                 return 0;
  160         }
  161         free(ap, M_TEMP);
  162         imgp->auxargs = NULL;
  163         (*stack_base)--;
  164         suword(*stack_base, (long) imgp->argc);
  165         return 0;
  166 }
  167 
  168 
  169 static int 
  170 pecoff_coredump(register struct thread * td, register struct vnode * vp,
  171                 off_t limit)
  172 {
  173         register struct ucred *cred = td->td_ucred;
  174         struct proc *p = td->td_proc;
  175         register struct vmspace *vm = p->p_vmspace;
  176         char *tempuser;
  177         int             error;
  178 #ifdef PECOFF_DEBUG
  179         struct vm_map  *map;
  180         struct vm_map_entry *ent;
  181         struct reg      regs;
  182 
  183 #endif
  184         if (ctob((uarea_pages + kstack_pages) + vm->vm_dsize + vm->vm_ssize) >=
  185             limit)
  186                 return (EFAULT);
  187         tempuser = malloc(ctob(uarea_pages + kstack_pages), M_TEMP,
  188             M_WAITOK | M_ZERO);
  189         if (tempuser == NULL)
  190                 return (ENOMEM);
  191         PROC_LOCK(p);
  192         fill_kinfo_proc(p, &p->p_uarea->u_kproc);
  193         PROC_UNLOCK(p);
  194         bcopy(p->p_uarea, tempuser, sizeof(struct user));
  195         bcopy(td->td_frame,
  196             tempuser + ctob(uarea_pages) +
  197             ((caddr_t)td->td_frame - (caddr_t)td->td_kstack),
  198             sizeof(struct trapframe));
  199 #if PECOFF_DEBUG
  200         fill_regs(td, &regs);
  201         printf("EIP%x\n", regs.r_eip);
  202         printf("EAX%x EBX%x ECX%x EDI%x\n",
  203                regs.r_eax, regs.r_ebx, regs.r_ecx, regs.r_edi);
  204         map = &vm->vm_map;
  205         ent = &map->header;
  206         printf("%p %p %p\n", ent, ent->prev, ent->next);
  207 #endif
  208         error = vn_rdwr(UIO_WRITE, vp, (caddr_t)tempuser,
  209             ctob(uarea_pages + kstack_pages),
  210             (off_t)0, UIO_SYSSPACE, IO_UNIT, cred, NOCRED,
  211             (int *)NULL, td);
  212         free(tempuser, M_TEMP);
  213         if (error == 0)
  214                 error = vn_rdwr_inchunks(UIO_WRITE, vp, vm->vm_daddr,
  215                     (int)ctob(vm->vm_dsize),
  216                     (off_t)ctob((uarea_pages + kstack_pages)),
  217                     UIO_USERSPACE, IO_UNIT, cred, NOCRED, (int *)NULL, td);
  218         if (error == 0)
  219                 error = vn_rdwr_inchunks(UIO_WRITE, vp,
  220                     (caddr_t)trunc_page(USRSTACK - ctob(vm->vm_ssize)),
  221                     round_page(ctob(vm->vm_ssize)),
  222                     (off_t)ctob((uarea_pages + kstack_pages)) +
  223                     ctob(vm->vm_dsize),
  224                     UIO_USERSPACE, IO_UNIT, cred, NOCRED, (int *)NULL, td);
  225         return (error);
  226 
  227 }
  228 
  229 static int 
  230 pecoff_load_section(struct thread * td, struct vmspace * vmspace, struct vnode * vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
  231 {
  232         size_t          map_len;
  233         vm_offset_t     map_addr;
  234         int             error, rv;
  235         size_t          copy_len;
  236         size_t          copy_map_len;
  237         size_t          copy_start;
  238         vm_object_t     object;
  239         vm_offset_t     copy_map_offset;
  240         vm_offset_t     file_addr;
  241         vm_offset_t     data_buf = 0;
  242 
  243         object = vp->v_object;
  244         error = 0;
  245 
  246         map_addr = trunc_page((vm_offset_t) vmaddr);
  247         file_addr = trunc_page(offset);
  248         DPRINTF(("SECARG:%x %p %x %x\n", offset, vmaddr, memsz, filsz));
  249         if (file_addr != offset) {
  250                 /*
  251                  * The section is not on page  boundary. We can't use
  252                  * vm_map_insert(). Use copyin instead.
  253                  */
  254                 map_len = round_page(memsz);
  255                 copy_len = filsz;
  256                 copy_map_offset = file_addr;
  257                 copy_map_len = round_page(offset + filsz) - file_addr;
  258                 copy_start = offset - file_addr;
  259 
  260                 DPRINTF(("offset=%x vmaddr=%lx filsz=%x memsz=%x\n",
  261                          offset, (long)vmaddr, filsz, memsz));
  262                 DPRINTF(("map_len=%x copy_len=%x copy_map_offset=%x"
  263                          " copy_map_len=%x copy_start=%x\n",
  264                          map_len, copy_len, copy_map_offset,
  265                          copy_map_len, copy_start));
  266         } else {
  267 
  268                 map_len = trunc_page(filsz);
  269 
  270                 if (map_len != 0) {
  271                         vm_object_reference(object);
  272                         vm_map_lock(&vmspace->vm_map);
  273                         rv = vm_map_insert(&vmspace->vm_map,
  274                                            object,
  275                                            file_addr,   /* file offset */
  276                                            map_addr,    /* virtual start */
  277                                            map_addr + map_len,  /* virtual end */
  278                                            prot,
  279                                            VM_PROT_ALL,
  280                                            MAP_COPY_ON_WRITE | MAP_PREFAULT);
  281 
  282                         vm_map_unlock(&vmspace->vm_map);
  283                         if (rv != KERN_SUCCESS) {
  284                                 vm_object_deallocate(object);
  285                                 return EINVAL;
  286                         }
  287                         /* we can stop now if we've covered it all */
  288                         if (memsz == filsz)
  289                                 return 0;
  290 
  291                 }
  292                 copy_map_offset = trunc_page(offset + filsz);
  293                 copy_map_len = PAGE_SIZE;
  294                 copy_start = 0;
  295                 copy_len = (offset + filsz) - trunc_page(offset + filsz);
  296                 map_addr = trunc_page((vm_offset_t) vmaddr + filsz);
  297                 map_len = round_page((vm_offset_t) vmaddr + memsz) - map_addr;
  298 
  299         }
  300 
  301         if (map_len != 0) {
  302                 vm_map_lock(&vmspace->vm_map);
  303                 rv = vm_map_insert(&vmspace->vm_map, NULL, 0,
  304                                    map_addr, map_addr + map_len,
  305                                    VM_PROT_ALL, VM_PROT_ALL, 0);
  306                 vm_map_unlock(&vmspace->vm_map);
  307                 DPRINTF(("EMP-rv:%d,%x %x\n", rv, map_addr, map_addr + map_len));
  308                 if (rv != KERN_SUCCESS) {
  309                         return EINVAL;
  310                 }
  311         }
  312         DPRINTF(("COPYARG %x %x\n", map_addr, copy_len));
  313         if (copy_len != 0) {
  314                 vm_object_reference(object);
  315                 rv = vm_map_find(exec_map,
  316                                  object,
  317                                  copy_map_offset,
  318                                  &data_buf,
  319                                  copy_map_len,
  320                                  TRUE,
  321                                  VM_PROT_READ,
  322                                  VM_PROT_ALL,
  323                                  MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL);
  324                 if (rv != KERN_SUCCESS) {
  325                         vm_object_deallocate(object);
  326                         return EINVAL;
  327                 }
  328                 /* send the page fragment to user space */
  329 
  330                 error = copyout((caddr_t) data_buf + copy_start,
  331                                 (caddr_t) map_addr, copy_len);
  332                 vm_map_remove(exec_map, data_buf, data_buf + copy_map_len);
  333                 DPRINTF(("%d\n", error));
  334                 if (error)
  335                         return (error);
  336         }
  337         /*
  338          * set it to the specified protection
  339          */
  340         vm_map_protect(&vmspace->vm_map, map_addr,
  341                        map_addr + map_len, prot,
  342                        FALSE);
  343         return error;
  344 
  345 }
  346 static int 
  347 pecoff_load_file(struct thread * td, const char *file, u_long * addr, u_long * entry, u_long * ldexport)
  348 {
  349 
  350         struct nameidata nd;
  351         struct pecoff_dos_filehdr dh;
  352         struct coff_filehdr *fp = 0;
  353         struct coff_aouthdr *ap;
  354         struct pecoff_opthdr *wp;
  355         struct coff_scnhdr *sh = 0;
  356         struct vmspace *vmspace = td->td_proc->p_vmspace;
  357         struct vattr    attr;
  358         struct image_params image_params, *imgp;
  359         int             peofs;
  360         int             error, i, scnsiz;
  361 
  362         imgp = &image_params;
  363         /*
  364          * Initialize part of the common data
  365          */
  366         imgp->proc = td->td_proc;
  367         imgp->userspace_argv = NULL;
  368         imgp->userspace_envv = NULL;
  369         imgp->execlabel = NULL;
  370         imgp->attr = &attr;
  371         imgp->firstpage = NULL;
  372 
  373         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, td);
  374 
  375         if ((error = namei(&nd)) != 0) {
  376                 nd.ni_vp = NULL;
  377                 goto fail;
  378         }
  379         NDFREE(&nd, NDF_ONLY_PNBUF);
  380         imgp->vp = nd.ni_vp;
  381 
  382         /*
  383          * Check permissions, modes, uid, etc on the file, and "open" it.
  384          */
  385         error = exec_check_permissions(imgp);
  386         if (error) {
  387                 VOP_UNLOCK(nd.ni_vp, 0, td);
  388                 goto fail;
  389         }
  390         VOP_UNLOCK(nd.ni_vp, 0, td);
  391         if (error)
  392                 goto fail;
  393         if ((error = pecoff_read_from(td, imgp->vp, 0, (caddr_t) & dh, sizeof(dh))) != 0)
  394                 goto fail;
  395         if ((error = pecoff_signature(td, imgp->vp, &dh) != 0))
  396                 goto fail;
  397         fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
  398         peofs = dh.d_peofs + sizeof(signature) - 1;
  399         if ((error = pecoff_read_from(td, imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE) != 0))
  400                 goto fail;
  401         if (COFF_BADMAG(fp)) {
  402                 error = ENOEXEC;
  403                 goto fail;
  404         }
  405         ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
  406         wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
  407         /* read section header */
  408         scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
  409         sh = malloc(scnsiz, M_TEMP, M_WAITOK);
  410         if ((error = pecoff_read_from(td, imgp->vp, peofs + PECOFF_HDR_SIZE,
  411                                       (caddr_t) sh, scnsiz)) != 0)
  412                 goto fail;
  413 
  414         /*
  415          * Read Section infomation and map sections.
  416          */
  417 
  418         for (i = 0; i < fp->f_nscns; i++) {
  419                 int             prot = 0;
  420 
  421                 if (sh[i].s_flags & COFF_STYP_DISCARD)
  422                         continue;
  423                 /* XXX ? */
  424                 if ((sh[i].s_flags & COFF_STYP_TEXT) &&
  425                     (sh[i].s_flags & COFF_STYP_EXEC) == 0)
  426                         continue;
  427                 if ((sh[i].s_flags & (COFF_STYP_TEXT | COFF_STYP_DATA | COFF_STYP_BSS)) == 0)
  428                         continue;
  429 
  430                 prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
  431                 prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
  432                 prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
  433 
  434                 sh[i].s_vaddr += wp->w_base;    /* RVA --> VA */
  435                 if ((error = pecoff_load_section(td, vmspace, imgp->vp, sh[i].s_scnptr
  436                                                  ,(caddr_t) sh[i].s_vaddr,
  437                                                  sh[i].s_paddr, sh[i].s_size
  438                                                  ,prot)) != 0)
  439                         goto fail;
  440 
  441         }
  442         *entry = wp->w_base + ap->a_entry;
  443         *addr = wp->w_base;
  444         *ldexport = wp->w_imghdr[0].i_vaddr + wp->w_base;
  445 fail:
  446         if (fp)
  447                 free(fp, M_TEMP);
  448         if (sh)
  449                 free(sh, M_TEMP);
  450         if (nd.ni_vp)
  451                 vrele(nd.ni_vp);
  452 
  453         return error;
  454 }
  455 static int
  456 exec_pecoff_coff_prep_omagic(struct image_params * imgp,
  457                              struct coff_filehdr * fp,
  458                              struct coff_aouthdr * ap, int peofs)
  459 {
  460         return ENOEXEC;
  461 }
  462 static int
  463 exec_pecoff_coff_prep_nmagic(struct image_params * imgp,
  464                              struct coff_filehdr * fp,
  465                              struct coff_aouthdr * ap, int peofs)
  466 {
  467         return ENOEXEC;
  468 }
  469 static int
  470 exec_pecoff_coff_prep_zmagic(struct image_params * imgp,
  471                              struct coff_filehdr * fp,
  472                              struct coff_aouthdr * ap, int peofs)
  473 {
  474         int             scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
  475         int             error = ENOEXEC, i;
  476         int             prot;
  477         u_long          text_size = 0, data_size = 0, dsize;
  478         u_long          text_addr = 0, data_addr = VM_MAXUSER_ADDRESS;
  479         u_long          ldexport, ldbase;
  480         struct pecoff_opthdr *wp;
  481         struct coff_scnhdr *sh;
  482         struct vmspace *vmspace;
  483         struct pecoff_args *argp = NULL;
  484 
  485         sh = malloc(scnsiz, M_TEMP, M_WAITOK);
  486 
  487         wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
  488         error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp,
  489             peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz);
  490         if ((error = exec_extract_strings(imgp)) != 0)
  491                 goto fail;
  492         exec_new_vmspace(imgp, &pecoff_sysvec);
  493         vmspace = imgp->proc->p_vmspace;
  494         for (i = 0; i < fp->f_nscns; i++) {
  495                 prot = VM_PROT_WRITE;   /* XXX for relocation? */
  496                 prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
  497                 prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
  498                 prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
  499                 sh[i].s_vaddr += wp->w_base;
  500                 if (sh[i].s_flags & COFF_STYP_DISCARD)
  501                         continue;
  502                 if ((sh[i].s_flags & COFF_STYP_TEXT) != 0) {
  503 
  504                         error = pecoff_load_section(
  505                             FIRST_THREAD_IN_PROC(imgp->proc),
  506                             vmspace, imgp->vp, sh[i].s_scnptr,
  507                             (caddr_t) sh[i].s_vaddr, sh[i].s_paddr,
  508                             sh[i].s_size ,prot);
  509                         DPRINTF(("ERROR%d\n", error));
  510                         if (error)
  511                                 goto fail;
  512                         text_addr = trunc_page(sh[i].s_vaddr);
  513                         text_size = trunc_page(sh[i].s_size + sh[i].s_vaddr - text_addr);
  514 
  515                 }
  516                 if ((sh[i].s_flags & (COFF_STYP_DATA|COFF_STYP_BSS)) != 0) {
  517                         if (pecoff_load_section(
  518                             FIRST_THREAD_IN_PROC(imgp->proc), vmspace,
  519                             imgp->vp, sh[i].s_scnptr, (caddr_t) sh[i].s_vaddr,
  520                             sh[i].s_paddr, sh[i].s_size, prot) != 0)
  521                                 goto fail;
  522                         data_addr = min(trunc_page(sh[i].s_vaddr), data_addr);
  523                         dsize = round_page(sh[i].s_vaddr + sh[i].s_paddr)
  524                                 - data_addr;
  525                         data_size = max(dsize, data_size);
  526 
  527                 }
  528         }
  529         vmspace->vm_tsize = text_size >> PAGE_SHIFT;
  530         vmspace->vm_taddr = (caddr_t) (uintptr_t) text_addr;
  531         vmspace->vm_dsize = data_size >> PAGE_SHIFT;
  532         vmspace->vm_daddr = (caddr_t) (uintptr_t) data_addr;
  533         argp = malloc(sizeof(struct pecoff_args), M_TEMP, M_WAITOK);
  534         if (argp == NULL) {
  535                 error = ENOMEM;
  536                 goto fail;
  537         }
  538         argp->a_base = wp->w_base;
  539         argp->a_entry = wp->w_base + ap->a_entry;
  540         argp->a_end = data_addr + data_size;
  541         argp->a_subsystem = wp->w_subvers;
  542         error = pecoff_load_file(FIRST_THREAD_IN_PROC(imgp->proc),
  543             "/usr/libexec/ld.so.dll", &ldbase, &imgp->entry_addr, &ldexport);
  544         if (error)
  545                 goto fail;
  546 
  547         argp->a_ldbase = ldbase;
  548         argp->a_ldexport = ldexport;
  549         memcpy(argp->a_imghdr, wp->w_imghdr, sizeof(struct pecoff_imghdr) * 16);
  550         for (i = 0; i < 16; i++) {
  551                 argp->a_imghdr[i].i_vaddr += wp->w_base;
  552         }
  553         imgp->proc->p_sysent = &pecoff_sysvec;
  554         if (error)
  555                 goto fail;
  556         imgp->auxargs = argp;
  557         imgp->auxarg_size = sizeof(struct pecoff_args);
  558         imgp->interpreted = 0;
  559 
  560         if (sh != NULL)
  561                 free(sh, M_TEMP);
  562         return 0;
  563 fail:
  564         error = (error) ? error : ENOEXEC;
  565         if (sh != NULL)
  566                 free(sh, M_TEMP);
  567         if (argp != NULL)
  568                 free(argp, M_TEMP);
  569 
  570         return error;
  571 }
  572 
  573 int
  574 exec_pecoff_coff_makecmds(struct image_params * imgp,
  575                           struct coff_filehdr * fp, int peofs)
  576 {
  577         struct coff_aouthdr *ap;
  578         int             error;
  579 
  580         if (COFF_BADMAG(fp)) {
  581                 return ENOEXEC;
  582         }
  583         ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
  584         switch (ap->a_magic) {
  585         case COFF_OMAGIC:
  586                 error = exec_pecoff_coff_prep_omagic(imgp, fp, ap, peofs);
  587                 break;
  588         case COFF_NMAGIC:
  589                 error = exec_pecoff_coff_prep_nmagic(imgp, fp, ap, peofs);
  590                 break;
  591         case COFF_ZMAGIC:
  592                 error = exec_pecoff_coff_prep_zmagic(imgp, fp, ap, peofs);
  593                 break;
  594         default:
  595                 return ENOEXEC;
  596         }
  597 
  598         return error;
  599 }
  600 
  601 static int
  602 pecoff_signature(td, vp, dp)
  603         struct thread  *td;
  604         struct vnode   *vp;
  605         const struct pecoff_dos_filehdr *dp;
  606 {
  607         int             error;
  608         char            buf[512];
  609         char           *pesig;
  610         if (DOS_BADMAG(dp)) {
  611                 return ENOEXEC;
  612         }
  613         error = pecoff_read_from(td, vp, dp->d_peofs, buf, sizeof(buf));
  614         if (error) {
  615                 return error;
  616         }
  617         pesig = buf;
  618         if (memcmp(pesig, signature, sizeof(signature) - 1) == 0) {
  619                 return 0;
  620         }
  621         return EFTYPE;
  622 }
  623 int
  624 pecoff_read_from(td, vp, pos, buf, siz)
  625         struct thread  *td;
  626         struct vnode   *vp;
  627         int             pos;
  628         caddr_t         buf;
  629         int             siz;
  630 {
  631         int             error;
  632         size_t          resid;
  633 
  634         error = vn_rdwr(UIO_READ, vp, buf, siz, pos,
  635                         UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
  636                         &resid, td);
  637         if (error)
  638                 return error;
  639 
  640         if (resid != 0) {
  641                 return ENOEXEC;
  642         }
  643         return 0;
  644 }
  645 
  646 static int 
  647 imgact_pecoff(struct image_params * imgp)
  648 {
  649         const struct pecoff_dos_filehdr *dp = (const struct pecoff_dos_filehdr *)
  650         imgp->image_header;
  651         struct coff_filehdr *fp;
  652         int             error, peofs;
  653         struct thread *td = curthread;
  654 
  655         error = pecoff_signature(FIRST_THREAD_IN_PROC(imgp->proc),
  656             imgp->vp, dp);
  657         if (error) {
  658                 return -1;
  659         }
  660         VOP_UNLOCK(imgp->vp, 0, td);
  661 
  662         peofs = dp->d_peofs + sizeof(signature) - 1;
  663         fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
  664         error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc),
  665              imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE);
  666         if (error)
  667                 goto fail;
  668 
  669         error = exec_pecoff_coff_makecmds(imgp, fp, peofs);
  670 fail:   
  671         free(fp, M_TEMP);
  672         vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY, td);
  673         return error;
  674 }
  675 
  676 static struct execsw pecoff_execsw = {imgact_pecoff, "FreeBSD PEcoff"};
  677 EXEC_SET(pecoff, pecoff_execsw);

Cache object: 93c11e9464607985622f3c6302ad6f8f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.