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$");
   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/exec.h>
   70 #include <sys/kernel.h>
   71 #include <sys/module.h>
   72 #include <machine/cpu.h>
   73 #include <sys/syscall.h>
   74 #include <sys/sysent.h>
   75 #include <machine/md_var.h>
   76 #include <machine/pecoff_machdep.h>
   77 #include <compat/pecoff/imgact_pecoff.h>
   78 
   79 #include "opt_pecoff.h"
   80 
   81 #define PECOFF_PE_SIGNATURE "PE\0\0"
   82 static int      pecoff_fixup(register_t **, struct image_params *);
   83 #ifndef PECOFF_DEBUG
   84 #define DPRINTF(a)
   85 #else
   86 #define DPRINTF(a) printf a
   87 #endif
   88 static struct sysentvec pecoff_sysvec = {
   89         SYS_MAXSYSCALL,
   90         sysent,
   91         0,
   92         0,
   93         NULL,
   94         0,
   95         NULL,
   96         NULL,
   97         pecoff_fixup,
   98         sendsig,
   99         sigcode,
  100         &szsigcode,
  101         0,
  102         "FreeBSD PECoff",
  103         NULL,
  104         NULL,
  105         MINSIGSTKSZ,
  106         PAGE_SIZE,
  107         VM_MIN_ADDRESS,
  108         VM_MAXUSER_ADDRESS,
  109         USRSTACK,
  110         PS_STRINGS,
  111         VM_PROT_ALL,
  112         exec_copyout_strings,
  113         exec_setregs,
  114         NULL
  115         
  116 };
  117 
  118 static const char signature[] = PECOFF_PE_SIGNATURE;
  119 
  120 static int 
  121 exec_pecoff_coff_prep_omagic(struct image_params *,
  122                              struct coff_filehdr *,
  123                              struct coff_aouthdr *, int peoffs);
  124 static int 
  125 exec_pecoff_coff_prep_nmagic(struct image_params *,
  126                              struct coff_filehdr *,
  127                              struct coff_aouthdr *, int peoffs);
  128 static int 
  129 exec_pecoff_coff_prep_zmagic(struct image_params *,
  130                              struct coff_filehdr *,
  131                              struct coff_aouthdr *, int peoffs);
  132 
  133 static int 
  134 exec_pecoff_coff_makecmds(struct image_params *,
  135                           struct coff_filehdr *, int);
  136 
  137 static int      pecoff_signature(struct thread *, struct vnode *, const struct pecoff_dos_filehdr *);
  138 static int      pecoff_read_from(struct thread *, struct vnode *, int, caddr_t, int);
  139 static int 
  140 pecoff_load_section(struct thread * td,
  141                     struct vmspace * vmspace, struct vnode * vp,
  142              vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
  143                     vm_prot_t prot);
  144 
  145 static int 
  146 pecoff_fixup(register_t ** stack_base, struct image_params * imgp)
  147 {
  148         int             len = sizeof(struct pecoff_args);
  149         struct pecoff_imghdr *ap;
  150         register_t     *pos;
  151 
  152         pos = *stack_base + (imgp->argc + imgp->envc + 2);
  153         ap = (struct pecoff_imghdr *) imgp->auxargs;
  154         if (copyout(ap, pos, len)) {
  155                 return 0;
  156         }
  157         free(ap, M_TEMP);
  158         imgp->auxargs = NULL;
  159         (*stack_base)--;
  160         suword(*stack_base, (long) imgp->argc);
  161         return 0;
  162 }
  163 
  164 static int 
  165 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)
  166 {
  167         size_t          map_len;
  168         vm_offset_t     map_addr;
  169         int             error, rv;
  170         size_t          copy_len;
  171         size_t          copy_map_len;
  172         size_t          copy_start;
  173         vm_object_t     object;
  174         vm_offset_t     copy_map_offset;
  175         vm_offset_t     file_addr;
  176         vm_offset_t     data_buf = 0;
  177 
  178         object = vp->v_object;
  179         error = 0;
  180 
  181         map_addr = trunc_page((vm_offset_t) vmaddr);
  182         file_addr = trunc_page(offset);
  183         DPRINTF(("SECARG:%x %p %x %x\n", offset, vmaddr, memsz, filsz));
  184         if (file_addr != offset) {
  185                 /*
  186                  * The section is not on page  boundary. We can't use
  187                  * vm_map_insert(). Use copyin instead.
  188                  */
  189                 map_len = round_page(memsz);
  190                 copy_len = filsz;
  191                 copy_map_offset = file_addr;
  192                 copy_map_len = round_page(offset + filsz) - file_addr;
  193                 copy_start = offset - file_addr;
  194 
  195                 DPRINTF(("offset=%x vmaddr=%lx filsz=%x memsz=%x\n",
  196                          offset, (long)vmaddr, filsz, memsz));
  197                 DPRINTF(("map_len=%x copy_len=%x copy_map_offset=%x"
  198                          " copy_map_len=%x copy_start=%x\n",
  199                          map_len, copy_len, copy_map_offset,
  200                          copy_map_len, copy_start));
  201         } else {
  202 
  203                 map_len = trunc_page(filsz);
  204 
  205                 if (map_len != 0) {
  206                         vm_object_reference(object);
  207                         vm_map_lock(&vmspace->vm_map);
  208                         rv = vm_map_insert(&vmspace->vm_map,
  209                                            object,
  210                                            file_addr,   /* file offset */
  211                                            map_addr,    /* virtual start */
  212                                            map_addr + map_len,  /* virtual end */
  213                                            prot,
  214                                            VM_PROT_ALL,
  215                                            MAP_COPY_ON_WRITE | MAP_PREFAULT);
  216 
  217                         vm_map_unlock(&vmspace->vm_map);
  218                         if (rv != KERN_SUCCESS) {
  219                                 vm_object_deallocate(object);
  220                                 return EINVAL;
  221                         }
  222                         /* we can stop now if we've covered it all */
  223                         if (memsz == filsz)
  224                                 return 0;
  225 
  226                 }
  227                 copy_map_offset = trunc_page(offset + filsz);
  228                 copy_map_len = PAGE_SIZE;
  229                 copy_start = 0;
  230                 copy_len = (offset + filsz) - trunc_page(offset + filsz);
  231                 map_addr = trunc_page((vm_offset_t) vmaddr + filsz);
  232                 map_len = round_page((vm_offset_t) vmaddr + memsz) - map_addr;
  233 
  234         }
  235 
  236         if (map_len != 0) {
  237                 vm_map_lock(&vmspace->vm_map);
  238                 rv = vm_map_insert(&vmspace->vm_map, NULL, 0,
  239                                    map_addr, map_addr + map_len,
  240                                    VM_PROT_ALL, VM_PROT_ALL, 0);
  241                 vm_map_unlock(&vmspace->vm_map);
  242                 DPRINTF(("EMP-rv:%d,%x %x\n", rv, map_addr, map_addr + map_len));
  243                 if (rv != KERN_SUCCESS) {
  244                         return EINVAL;
  245                 }
  246         }
  247         DPRINTF(("COPYARG %x %x\n", map_addr, copy_len));
  248         if (copy_len != 0) {
  249                 vm_object_reference(object);
  250                 rv = vm_map_find(exec_map,
  251                                  object,
  252                                  copy_map_offset,
  253                                  &data_buf,
  254                                  copy_map_len,
  255                                  TRUE,
  256                                  VM_PROT_READ,
  257                                  VM_PROT_ALL,
  258                                  MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL);
  259                 if (rv != KERN_SUCCESS) {
  260                         vm_object_deallocate(object);
  261                         return EINVAL;
  262                 }
  263                 /* send the page fragment to user space */
  264 
  265                 error = copyout((caddr_t) data_buf + copy_start,
  266                                 (caddr_t) map_addr, copy_len);
  267                 vm_map_remove(exec_map, data_buf, data_buf + copy_map_len);
  268                 DPRINTF(("%d\n", error));
  269                 if (error)
  270                         return (error);
  271         }
  272         /*
  273          * set it to the specified protection
  274          */
  275         vm_map_protect(&vmspace->vm_map, map_addr,
  276                        map_addr + map_len, prot,
  277                        FALSE);
  278         return error;
  279 
  280 }
  281 static int 
  282 pecoff_load_file(struct thread * td, const char *file, u_long * addr, u_long * entry, u_long * ldexport)
  283 {
  284 
  285         struct nameidata nd;
  286         struct pecoff_dos_filehdr dh;
  287         struct coff_filehdr *fp = 0;
  288         struct coff_aouthdr *ap;
  289         struct pecoff_opthdr *wp;
  290         struct coff_scnhdr *sh = 0;
  291         struct vmspace *vmspace = td->td_proc->p_vmspace;
  292         struct vattr    attr;
  293         struct image_params image_params, *imgp;
  294         int             peofs;
  295         int             error, i, scnsiz;
  296 
  297         imgp = &image_params;
  298         /*
  299          * Initialize part of the common data
  300          */
  301         imgp->proc = td->td_proc;
  302         imgp->userspace_argv = NULL;
  303         imgp->userspace_envv = NULL;
  304         imgp->execlabel = NULL;
  305         imgp->attr = &attr;
  306         imgp->firstpage = NULL;
  307 
  308         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, td);
  309 
  310         if ((error = namei(&nd)) != 0) {
  311                 nd.ni_vp = NULL;
  312                 goto fail;
  313         }
  314         NDFREE(&nd, NDF_ONLY_PNBUF);
  315         imgp->vp = nd.ni_vp;
  316 
  317         /*
  318          * Check permissions, modes, uid, etc on the file, and "open" it.
  319          */
  320         error = exec_check_permissions(imgp);
  321         if (error) {
  322                 VOP_UNLOCK(nd.ni_vp, 0, td);
  323                 goto fail;
  324         }
  325         VOP_UNLOCK(nd.ni_vp, 0, td);
  326         if (error)
  327                 goto fail;
  328         if ((error = pecoff_read_from(td, imgp->vp, 0, (caddr_t) & dh, sizeof(dh))) != 0)
  329                 goto fail;
  330         if ((error = pecoff_signature(td, imgp->vp, &dh) != 0))
  331                 goto fail;
  332         fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
  333         peofs = dh.d_peofs + sizeof(signature) - 1;
  334         if ((error = pecoff_read_from(td, imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE) != 0))
  335                 goto fail;
  336         if (COFF_BADMAG(fp)) {
  337                 error = ENOEXEC;
  338                 goto fail;
  339         }
  340         ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
  341         wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
  342         /* read section header */
  343         scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
  344         sh = malloc(scnsiz, M_TEMP, M_WAITOK);
  345         if ((error = pecoff_read_from(td, imgp->vp, peofs + PECOFF_HDR_SIZE,
  346                                       (caddr_t) sh, scnsiz)) != 0)
  347                 goto fail;
  348 
  349         /*
  350          * Read Section infomation and map sections.
  351          */
  352 
  353         for (i = 0; i < fp->f_nscns; i++) {
  354                 int             prot = 0;
  355 
  356                 if (sh[i].s_flags & COFF_STYP_DISCARD)
  357                         continue;
  358                 /* XXX ? */
  359                 if ((sh[i].s_flags & COFF_STYP_TEXT) &&
  360                     (sh[i].s_flags & COFF_STYP_EXEC) == 0)
  361                         continue;
  362                 if ((sh[i].s_flags & (COFF_STYP_TEXT | COFF_STYP_DATA | COFF_STYP_BSS)) == 0)
  363                         continue;
  364 
  365                 prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
  366                 prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
  367                 prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
  368 
  369                 sh[i].s_vaddr += wp->w_base;    /* RVA --> VA */
  370                 if ((error = pecoff_load_section(td, vmspace, imgp->vp, sh[i].s_scnptr
  371                                                  ,(caddr_t) sh[i].s_vaddr,
  372                                                  sh[i].s_paddr, sh[i].s_size
  373                                                  ,prot)) != 0)
  374                         goto fail;
  375 
  376         }
  377         *entry = wp->w_base + ap->a_entry;
  378         *addr = wp->w_base;
  379         *ldexport = wp->w_imghdr[0].i_vaddr + wp->w_base;
  380 fail:
  381         if (fp)
  382                 free(fp, M_TEMP);
  383         if (sh)
  384                 free(sh, M_TEMP);
  385         if (nd.ni_vp)
  386                 vrele(nd.ni_vp);
  387 
  388         return error;
  389 }
  390 static int
  391 exec_pecoff_coff_prep_omagic(struct image_params * imgp,
  392                              struct coff_filehdr * fp,
  393                              struct coff_aouthdr * ap, int peofs)
  394 {
  395         return ENOEXEC;
  396 }
  397 static int
  398 exec_pecoff_coff_prep_nmagic(struct image_params * imgp,
  399                              struct coff_filehdr * fp,
  400                              struct coff_aouthdr * ap, int peofs)
  401 {
  402         return ENOEXEC;
  403 }
  404 static int
  405 exec_pecoff_coff_prep_zmagic(struct image_params * imgp,
  406                              struct coff_filehdr * fp,
  407                              struct coff_aouthdr * ap, int peofs)
  408 {
  409         int             scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
  410         int             error = ENOEXEC, i;
  411         int             prot;
  412         u_long          text_size = 0, data_size = 0, dsize;
  413         u_long          text_addr = 0, data_addr = VM_MAXUSER_ADDRESS;
  414         u_long          ldexport, ldbase;
  415         struct pecoff_opthdr *wp;
  416         struct coff_scnhdr *sh;
  417         struct vmspace *vmspace;
  418         struct pecoff_args *argp = NULL;
  419 
  420         sh = malloc(scnsiz, M_TEMP, M_WAITOK);
  421 
  422         wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
  423         error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp,
  424             peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz);
  425         if ((error = exec_extract_strings(imgp)) != 0)
  426                 goto fail;
  427         exec_new_vmspace(imgp, &pecoff_sysvec);
  428         vmspace = imgp->proc->p_vmspace;
  429         for (i = 0; i < fp->f_nscns; i++) {
  430                 prot = VM_PROT_WRITE;   /* XXX for relocation? */
  431                 prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
  432                 prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
  433                 prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
  434                 sh[i].s_vaddr += wp->w_base;
  435                 if (sh[i].s_flags & COFF_STYP_DISCARD)
  436                         continue;
  437                 if ((sh[i].s_flags & COFF_STYP_TEXT) != 0) {
  438 
  439                         error = pecoff_load_section(
  440                             FIRST_THREAD_IN_PROC(imgp->proc),
  441                             vmspace, imgp->vp, sh[i].s_scnptr,
  442                             (caddr_t) sh[i].s_vaddr, sh[i].s_paddr,
  443                             sh[i].s_size ,prot);
  444                         DPRINTF(("ERROR%d\n", error));
  445                         if (error)
  446                                 goto fail;
  447                         text_addr = trunc_page(sh[i].s_vaddr);
  448                         text_size = trunc_page(sh[i].s_size + sh[i].s_vaddr - text_addr);
  449 
  450                 }
  451                 if ((sh[i].s_flags & (COFF_STYP_DATA|COFF_STYP_BSS)) != 0) {
  452                         if (pecoff_load_section(
  453                             FIRST_THREAD_IN_PROC(imgp->proc), vmspace,
  454                             imgp->vp, sh[i].s_scnptr, (caddr_t) sh[i].s_vaddr,
  455                             sh[i].s_paddr, sh[i].s_size, prot) != 0)
  456                                 goto fail;
  457                         data_addr = min(trunc_page(sh[i].s_vaddr), data_addr);
  458                         dsize = round_page(sh[i].s_vaddr + sh[i].s_paddr)
  459                                 - data_addr;
  460                         data_size = max(dsize, data_size);
  461 
  462                 }
  463         }
  464         vmspace->vm_tsize = text_size >> PAGE_SHIFT;
  465         vmspace->vm_taddr = (caddr_t) (uintptr_t) text_addr;
  466         vmspace->vm_dsize = data_size >> PAGE_SHIFT;
  467         vmspace->vm_daddr = (caddr_t) (uintptr_t) data_addr;
  468         argp = malloc(sizeof(struct pecoff_args), M_TEMP, M_WAITOK);
  469         if (argp == NULL) {
  470                 error = ENOMEM;
  471                 goto fail;
  472         }
  473         argp->a_base = wp->w_base;
  474         argp->a_entry = wp->w_base + ap->a_entry;
  475         argp->a_end = data_addr + data_size;
  476         argp->a_subsystem = wp->w_subvers;
  477         error = pecoff_load_file(FIRST_THREAD_IN_PROC(imgp->proc),
  478             "/usr/libexec/ld.so.dll", &ldbase, &imgp->entry_addr, &ldexport);
  479         if (error)
  480                 goto fail;
  481 
  482         argp->a_ldbase = ldbase;
  483         argp->a_ldexport = ldexport;
  484         memcpy(argp->a_imghdr, wp->w_imghdr, sizeof(struct pecoff_imghdr) * 16);
  485         for (i = 0; i < 16; i++) {
  486                 argp->a_imghdr[i].i_vaddr += wp->w_base;
  487         }
  488         imgp->proc->p_sysent = &pecoff_sysvec;
  489         if (error)
  490                 goto fail;
  491         imgp->auxargs = argp;
  492         imgp->auxarg_size = sizeof(struct pecoff_args);
  493         imgp->interpreted = 0;
  494 
  495         if (sh != NULL)
  496                 free(sh, M_TEMP);
  497         return 0;
  498 fail:
  499         error = (error) ? error : ENOEXEC;
  500         if (sh != NULL)
  501                 free(sh, M_TEMP);
  502         if (argp != NULL)
  503                 free(argp, M_TEMP);
  504 
  505         return error;
  506 }
  507 
  508 int
  509 exec_pecoff_coff_makecmds(struct image_params * imgp,
  510                           struct coff_filehdr * fp, int peofs)
  511 {
  512         struct coff_aouthdr *ap;
  513         int             error;
  514 
  515         if (COFF_BADMAG(fp)) {
  516                 return ENOEXEC;
  517         }
  518         ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
  519         switch (ap->a_magic) {
  520         case COFF_OMAGIC:
  521                 error = exec_pecoff_coff_prep_omagic(imgp, fp, ap, peofs);
  522                 break;
  523         case COFF_NMAGIC:
  524                 error = exec_pecoff_coff_prep_nmagic(imgp, fp, ap, peofs);
  525                 break;
  526         case COFF_ZMAGIC:
  527                 error = exec_pecoff_coff_prep_zmagic(imgp, fp, ap, peofs);
  528                 break;
  529         default:
  530                 return ENOEXEC;
  531         }
  532 
  533         return error;
  534 }
  535 
  536 static int
  537 pecoff_signature(td, vp, dp)
  538         struct thread  *td;
  539         struct vnode   *vp;
  540         const struct pecoff_dos_filehdr *dp;
  541 {
  542         int             error;
  543         char            buf[512];
  544         char           *pesig;
  545         if (DOS_BADMAG(dp)) {
  546                 return ENOEXEC;
  547         }
  548         error = pecoff_read_from(td, vp, dp->d_peofs, buf, sizeof(buf));
  549         if (error) {
  550                 return error;
  551         }
  552         pesig = buf;
  553         if (memcmp(pesig, signature, sizeof(signature) - 1) == 0) {
  554                 return 0;
  555         }
  556         return EFTYPE;
  557 }
  558 int
  559 pecoff_read_from(td, vp, pos, buf, siz)
  560         struct thread  *td;
  561         struct vnode   *vp;
  562         int             pos;
  563         caddr_t         buf;
  564         int             siz;
  565 {
  566         int             error;
  567         size_t          resid;
  568 
  569         error = vn_rdwr(UIO_READ, vp, buf, siz, pos,
  570                         UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
  571                         &resid, td);
  572         if (error)
  573                 return error;
  574 
  575         if (resid != 0) {
  576                 return ENOEXEC;
  577         }
  578         return 0;
  579 }
  580 
  581 static int 
  582 imgact_pecoff(struct image_params * imgp)
  583 {
  584         const struct pecoff_dos_filehdr *dp = (const struct pecoff_dos_filehdr *)
  585         imgp->image_header;
  586         struct coff_filehdr *fp;
  587         int             error, peofs;
  588         struct thread *td = curthread;
  589 
  590         error = pecoff_signature(FIRST_THREAD_IN_PROC(imgp->proc),
  591             imgp->vp, dp);
  592         if (error) {
  593                 return -1;
  594         }
  595         VOP_UNLOCK(imgp->vp, 0, td);
  596 
  597         peofs = dp->d_peofs + sizeof(signature) - 1;
  598         fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
  599         error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc),
  600              imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE);
  601         if (error)
  602                 goto fail;
  603 
  604         error = exec_pecoff_coff_makecmds(imgp, fp, peofs);
  605 fail:   
  606         free(fp, M_TEMP);
  607         vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY, td);
  608         return error;
  609 }
  610 
  611 static struct execsw pecoff_execsw = {imgact_pecoff, "FreeBSD PEcoff"};
  612 EXEC_SET(pecoff, pecoff_execsw);

Cache object: ef0e7d18965c1d7a503905c6ebab6bdd


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