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/darwin/darwin_mman.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 #undef DEBUG_DARWIN
    2 #undef DEBUG_MACH
    3 /*      $NetBSD: darwin_mman.c,v 1.29 2008/04/28 20:23:41 martin Exp $ */
    4 
    5 /*-
    6  * Copyright (c) 2002, 2008 The NetBSD Foundation, Inc.
    7  * All rights reserved.
    8  *
    9  * This code is derived from software contributed to The NetBSD Foundation
   10  * by Emmanuel Dreyfus.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31  * POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: darwin_mman.c,v 1.29 2008/04/28 20:23:41 martin Exp $");
   36 
   37 #include <sys/types.h>
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/malloc.h>
   41 #include <sys/signal.h>
   42 #include <sys/mount.h>
   43 #include <sys/proc.h>
   44 #include <sys/fcntl.h>
   45 #include <sys/file.h>
   46 #include <sys/filedesc.h>
   47 #include <sys/vnode.h>
   48 #include <sys/exec.h>
   49 
   50 #include <sys/syscallargs.h>
   51 
   52 #include <compat/sys/signal.h>
   53 
   54 #include <compat/mach/mach_types.h>
   55 #include <compat/mach/mach_vm.h>
   56 
   57 #include <compat/darwin/darwin_audit.h>
   58 #include <compat/darwin/darwin_syscallargs.h>
   59 
   60 int
   61 darwin_sys_load_shared_file(struct lwp *l, const struct darwin_sys_load_shared_file_args *uap, register_t *retval)
   62 {
   63         /* {
   64                 syscallarg(char *) filename;
   65                 syscallarg(void *) addr;
   66                 syscallarg(u_long) len;
   67                 syscallarg(void **) base;
   68                 syscallarg(int) count:
   69                 syscallarg(mach_sf_mapping_t *) mappings;
   70                 syscallarg(int *) flags;
   71         } */
   72         struct file *fp;
   73         struct vnode *vp = NULL;
   74         vaddr_t base;
   75         struct proc *p = l->l_proc;
   76         int flags;
   77         char *filename;
   78         mach_sf_mapping_t *mapp = NULL;
   79         size_t maplen;
   80         struct sys_open_args open_cup;
   81         struct sys_close_args close_cup;
   82         register_t fdc;
   83         int fd;
   84         int i;
   85         int error;
   86         vaddr_t max_addr, addr;
   87         size_t len;
   88         vaddr_t uaddr;
   89         int need_relocation;
   90         struct exec_vmcmd evc;
   91 
   92         filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
   93         if ((error = copyin(SCARG(uap, filename), filename, MAXPATHLEN)) != 0)
   94                 goto bad1;
   95 
   96         if ((error = copyin(SCARG(uap, base), &base, sizeof(base))) != 0)
   97                 goto bad1;
   98 
   99         if ((error = copyin(SCARG(uap, flags), &flags, sizeof(base))) != 0)
  100                 goto bad1;
  101 
  102 #ifdef DEBUG_DARWIN
  103         DPRINTF(("darwin_sys_load_shared_file: filename = %p ",
  104             SCARG(uap, filename)));
  105         DPRINTF(("addr = %p len = 0x%08lx base = %p ",
  106             SCARG(uap, addr), SCARG(uap, len), SCARG(uap, base)));
  107         DPRINTF(("count = %d mappings = %p flags = %p ",
  108             SCARG(uap, count), SCARG(uap, mappings), SCARG(uap, flags)));
  109         DPRINTF(("*base = 0x%08lx *flags = %d filename=`%s'\n",
  110             base, flags, filename));
  111 #endif
  112 
  113         SCARG(&open_cup, path) = SCARG(uap, filename);
  114         SCARG(&open_cup, flags) = O_RDONLY;
  115         SCARG(&open_cup, mode) = 0;
  116         if ((error = sys_open(l, &open_cup, &fdc)) != 0)
  117                 goto bad1;
  118 
  119         fd = (int)fdc;
  120         fp = fd_getfile(fd);
  121         if (fp == NULL) {
  122                 error = EBADF;
  123                 goto bad1point5;
  124         }
  125         vp = fp->f_data;
  126         vref(vp);
  127 
  128         if (SCARG(uap, count) < 0 ||
  129             SCARG(uap, count) > PAGE_SIZE / sizeof(*mapp)) {
  130                 error = EINVAL;
  131                 goto bad2;
  132         }
  133         maplen = SCARG(uap, count) * sizeof(*mapp);
  134         mapp = malloc(maplen, M_TEMP, M_WAITOK);
  135 
  136         if ((error = copyin(SCARG(uap, mappings), mapp, maplen)) != 0)
  137                 goto bad2;
  138 
  139 #ifdef DEBUG_DARWIN
  140         for (i = 0; i < SCARG(uap, count); i++) {
  141                 DPRINTF(("mapp[%d].mapping_offset = 0x%08lx\n",
  142                     i, mapp[i].mapping_offset));
  143                 DPRINTF(("mapp[%d].size = 0x%08lx\n", i, (long)mapp[i].size));
  144                 DPRINTF(("mapp[%d].file_offset = 0x%08lx\n",
  145                     i, mapp[i].file_offset));
  146                 DPRINTF(("mapp[%d].protection = %d\n",
  147                     i, mapp[i].protection));
  148                 DPRINTF(("mapp[%d].cksum = %ld\n", i, mapp[i].cksum));
  149         }
  150 #endif
  151 
  152         /* Check if we can load at the default addresses */
  153         need_relocation = 0;
  154         vm_map_lock(&p->p_vmspace->vm_map);
  155         for (i = 0; i < SCARG(uap, count); i++)
  156                 if ((uvm_map_findspace(&p->p_vmspace->vm_map,
  157                     base + mapp[i].mapping_offset, mapp[i].size,
  158                     &uaddr, NULL, 0, 0, UVM_FLAG_FIXED)) == NULL)
  159                         need_relocation = 1;
  160         vm_map_unlock(&p->p_vmspace->vm_map);
  161 
  162         /* If we cannot, we need a relocation */
  163         if (need_relocation) {
  164                 DPRINTF(("Relocating\n"));
  165                 /* Compute the length of the region enclosing all sections */
  166                 max_addr = 0;
  167                 for (i = 0; i < SCARG(uap, count); i++) {
  168                         addr = (vaddr_t)(mapp[i].mapping_offset
  169                             + base + mapp[i].size);
  170                         if (addr > max_addr)
  171                                 max_addr = addr;
  172                 }
  173                 len = max_addr - base;
  174                 DPRINTF(("base = 0x%08lx max_addr = 0x%08lx len = 0x%08x\n",
  175                     base, max_addr, len));
  176 
  177                 /* Find some place to map this region */
  178                 vm_map_lock(&p->p_vmspace->vm_map);
  179                 if ((uvm_map_findspace(&p->p_vmspace->vm_map, base,
  180                     len, &uaddr, NULL, 0, PAGE_SIZE, 0)) == NULL) {
  181                         DPRINTF(("Impossible to find some space\n"));
  182                         vm_map_unlock(&p->p_vmspace->vm_map);
  183                         error = ENOMEM;
  184                         goto bad2;
  185                 }
  186                 vm_map_unlock(&p->p_vmspace->vm_map);
  187 
  188                 /* Update the base address */
  189                 base = uaddr;
  190                 DPRINTF(("New base address: base = 0x%08lx\n", base));
  191         }
  192 
  193         /* Do the actual mapping */
  194         for (i = 0; i < SCARG(uap, count); i++) {
  195                 bzero(&evc, sizeof(evc));
  196                 evc.ev_addr = base + mapp[i].mapping_offset;
  197                 evc.ev_len = mapp[i].size;
  198                 evc.ev_prot = mapp[i].protection & VM_PROT_ALL;
  199                 evc.ev_flags = 0;
  200                 if (mapp[i].protection & MACH_VM_PROT_ZF)
  201                         evc.ev_proc = vmcmd_map_zero;
  202                 else
  203                         evc.ev_proc = vmcmd_map_readvn;
  204                 evc.ev_offset = mapp[i].file_offset;
  205                 evc.ev_vp = vp;
  206 
  207                 DPRINTF(("map section %d: start = 0x%08lx, len = 0x%08lx\n",
  208                     i, evc.ev_addr, evc.ev_len));
  209 
  210                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  211                 if ((error = (*evc.ev_proc)(l, &evc)) != 0) {
  212                         VOP_UNLOCK(vp, 0);
  213                         DPRINTF(("Failed\n"));
  214                         goto bad2;
  215                 }
  216                 VOP_UNLOCK(vp, 0);
  217                 DPRINTF(("Success\n"));
  218         }
  219 bad2:
  220         if (mapp)
  221                 free(mapp, M_TEMP);
  222         vrele(vp);
  223         fd_putfile(fd);
  224 bad1point5:
  225         SCARG(&close_cup, fd) = fd;
  226         if ((error = sys_close(l, &close_cup, retval)) != 0)
  227                 goto bad1;
  228 
  229         if ((error = copyout(&base, SCARG(uap, base), sizeof(base))) != 0)
  230                 goto bad1;
  231 
  232         if ((error = copyout(&flags, SCARG(uap, flags), sizeof(base))) != 0)
  233                 goto bad1;
  234 bad1:
  235         free(filename, M_TEMP);
  236 
  237         return error;
  238 }

Cache object: b60868c37b3dd42d5646fbab93f2994a


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