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

Cache object: 91aa2f079c67ab01fbb71632238b0e91


[ 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.