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/i386/ibcs2/imgact_coff.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) 1994 Sean Eric Fagan
    3  * Copyright (c) 1994 Søren Schmidt
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer
   11  *    in this position and unchanged.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software withough specific prior written permission
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  *
   29  * $FreeBSD: src/sys/i386/ibcs2/imgact_coff.c,v 1.17.2.1 1999/09/05 08:11:31 peter Exp $
   30  */
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/resourcevar.h>
   35 #include <sys/exec.h>
   36 #include <sys/mman.h>
   37 #include <sys/imgact.h>
   38 #include <sys/kernel.h>
   39 #include <sys/file.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mount.h>
   42 #include <sys/namei.h>
   43 #include <sys/sysent.h>
   44 #include <sys/vnode.h>
   45 
   46 #include <vm/vm.h>
   47 #include <vm/vm_param.h>
   48 #include <vm/vm_prot.h>
   49 #include <vm/lock.h>
   50 #include <vm/pmap.h>
   51 #include <vm/vm_map.h>
   52 #include <vm/vm_kern.h>
   53 #include <vm/vm_extern.h>
   54 
   55 #include <i386/ibcs2/coff.h>
   56 #include <i386/ibcs2/ibcs2_util.h>
   57 
   58 extern struct sysentvec ibcs2_svr3_sysvec;
   59 
   60 extern int coff_load_file __P((struct proc *p, char *name));
   61 extern int exec_coff_imgact __P((struct image_params *imgp));
   62 
   63 static int load_coff_section __P((struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot));
   64 
   65 static int
   66 load_coff_section(vmspace, vp, offset, vmaddr, memsz, filsz, prot)
   67         struct vmspace *vmspace;
   68         struct vnode *vp;
   69         vm_offset_t offset;
   70         caddr_t vmaddr;
   71         size_t memsz, filsz;
   72         vm_prot_t prot;
   73 {
   74         size_t map_len;
   75         vm_offset_t map_offset;
   76         vm_offset_t map_addr;
   77         int error;
   78         unsigned char *data_buf = 0;
   79         size_t copy_len;
   80 
   81         map_offset = trunc_page(offset);
   82         map_addr = trunc_page(vmaddr);
   83 
   84         if (memsz > filsz) {
   85                 /*
   86                  * We have the stupid situation that
   87                  * the section is longer than it is on file,
   88                  * which means it has zero-filled areas, and
   89                  * we have to work for it.  Stupid iBCS!
   90                  */
   91                 map_len = trunc_page(offset + filsz) - trunc_page(map_offset);
   92         } else {
   93                 /*
   94                  * The only stuff we care about is on disk, and we
   95                  * don't care if we map in more than is really there.
   96                  */
   97                 map_len = round_page(offset + filsz) - trunc_page(map_offset);
   98         }
   99 
  100         DPRINTF(("%s(%d):  vm_mmap(&vmspace->vm_map, &0x%08lx, 0x%x, 0x%x, "
  101                 "VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, vp, 0x%x)\n",
  102                 __FILE__, __LINE__, map_addr, map_len, prot, map_offset));
  103 
  104         if (error = vm_mmap(&vmspace->vm_map,
  105                              &map_addr,
  106                              map_len,
  107                              prot,
  108                              VM_PROT_ALL,
  109                              MAP_PRIVATE | MAP_FIXED,
  110                              (caddr_t) vp,
  111                              map_offset))
  112                 return error;
  113 
  114         if (memsz == filsz) {
  115                 /* We're done! */
  116                 return 0;
  117         }
  118 
  119         /*
  120          * Now we have screwball stuff, to accomodate stupid COFF.
  121          * We have to map the remaining bit of the file into the kernel's
  122          * memory map, allocate some anonymous memory, copy that last
  123          * bit into it, and then we're done. *sigh*
  124          * For clean-up reasons, we actally map in the file last.
  125          */
  126 
  127         copy_len = (offset + filsz) - trunc_page(offset + filsz);
  128         map_addr = trunc_page(vmaddr + filsz);
  129         map_len = round_page(vmaddr + memsz) - map_addr;
  130 
  131         DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx,0x%x, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n", __FILE__, __LINE__, map_addr, map_len));
  132 
  133         if (map_len != 0) {
  134                 error = vm_map_find(&vmspace->vm_map, NULL, 0, &map_addr,
  135                                     map_len, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
  136                 if (error)
  137                         return error;
  138         }
  139 
  140         if (error = vm_mmap(kernel_map,
  141                             (vm_offset_t *) &data_buf,
  142                             PAGE_SIZE,
  143                             VM_PROT_READ,
  144                             VM_PROT_READ,
  145                             0,
  146                             (caddr_t) vp,
  147                             trunc_page(offset + filsz)))
  148                 return error;
  149 
  150         error = copyout(data_buf, (caddr_t) map_addr, copy_len);
  151 
  152         if (vm_map_remove(kernel_map,
  153                           (vm_offset_t) data_buf,
  154                           (vm_offset_t) data_buf + PAGE_SIZE))
  155                 panic("load_coff_section vm_map_remove failed");
  156 
  157         return error;
  158 }
  159 
  160 int
  161 coff_load_file(struct proc *p, char *name)
  162 {
  163         struct vmspace *vmspace = p->p_vmspace;
  164         int error;
  165         struct nameidata nd;
  166         struct vnode *vp;
  167         struct vattr attr;
  168         struct filehdr *fhdr;
  169         struct aouthdr *ahdr;
  170         struct scnhdr *scns;
  171         char *ptr = 0;
  172         int nscns;
  173         unsigned long text_offset = 0, text_address = 0, text_size = 0;
  174         unsigned long data_offset = 0, data_address = 0, data_size = 0;
  175         unsigned long bss_size = 0;
  176         int i;
  177 
  178         /* XXX use of 'curproc' should be 'p'?*/
  179         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_SYSSPACE, name, curproc);
  180 
  181         error = namei(&nd);
  182         if (error)
  183                 return error;
  184 
  185         vp = nd.ni_vp;
  186         if (vp == NULL)
  187                 return ENOEXEC;
  188 
  189         if (vp->v_writecount) {
  190                 error = ETXTBSY;
  191                 goto fail;
  192         }
  193 
  194         if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p))
  195                 goto fail;
  196 
  197         if ((vp->v_mount->mnt_flag & MNT_NOEXEC)
  198             || ((attr.va_mode & 0111) == 0)
  199             || (attr.va_type != VREG))
  200                 goto fail;
  201 
  202         if (attr.va_size == 0) {
  203                 error = ENOEXEC;
  204                 goto fail;
  205         }
  206 
  207         if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p))
  208                 goto fail;
  209 
  210         if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p))
  211                 goto fail;
  212 
  213         /*
  214          * Lose the lock on the vnode. It's no longer needed, and must not
  215          * exist for the pagefault paging to work below.
  216          */
  217         VOP_UNLOCK(vp);
  218 
  219         if (error = vm_mmap(kernel_map,
  220                             (vm_offset_t *) &ptr,
  221                             PAGE_SIZE,
  222                             VM_PROT_READ,
  223                             VM_PROT_READ,
  224                             0,
  225                             (caddr_t) vp,
  226                             0))
  227         goto fail;
  228 
  229         fhdr = (struct filehdr *)ptr;
  230 
  231         if (fhdr->f_magic != I386_COFF) {
  232                 error = ENOEXEC;
  233                 goto dealloc_and_fail;
  234         }
  235 
  236         nscns = fhdr->f_nscns;
  237 
  238         if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) {
  239                 /*
  240                  * XXX -- just fail.  I'm so lazy.
  241                  */
  242                 error = ENOEXEC;
  243                 goto dealloc_and_fail;
  244         }
  245 
  246         ahdr = (struct aouthdr*)(ptr + sizeof(struct filehdr));
  247 
  248         scns = (struct scnhdr*)(ptr + sizeof(struct filehdr)
  249                           + sizeof(struct aouthdr));
  250 
  251         for (i = 0; i < nscns; i++) {
  252                 if (scns[i].s_flags & STYP_NOLOAD)
  253                         continue;
  254                 else if (scns[i].s_flags & STYP_TEXT) {
  255                         text_address = scns[i].s_vaddr;
  256                         text_size = scns[i].s_size;
  257                         text_offset = scns[i].s_scnptr;
  258                 }
  259                 else if (scns[i].s_flags & STYP_DATA) {
  260                         data_address = scns[i].s_vaddr;
  261                         data_size = scns[i].s_size;
  262                         data_offset = scns[i].s_scnptr;
  263                 } else if (scns[i].s_flags & STYP_BSS) {
  264                         bss_size = scns[i].s_size;
  265                 }
  266         }
  267 
  268         if (error = load_coff_section(vmspace, vp, text_offset,
  269                                       (caddr_t)text_address,
  270                                       text_size, text_size,
  271                                       VM_PROT_READ | VM_PROT_EXECUTE)) {
  272                 goto dealloc_and_fail;
  273         }
  274         if (error = load_coff_section(vmspace, vp, data_offset,
  275                                       (caddr_t)data_address,
  276                                       data_size + bss_size, data_size,
  277                                       VM_PROT_ALL)) {
  278                 goto dealloc_and_fail;
  279         }
  280 
  281         error = 0;
  282 
  283         dealloc_and_fail:
  284         if (vm_map_remove(kernel_map,
  285                           (vm_offset_t) ptr,
  286                           (vm_offset_t) ptr + PAGE_SIZE))
  287                 panic(__FUNCTION__ " vm_map_remove failed");
  288 
  289  fail:
  290         vput(nd.ni_vp);
  291         FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
  292         return error;
  293 }
  294 
  295 int
  296 exec_coff_imgact(imgp)
  297         struct image_params *imgp;
  298 {
  299         const struct filehdr *fhdr = (const struct filehdr*)imgp->image_header;
  300         const struct aouthdr *ahdr;
  301         const struct scnhdr *scns;
  302         int i;
  303         struct vmspace *vmspace = imgp->proc->p_vmspace;
  304         int nscns;
  305         int error;
  306         unsigned long text_offset = 0, text_address = 0, text_size = 0;
  307         unsigned long data_offset = 0, data_address = 0, data_size = 0;
  308         unsigned long bss_size = 0;
  309         caddr_t hole;
  310 
  311         if (fhdr->f_magic != I386_COFF ||
  312             !(fhdr->f_flags & F_EXEC)) {
  313 
  314                  DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__));
  315                  return -1;
  316         }
  317 
  318         nscns = fhdr->f_nscns;
  319         if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) {
  320                 /*
  321                  * For now, return an error -- need to be able to
  322                  * read in all of the section structures.
  323                  */
  324 
  325                 DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__));
  326                 return -1;
  327         }
  328 
  329         ahdr = (const struct aouthdr*)
  330                ((const char*)(imgp->image_header) + sizeof(struct filehdr));
  331         imgp->entry_addr = ahdr->entry;
  332 
  333         scns = (const struct scnhdr*)
  334                ((const char*)(imgp->image_header) + sizeof(struct filehdr) +
  335                 sizeof(struct aouthdr));
  336 
  337         if (error = exec_extract_strings(imgp)) {
  338                 DPRINTF(("%s(%d):  return %d\n", __FILE__, __LINE__, error));
  339                 return error;
  340         }
  341 
  342         exec_new_vmspace(imgp);
  343 
  344         for (i = 0; i < nscns; i++) {
  345 
  346           DPRINTF(("i = %d, scns[i].s_name = %s, scns[i].s_vaddr = %08lx, "
  347                    "scns[i].s_scnptr = %d\n", i, scns[i].s_name,
  348                    scns[i].s_vaddr, scns[i].s_scnptr));
  349           if (scns[i].s_flags & STYP_NOLOAD) {
  350                 /*
  351                  * A section that is not loaded, for whatever
  352                  * reason.  It takes precedance over other flag
  353                  * bits...
  354                  */
  355                 continue;
  356           } else if (scns[i].s_flags & STYP_TEXT) {
  357                 text_address = scns[i].s_vaddr;
  358                 text_size = scns[i].s_size;
  359                 text_offset = scns[i].s_scnptr;
  360           } else if (scns[i].s_flags & STYP_DATA) {
  361                 /* .data section */
  362                 data_address = scns[i].s_vaddr;
  363                 data_size = scns[i].s_size;
  364                 data_offset = scns[i].s_scnptr;
  365           } else if (scns[i].s_flags & STYP_BSS) {
  366                 /* .bss section */
  367                 bss_size = scns[i].s_size;
  368           } else if (scns[i].s_flags & STYP_LIB) {
  369                 char *buf = 0;
  370                 int foff = trunc_page(scns[i].s_scnptr);
  371                 int off = scns[i].s_scnptr - foff;
  372                 int len = round_page(scns[i].s_size + PAGE_SIZE);
  373                 int j;
  374 
  375                 if (error = vm_mmap(kernel_map,
  376                                     (vm_offset_t *) &buf,
  377                                     len,
  378                                     VM_PROT_READ,
  379                                     VM_PROT_READ,
  380                                     0,
  381                                     (caddr_t) imgp->vp,
  382                                     foff)) {
  383                         return ENOEXEC;
  384                 }
  385                 if(scns[i].s_size) {
  386                         char *libbuf;
  387                         int emul_path_len = strlen(ibcs2_emul_path);
  388 
  389                         libbuf = malloc(MAXPATHLEN + emul_path_len,
  390                                         M_TEMP, M_WAITOK);
  391                         strcpy(libbuf, ibcs2_emul_path);
  392 
  393                         for (j = off; j < scns[i].s_size + off; j++) {
  394                                 char *libname;
  395 
  396                                 libname = buf + j + 4 * *(long*)(buf + j + 4);
  397                                 j += 4* *(long*)(buf + j);
  398 
  399                                 DPRINTF(("%s(%d):  shared library %s\n",
  400                                          __FILE__, __LINE__, libname));
  401                                 strcpy(&libbuf[emul_path_len], libname);
  402                                 error = coff_load_file(imgp->proc, libbuf);
  403                                 if (error)
  404                                         error = coff_load_file(imgp->proc,
  405                                                                libname);
  406                                 if (error)
  407                                         break;
  408                         }
  409                         free(libbuf, M_TEMP);
  410                 }
  411                 if (vm_map_remove(kernel_map,
  412                                   (vm_offset_t) buf,
  413                                   (vm_offset_t) buf + len))
  414                         panic("exec_coff_imgact vm_map_remove failed");
  415                 if (error)
  416                         return error;
  417                 }
  418         }
  419         /*
  420          * Map in .text now
  421          */
  422 
  423         DPRINTF(("%s(%d):  load_coff_section(vmspace, "
  424                 "imgp->vp, %08lx, %08lx, 0x%x, 0x%x, 0x%x)\n",
  425                 __FILE__, __LINE__, text_offset, text_address,
  426                 text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE));
  427         if (error = load_coff_section(vmspace, imgp->vp,
  428                                       text_offset, (caddr_t)text_address,
  429                                       text_size, text_size,
  430                                       VM_PROT_READ | VM_PROT_EXECUTE)) {
  431                 DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error));
  432                 return error;
  433         }
  434         /*
  435          * Map in .data and .bss now
  436          */
  437 
  438 
  439         DPRINTF(("%s(%d): load_coff_section(vmspace, "
  440                 "imgp->vp, 0x%08lx, 0x%08lx, 0x%x, 0x%x, 0x%x)\n",
  441                 __FILE__, __LINE__, data_offset, data_address,
  442                 data_size + bss_size, data_size, VM_PROT_ALL));
  443         if (error = load_coff_section(vmspace, imgp->vp,
  444                                       data_offset, (caddr_t)data_address,
  445                                       data_size + bss_size, data_size,
  446                                       VM_PROT_ALL)) {
  447 
  448                 DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error));
  449                 return error;
  450         }
  451 
  452         imgp->interpreted = 0;
  453         imgp->proc->p_sysent = &ibcs2_svr3_sysvec;
  454 
  455         vmspace->vm_tsize = round_page(text_size) >> PAGE_SHIFT;
  456         vmspace->vm_dsize = round_page(data_size + bss_size) >> PAGE_SHIFT;
  457         vmspace->vm_taddr = (caddr_t)text_address;
  458         vmspace->vm_daddr = (caddr_t)data_address;
  459 
  460         hole = (caddr_t)trunc_page(vmspace->vm_daddr) + ctob(vmspace->vm_dsize);
  461 
  462 
  463         DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n",
  464                 __FILE__, __LINE__, hole));
  465         DPRINTF(("imgact: error = %d\n", error));
  466 
  467         error = vm_map_find(&vmspace->vm_map, NULL, 0,
  468                             (vm_offset_t *) &hole, PAGE_SIZE, FALSE,
  469                                 VM_PROT_ALL, VM_PROT_ALL, 0);
  470 
  471         DPRINTF(("IBCS2: start vm_dsize = 0x%x, vm_daddr = 0x%x end = 0x%x\n",
  472                 ctob(vmspace->vm_dsize), vmspace->vm_daddr,
  473                 ctob(vmspace->vm_dsize) + vmspace->vm_daddr ));
  474         DPRINTF(("%s(%d):  returning successfully!\n", __FILE__, __LINE__));
  475 
  476         /* Indicate that this file should not be modified */
  477         imgp->vp->v_flag |= VTEXT;
  478         return 0;
  479 }
  480 
  481 /*
  482  * Tell kern_execve.c about it, with a little help from the linker.
  483  * Since `const' objects end up in the text segment, TEXT_SET is the
  484  * correct directive to use.
  485  */
  486 const struct execsw coff_execsw = { exec_coff_imgact, "coff" };
  487 TEXT_SET(execsw_set, coff_execsw);

Cache object: 88fcc5bad9a984ae4b3008f6e0fd7453


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