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->args->argc + imgp->args->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->args->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->execlabel = NULL;
  303         imgp->attr = &attr;
  304         imgp->firstpage = NULL;
  305 
  306         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, td);
  307 
  308         if ((error = namei(&nd)) != 0) {
  309                 nd.ni_vp = NULL;
  310                 goto fail;
  311         }
  312         NDFREE(&nd, NDF_ONLY_PNBUF);
  313         imgp->vp = nd.ni_vp;
  314 
  315         /*
  316          * Check permissions, modes, uid, etc on the file, and "open" it.
  317          */
  318         error = exec_check_permissions(imgp);
  319         VOP_UNLOCK(nd.ni_vp, 0, td);
  320         if (error)
  321                 goto fail;
  322         if ((error = pecoff_read_from(td, imgp->vp, 0, (caddr_t) & dh, sizeof(dh))) != 0)
  323                 goto fail;
  324         if ((error = pecoff_signature(td, imgp->vp, &dh) != 0))
  325                 goto fail;
  326         fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
  327         peofs = dh.d_peofs + sizeof(signature) - 1;
  328         if ((error = pecoff_read_from(td, imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE) != 0))
  329                 goto fail;
  330         if (COFF_BADMAG(fp)) {
  331                 error = ENOEXEC;
  332                 goto fail;
  333         }
  334         ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
  335         wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
  336         /* read section header */
  337         scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
  338         sh = malloc(scnsiz, M_TEMP, M_WAITOK);
  339         if ((error = pecoff_read_from(td, imgp->vp, peofs + PECOFF_HDR_SIZE,
  340                                       (caddr_t) sh, scnsiz)) != 0)
  341                 goto fail;
  342 
  343         /*
  344          * Read Section infomation and map sections.
  345          */
  346 
  347         for (i = 0; i < fp->f_nscns; i++) {
  348                 int             prot = 0;
  349 
  350                 if (sh[i].s_flags & COFF_STYP_DISCARD)
  351                         continue;
  352                 /* XXX ? */
  353                 if ((sh[i].s_flags & COFF_STYP_TEXT) &&
  354                     (sh[i].s_flags & COFF_STYP_EXEC) == 0)
  355                         continue;
  356                 if ((sh[i].s_flags & (COFF_STYP_TEXT | COFF_STYP_DATA | COFF_STYP_BSS)) == 0)
  357                         continue;
  358 
  359                 prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
  360                 prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
  361                 prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
  362 
  363                 sh[i].s_vaddr += wp->w_base;    /* RVA --> VA */
  364                 if ((error = pecoff_load_section(td, vmspace, imgp->vp, sh[i].s_scnptr
  365                                                  ,(caddr_t) sh[i].s_vaddr,
  366                                                  sh[i].s_paddr, sh[i].s_size
  367                                                  ,prot)) != 0)
  368                         goto fail;
  369 
  370         }
  371         *entry = wp->w_base + ap->a_entry;
  372         *addr = wp->w_base;
  373         *ldexport = wp->w_imghdr[0].i_vaddr + wp->w_base;
  374 fail:
  375         if (fp)
  376                 free(fp, M_TEMP);
  377         if (sh)
  378                 free(sh, M_TEMP);
  379         if (nd.ni_vp)
  380                 vrele(nd.ni_vp);
  381 
  382         return error;
  383 }
  384 static int
  385 exec_pecoff_coff_prep_omagic(struct image_params * imgp,
  386                              struct coff_filehdr * fp,
  387                              struct coff_aouthdr * ap, int peofs)
  388 {
  389         return ENOEXEC;
  390 }
  391 static int
  392 exec_pecoff_coff_prep_nmagic(struct image_params * imgp,
  393                              struct coff_filehdr * fp,
  394                              struct coff_aouthdr * ap, int peofs)
  395 {
  396         return ENOEXEC;
  397 }
  398 static int
  399 exec_pecoff_coff_prep_zmagic(struct image_params * imgp,
  400                              struct coff_filehdr * fp,
  401                              struct coff_aouthdr * ap, int peofs)
  402 {
  403         int             scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
  404         int             error = ENOEXEC, i;
  405         int             prot;
  406         u_long          text_size = 0, data_size = 0, dsize;
  407         u_long          text_addr = 0, data_addr = VM_MAXUSER_ADDRESS;
  408         u_long          ldexport = 0, ldbase = 0;
  409         struct pecoff_opthdr *wp;
  410         struct coff_scnhdr *sh;
  411         struct vmspace *vmspace;
  412         struct pecoff_args *argp = NULL;
  413 
  414         sh = malloc(scnsiz, M_TEMP, M_WAITOK);
  415 
  416         wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
  417         error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp,
  418             peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz);
  419         if (error)
  420                 return (error);
  421         error = exec_new_vmspace(imgp, &pecoff_sysvec);
  422         if (error)
  423                 return (error);
  424         vmspace = imgp->proc->p_vmspace;
  425         for (i = 0; i < fp->f_nscns; i++) {
  426                 prot = VM_PROT_WRITE;   /* XXX for relocation? */
  427                 prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
  428                 prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
  429                 prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
  430                 sh[i].s_vaddr += wp->w_base;
  431                 if (sh[i].s_flags & COFF_STYP_DISCARD)
  432                         continue;
  433                 if ((sh[i].s_flags & COFF_STYP_TEXT) != 0) {
  434 
  435                         error = pecoff_load_section(
  436                             FIRST_THREAD_IN_PROC(imgp->proc),
  437                             vmspace, imgp->vp, sh[i].s_scnptr,
  438                             (caddr_t) sh[i].s_vaddr, sh[i].s_paddr,
  439                             sh[i].s_size ,prot);
  440                         DPRINTF(("ERROR%d\n", error));
  441                         if (error)
  442                                 goto fail;
  443                         text_addr = trunc_page(sh[i].s_vaddr);
  444                         text_size = trunc_page(sh[i].s_size + sh[i].s_vaddr - text_addr);
  445 
  446                 }
  447                 if ((sh[i].s_flags & (COFF_STYP_DATA|COFF_STYP_BSS)) != 0) {
  448                         if (pecoff_load_section(
  449                             FIRST_THREAD_IN_PROC(imgp->proc), vmspace,
  450                             imgp->vp, sh[i].s_scnptr, (caddr_t) sh[i].s_vaddr,
  451                             sh[i].s_paddr, sh[i].s_size, prot) != 0)
  452                                 goto fail;
  453                         data_addr = min(trunc_page(sh[i].s_vaddr), data_addr);
  454                         dsize = round_page(sh[i].s_vaddr + sh[i].s_paddr)
  455                                 - data_addr;
  456                         data_size = max(dsize, data_size);
  457 
  458                 }
  459         }
  460         vmspace->vm_tsize = text_size >> PAGE_SHIFT;
  461         vmspace->vm_taddr = (caddr_t) (uintptr_t) text_addr;
  462         vmspace->vm_dsize = data_size >> PAGE_SHIFT;
  463         vmspace->vm_daddr = (caddr_t) (uintptr_t) data_addr;
  464         argp = malloc(sizeof(struct pecoff_args), M_TEMP, M_WAITOK);
  465         if (argp == NULL) {
  466                 error = ENOMEM;
  467                 goto fail;
  468         }
  469         argp->a_base = wp->w_base;
  470         argp->a_entry = wp->w_base + ap->a_entry;
  471         argp->a_end = data_addr + data_size;
  472         argp->a_subsystem = wp->w_subvers;
  473         error = pecoff_load_file(FIRST_THREAD_IN_PROC(imgp->proc),
  474             "/usr/libexec/ld.so.dll", &ldbase, &imgp->entry_addr, &ldexport);
  475         if (error)
  476                 goto fail;
  477 
  478         argp->a_ldbase = ldbase;
  479         argp->a_ldexport = ldexport;
  480         memcpy(argp->a_imghdr, wp->w_imghdr, sizeof(struct pecoff_imghdr) * 16);
  481         for (i = 0; i < 16; i++) {
  482                 argp->a_imghdr[i].i_vaddr += wp->w_base;
  483         }
  484         imgp->proc->p_sysent = &pecoff_sysvec;
  485         imgp->auxargs = argp;
  486         imgp->auxarg_size = sizeof(struct pecoff_args);
  487         imgp->interpreted = 0;
  488 
  489         if (sh != NULL)
  490                 free(sh, M_TEMP);
  491         return 0;
  492 fail:
  493         error = (error) ? error : ENOEXEC;
  494         if (sh != NULL)
  495                 free(sh, M_TEMP);
  496         if (argp != NULL)
  497                 free(argp, M_TEMP);
  498 
  499         return error;
  500 }
  501 
  502 int
  503 exec_pecoff_coff_makecmds(struct image_params * imgp,
  504                           struct coff_filehdr * fp, int peofs)
  505 {
  506         struct coff_aouthdr *ap;
  507         int             error;
  508 
  509         if (COFF_BADMAG(fp)) {
  510                 return ENOEXEC;
  511         }
  512         ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
  513         switch (ap->a_magic) {
  514         case COFF_OMAGIC:
  515                 error = exec_pecoff_coff_prep_omagic(imgp, fp, ap, peofs);
  516                 break;
  517         case COFF_NMAGIC:
  518                 error = exec_pecoff_coff_prep_nmagic(imgp, fp, ap, peofs);
  519                 break;
  520         case COFF_ZMAGIC:
  521                 error = exec_pecoff_coff_prep_zmagic(imgp, fp, ap, peofs);
  522                 break;
  523         default:
  524                 return ENOEXEC;
  525         }
  526 
  527         return error;
  528 }
  529 
  530 static int
  531 pecoff_signature(td, vp, dp)
  532         struct thread  *td;
  533         struct vnode   *vp;
  534         const struct pecoff_dos_filehdr *dp;
  535 {
  536         int             error;
  537         char            buf[512];
  538         char           *pesig;
  539         if (DOS_BADMAG(dp)) {
  540                 return ENOEXEC;
  541         }
  542         error = pecoff_read_from(td, vp, dp->d_peofs, buf, sizeof(buf));
  543         if (error) {
  544                 return error;
  545         }
  546         pesig = buf;
  547         if (memcmp(pesig, signature, sizeof(signature) - 1) == 0) {
  548                 return 0;
  549         }
  550         return EFTYPE;
  551 }
  552 int
  553 pecoff_read_from(td, vp, pos, buf, siz)
  554         struct thread  *td;
  555         struct vnode   *vp;
  556         int             pos;
  557         caddr_t         buf;
  558         int             siz;
  559 {
  560         int             error;
  561         size_t          resid;
  562 
  563         error = vn_rdwr(UIO_READ, vp, buf, siz, pos,
  564                         UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
  565                         &resid, td);
  566         if (error)
  567                 return error;
  568 
  569         if (resid != 0) {
  570                 return ENOEXEC;
  571         }
  572         return 0;
  573 }
  574 
  575 static int 
  576 imgact_pecoff(struct image_params * imgp)
  577 {
  578         const struct pecoff_dos_filehdr *dp = (const struct pecoff_dos_filehdr *)
  579         imgp->image_header;
  580         struct coff_filehdr *fp;
  581         int             error, peofs;
  582         struct thread *td = curthread;
  583 
  584         error = pecoff_signature(FIRST_THREAD_IN_PROC(imgp->proc),
  585             imgp->vp, dp);
  586         if (error) {
  587                 return -1;
  588         }
  589         VOP_UNLOCK(imgp->vp, 0, td);
  590 
  591         peofs = dp->d_peofs + sizeof(signature) - 1;
  592         fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
  593         error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc),
  594              imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE);
  595         if (error)
  596                 goto fail;
  597 
  598         error = exec_pecoff_coff_makecmds(imgp, fp, peofs);
  599 fail:   
  600         free(fp, M_TEMP);
  601         vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY, td);
  602         return error;
  603 }
  604 
  605 static struct execsw pecoff_execsw = {imgact_pecoff, "FreeBSD PEcoff"};
  606 EXEC_SET(pecoff, pecoff_execsw);

Cache object: c6e680c5539234357a0fc4cc025c342d


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