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_exec.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: darwin_exec.c,v 1.55.4.2 2009/04/01 00:27:20 snj Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Emmanuel Dreyfus.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include "opt_compat_darwin.h" /* For COMPAT_DARWIN in mach_port.h */
   33 #include <sys/cdefs.h>
   34 __KERNEL_RCSID(0, "$NetBSD: darwin_exec.c,v 1.55.4.2 2009/04/01 00:27:20 snj Exp $");
   35 
   36 #include "opt_syscall_debug.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/proc.h>
   41 #include <sys/exec.h>
   42 #include <sys/malloc.h>
   43 #include <sys/syscall.h>
   44 #include <sys/sysctl.h>
   45 #include <sys/conf.h>
   46 #include <sys/exec_macho.h>
   47 
   48 #include <uvm/uvm_extern.h>
   49 #include <uvm/uvm_param.h>
   50 
   51 #include <dev/wscons/wsconsio.h>
   52 
   53 #include <compat/sys/signal.h>
   54 
   55 #include <compat/common/compat_util.h>
   56 
   57 #include <compat/mach/mach_types.h>
   58 #include <compat/mach/mach_message.h>
   59 #include <compat/mach/mach_exec.h>
   60 #include <compat/mach/mach_port.h>
   61 
   62 #include <compat/darwin/darwin_exec.h>
   63 #include <compat/darwin/darwin_commpage.h>
   64 #include <compat/darwin/darwin_signal.h>
   65 #include <compat/darwin/darwin_syscall.h>
   66 #include <compat/darwin/darwin_sysctl.h>
   67 #include <compat/darwin/darwin_iokit.h>
   68 #include <compat/darwin/darwin_iohidsystem.h>
   69 
   70 #include <machine/darwin_machdep.h>
   71 
   72 /* Redefined from sys/dev/wscons/wsdisplay.c */
   73 extern const struct cdevsw wsdisplay_cdevsw;
   74 
   75 static void darwin_e_proc_exec(struct proc *, struct exec_package *);
   76 static void darwin_e_proc_fork(struct proc *, struct proc *, int);
   77 static void darwin_e_proc_exit(struct proc *);
   78 static void darwin_e_proc_init(struct proc *, struct vmspace *);
   79 
   80 extern struct sysent darwin_sysent[];
   81 #ifdef SYSCALL_DEBUG
   82 extern const char * const darwin_syscallnames[];
   83 #endif
   84 #ifndef __HAVE_SYSCALL_INTERN
   85 void syscall(void);
   86 #else
   87 void mach_syscall_intern(struct proc *);
   88 #endif
   89 
   90 const struct emul emul_darwin = {
   91         "darwin",
   92         "/emul/darwin",
   93 #ifndef __HAVE_MINIMAL_EMUL
   94         0,
   95         0,
   96         DARWIN_SYS_syscall,
   97         DARWIN_SYS_NSYSENT,
   98 #endif
   99         darwin_sysent,
  100 #ifdef SYSCALL_DEBUG
  101         darwin_syscallnames,
  102 #else
  103         NULL,
  104 #endif
  105         darwin_sendsig,
  106         darwin_trapsignal,
  107         darwin_tracesig,
  108         NULL,
  109         NULL,
  110         NULL,
  111         setregs,
  112         darwin_e_proc_exec,
  113         darwin_e_proc_fork,
  114         darwin_e_proc_exit,
  115         mach_e_lwp_fork,
  116         mach_e_lwp_exit,
  117 #ifdef __HAVE_SYSCALL_INTERN
  118         mach_syscall_intern,
  119 #else
  120         syscall,
  121 #endif
  122         NULL,
  123         NULL,
  124 
  125         uvm_default_mapaddr,
  126         NULL,
  127         NULL,
  128         0,
  129         NULL,
  130 };
  131 
  132 /*
  133  * Copy arguments onto the stack in the normal way, but add some
  134  * extra information in case of dynamic binding.
  135  */
  136 int
  137 exec_darwin_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp)
  138 {
  139         struct exec_macho_emul_arg *emea;
  140         struct exec_macho_object_header *macho_hdr;
  141         struct proc *p = l->l_proc;
  142         char **cpp, *dp, *sp, *progname;
  143         size_t len;
  144         void *nullp = NULL;
  145         long argc, envc;
  146         int error;
  147 
  148         /*
  149          * Prepare the comm pages
  150          */
  151         if ((error = darwin_commpage_map(p)) != 0)
  152                 return error;
  153 
  154         /*
  155          * Set up the stack
  156          */
  157         *stackp = (char *)(((unsigned long)*stackp - 1) & ~0xfUL);
  158 
  159         emea = (struct exec_macho_emul_arg *)pack->ep_emul_arg;
  160 
  161         if (emea->dynamic == 1) {
  162                 macho_hdr = (struct exec_macho_object_header *)emea->macho_hdr;
  163                 error = copyout(&macho_hdr, *stackp, sizeof(macho_hdr));
  164                 if (error != 0)
  165                         return error;
  166                 *stackp += sizeof(macho_hdr);
  167         }
  168 
  169         cpp = (char **)*stackp;
  170         argc = arginfo->ps_nargvstr;
  171         envc = arginfo->ps_nenvstr;
  172         if ((error = copyout(&argc, cpp++, sizeof(argc))) != 0)
  173                 return error;
  174 
  175         dp = (char *) (cpp + argc + envc + 4);
  176 
  177         if ((error = copyoutstr(emea->filename, dp,
  178             (ARG_MAX < MAXPATHLEN) ? ARG_MAX : MAXPATHLEN, &len)) != 0)
  179                 return error;
  180         progname = dp;
  181         dp += len;
  182 
  183         sp = argp;
  184         arginfo->ps_argvstr = cpp; /* remember location of argv for later */
  185         for (; --argc >= 0; sp += len, dp += len)
  186                 if ((error = copyout(&dp, cpp++, sizeof(dp))) != 0 ||
  187                     (error = copyoutstr(sp, dp, ARG_MAX, &len)) != 0)
  188                         return error;
  189 
  190         if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0)
  191                 return error;
  192 
  193         arginfo->ps_envstr = cpp; /* remember location of envp for later */
  194         for (; --envc >= 0; sp += len, dp += len)
  195                 if ((error = copyout(&dp, cpp++, sizeof(dp))) != 0 ||
  196                     (error = copyoutstr(sp, dp, ARG_MAX, &len)) != 0)
  197                         return error;
  198 
  199         if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0)
  200                 return error;
  201 
  202         if ((error = copyout(&progname, cpp++, sizeof(progname))) != 0)
  203                 return error;
  204 
  205         if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0)
  206                 return error;
  207 
  208         *stackp = (char *)cpp;
  209 
  210         /* We don't need this anymore */
  211         free(pack->ep_emul_arg, M_TEMP);
  212         pack->ep_emul_arg = NULL;
  213 
  214         return 0;
  215 }
  216 
  217 int
  218 exec_darwin_probe(const char **path)
  219 {
  220         *path = emul_darwin.e_path;
  221         return 0;
  222 }
  223 
  224 static void
  225 darwin_e_proc_exec(struct proc *p, struct exec_package *epp)
  226 {
  227         struct darwin_emuldata *ded;
  228 
  229         darwin_e_proc_init(p, p->p_vmspace);
  230 
  231         /* Setup the mach_emuldata part of darwin_emuldata */
  232         mach_e_proc_exec(p, epp);
  233 
  234         ded = (struct darwin_emuldata *)p->p_emuldata;
  235         if (p->p_pid == darwin_init_pid)
  236                 ded->ded_fakepid = 1;
  237 #ifdef DEBUG_DARWIN
  238         printf("pid %d exec'd: fakepid = %d\n", p->p_pid, ded->ded_fakepid);
  239 #endif
  240 
  241         return;
  242 }
  243 
  244 static void
  245 darwin_e_proc_fork(struct proc *p, struct proc *parent, int forkflags)
  246 {
  247         struct darwin_emuldata *ded1;
  248         struct darwin_emuldata *ded2;
  249         char *ed1, *ed2;
  250         size_t len;
  251 
  252         p->p_emuldata = NULL;
  253 
  254         /* Use parent's vmspace because our vmspace may not be setup yet */
  255         darwin_e_proc_init(p, parent->p_vmspace);
  256 
  257         /*
  258          * Setup the mach_emuldata part of darwin_emuldata
  259          * The null third argument asks to not re-allocate
  260          * p->p_emuldata again.
  261          */
  262         mach_e_proc_fork1(p, parent, 0);
  263 
  264         ded1 = p->p_emuldata;
  265         ded2 = parent->p_emuldata;
  266 
  267         ed1 = (char *)ded1 + sizeof(struct mach_emuldata);;
  268         ed2 = (char *)ded2 + sizeof(struct mach_emuldata);;
  269         len = sizeof(struct darwin_emuldata) - sizeof(struct mach_emuldata);
  270 
  271         (void)memcpy(ed1, ed2, len);
  272 
  273         if ((ded2->ded_fakepid == 1) && (darwin_init_pid != 0)) {
  274                 darwin_init_pid = 0;
  275                 ded1->ded_fakepid = 2;
  276         } else {
  277                 ded1->ded_fakepid = 0;
  278         }
  279 #ifdef DEBUG_DARWIN
  280         printf("pid %d fork'd: fakepid = %d\n", p->p_pid, ded1->ded_fakepid);
  281 #endif
  282 
  283         return;
  284 }
  285 
  286 static void
  287 darwin_e_proc_init(struct proc *p, struct vmspace *vmspace)
  288 {
  289         struct darwin_emuldata *ded;
  290 
  291         if (!p->p_emuldata) {
  292                 p->p_emuldata = malloc(sizeof(struct darwin_emuldata),
  293                     M_EMULDATA, M_WAITOK | M_ZERO);
  294 
  295         }
  296         ded = (struct darwin_emuldata *)p->p_emuldata;
  297         ded->ded_fakepid = 0;
  298         ded->ded_wsdev = NODEV;
  299         ded->ded_vramoffset = NULL;
  300 
  301         /* Initalize the mach_emuldata part of darwin_emuldata */
  302         mach_e_proc_init(p, vmspace);
  303 
  304         return;
  305 }
  306 
  307 static void
  308 darwin_e_proc_exit(struct proc *p)
  309 {
  310         struct darwin_emuldata *ded;
  311         int error, mode;
  312         struct lwp *l;
  313 
  314         ded = p->p_emuldata;
  315         l = LIST_FIRST(&p->p_lwps);
  316         /*
  317          * mach_init is setting the bootstrap port for other processes.
  318          * If mach_init dies, we want to restore the original bootstrap
  319          * port.
  320          */
  321         if (ded->ded_fakepid == 2)
  322                 mach_bootstrap_port = mach_saved_bootstrap_port;
  323 
  324         /*
  325          * Terminate the iohidsystem kernel thread.
  326          * We need to post a fake event in case
  327          * the thread is sleeping for an event.
  328          */
  329         if (ded->ded_hidsystem_finished != NULL) {
  330                 *ded->ded_hidsystem_finished = 1;
  331                 darwin_iohidsystem_postfake(l);
  332                 wakeup(ded->ded_hidsystem_finished);
  333         }
  334 
  335         /*
  336          * Restore text mode and black and white colormap
  337          */
  338         if (ded->ded_wsdev != NODEV) {
  339                 mode = WSDISPLAYIO_MODE_EMUL;
  340                 error = (*wsdisplay_cdevsw.d_ioctl)(ded->ded_wsdev,
  341                     WSDISPLAYIO_SMODE, (void *)&mode, 0, l);
  342 #ifdef DEBUG_DARWIN
  343                 if (error != 0)
  344                         printf("Unable to switch back to text mode\n");
  345 #endif
  346 #if 0   /* Comment out stackgap use - this needs to be done another way */
  347             {
  348                 void *sg = stackgap_init(p, 0);
  349                 struct wsdisplay_cmap cmap;
  350                 u_char *red;
  351                 u_char *green;
  352                 u_char *blue;
  353                 u_char kred[256];
  354                 u_char kgreen[256];
  355                 u_char kblue[256];
  356                 red = stackgap_alloc(p, &sg, 256);
  357                 green = stackgap_alloc(p, &sg, 256);
  358                 blue = stackgap_alloc(p, &sg, 256);
  359 
  360                 (void)memset(kred, 255, 256);
  361                 (void)memset(kgreen, 255, 256);
  362                 (void)memset(kblue, 255, 256);
  363 
  364                 kred[0] = 0;
  365                 kgreen[0] = 0;
  366                 kblue[0] = 0;
  367 
  368                 cmap.index = 0;
  369                 cmap.count = 256;
  370                 cmap.red = red;
  371                 cmap.green = green;
  372                 cmap.blue = blue;
  373 
  374                 if (((error = copyout(kred, red, 256)) != 0) ||
  375                     ((error = copyout(kgreen, green, 256)) != 0) ||
  376                     ((error = copyout(kblue, blue, 256)) != 0))
  377                         error = (*wsdisplay_cdevsw.d_ioctl)(ded->ded_wsdev,
  378                             WSDISPLAYIO_PUTCMAP, (void *)&cmap, 0, l);
  379 #ifdef DEBUG_DARWIN
  380                 if (error != 0)
  381                         printf("Cannot revert colormap (error %d)\n", error);
  382 #endif
  383             }
  384 #endif
  385 
  386         }
  387 
  388         /*
  389          * Cleanup mach_emuldata part of darwin_emuldata
  390          * It will also free p->p_emuldata.
  391          */
  392         mach_e_proc_exit(p);
  393 
  394         return;
  395 }
  396 
  397 int
  398 darwin_exec_setup_stack(struct lwp *l, struct exec_package *epp)
  399 {
  400         u_long max_stack_size;
  401         u_long access_linear_min, access_size;
  402         u_long noaccess_linear_min, noaccess_size;
  403 
  404         if (epp->ep_flags & EXEC_32) {
  405                 epp->ep_minsaddr = DARWIN_USRSTACK32;
  406                 max_stack_size = MAXSSIZ;
  407         } else {
  408                 epp->ep_minsaddr = DARWIN_USRSTACK;
  409                 max_stack_size = MAXSSIZ;
  410         }
  411         epp->ep_maxsaddr = (u_long)STACK_GROW(epp->ep_minsaddr,
  412                 max_stack_size);
  413         epp->ep_ssize = l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur;
  414 
  415         /*
  416          * set up commands for stack.  note that this takes *two*, one to
  417          * map the part of the stack which we can access, and one to map
  418          * the part which we can't.
  419          *
  420          * arguably, it could be made into one, but that would require the
  421          * addition of another mapping proc, which is unnecessary
  422          */
  423         access_size = epp->ep_ssize;
  424         access_linear_min = (u_long)STACK_ALLOC(epp->ep_minsaddr, access_size);
  425         noaccess_size = max_stack_size - access_size;
  426         noaccess_linear_min = (u_long)STACK_ALLOC(STACK_GROW(epp->ep_minsaddr,
  427             access_size), noaccess_size);
  428         if (noaccess_size > 0) {
  429                 NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, noaccess_size,
  430                     noaccess_linear_min, NULL, 0, VM_PROT_NONE, VMCMD_STACK);
  431         }
  432         KASSERT(access_size > 0);
  433         NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, access_size,
  434             access_linear_min, NULL, 0, VM_PROT_READ | VM_PROT_WRITE,
  435             VMCMD_STACK);
  436 
  437         return 0;
  438 }

Cache object: 686d14820de17637e9341a44e471f38e


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