Sync usage with man page.
[netbsd-mini2440.git] / sys / compat / mach / mach_exec.c
blobac52507eb5659f3276f41da3ff9019f4efedb808
1 /* $NetBSD: mach_exec.c,v 1.71 2008/11/19 18:36:05 ad Exp $ */
3 /*-
4 * Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas and Emmanuel Dreyfus.
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.71 2008/11/19 18:36:05 ad Exp $");
35 #include "opt_syscall_debug.h"
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/proc.h>
40 #include <sys/exec.h>
41 #include <sys/queue.h>
42 #include <sys/exec_macho.h>
43 #include <sys/malloc.h>
45 #include <sys/syscall.h>
46 #include <sys/syscallvar.h>
48 #include <uvm/uvm_extern.h>
49 #include <uvm/uvm_param.h>
51 #include <compat/mach/mach_types.h>
52 #include <compat/mach/mach_message.h>
53 #include <compat/mach/mach_port.h>
54 #include <compat/mach/mach_semaphore.h>
55 #include <compat/mach/mach_notify.h>
56 #include <compat/mach/mach_exec.h>
58 static int mach_cold = 1; /* Have we initialized COMPAT_MACH structures? */
59 static void mach_init(void);
61 extern struct sysent sysent[];
62 #ifndef __HAVE_SYSCALL_INTERN
63 void syscall(void);
64 #else
65 void mach_syscall_intern(struct proc *);
66 #endif
68 #ifdef COMPAT_16
69 extern char sigcode[], esigcode[];
70 struct uvm_object *emul_mach_object;
71 #endif
73 struct emul emul_mach = {
74 "mach",
75 "/emul/mach",
76 #ifndef __HAVE_MINIMAL_EMUL
79 SYS_syscall,
80 SYS_NSYSENT,
81 #endif
82 sysent,
83 #ifdef SYSCALL_DEBUG
84 syscallnames,
85 #else
86 NULL,
87 #endif
88 sendsig,
89 mach_trapsignal,
90 NULL,
91 #ifdef COMPAT_16
92 sigcode,
93 esigcode,
94 &emul_mach_object,
95 #else
96 NULL,
97 NULL,
98 NULL,
99 #endif
100 setregs,
101 mach_e_proc_exec,
102 mach_e_proc_fork,
103 mach_e_proc_exit,
104 mach_e_lwp_fork,
105 mach_e_lwp_exit,
106 #ifdef __HAVE_SYSCALL_INTERN
107 mach_syscall_intern,
108 #else
109 syscall,
110 #endif
111 NULL, /* e_fault */
112 NULL, /* e_vm_default_addr */
114 uvm_default_mapaddr,
115 NULL, /* e_usertrap */
116 NULL, /* e_sa */
117 0, /* e_ucsize */
118 NULL, /* e_startlwp */
122 * Copy arguments onto the stack in the normal way, but add some
123 * extra information in case of dynamic binding.
124 * XXX This needs a cleanup: it is not used anymore by the Darwin
125 * emulation, and it probably contains Darwin specific bits.
128 exec_mach_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp)
130 struct exec_macho_emul_arg *emea;
131 struct exec_macho_object_header *macho_hdr;
132 size_t len;
133 size_t zero = 0;
134 int error;
136 *stackp = (char *)(((unsigned long)*stackp - 1) & ~0xfUL);
138 emea = (struct exec_macho_emul_arg *)pack->ep_emul_arg;
139 macho_hdr = (struct exec_macho_object_header *)emea->macho_hdr;
140 if ((error = copyout(&macho_hdr, *stackp, sizeof(macho_hdr))) != 0)
141 return error;
143 *stackp += sizeof(macho_hdr);
145 if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) {
146 DPRINTF(("mach: copyargs failed\n"));
147 return error;
150 if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0)
151 return error;
152 *stackp += sizeof(zero);
154 if ((error = copyoutstr(emea->filename,
155 *stackp, MAXPATHLEN, &len)) != 0) {
156 DPRINTF(("mach: copyout path failed\n"));
157 return error;
159 *stackp += len + 1;
161 /* We don't need this anymore */
162 free(pack->ep_emul_arg, M_TEMP);
163 pack->ep_emul_arg = NULL;
165 len = len % sizeof(zero);
166 if (len) {
167 if ((error = copyout(&zero, *stackp, len)) != 0)
168 return error;
169 *stackp += len;
172 if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0)
173 return error;
174 *stackp += sizeof(zero);
176 return 0;
180 exec_mach_probe(const char **path)
182 *path = emul_mach.e_path;
183 return 0;
186 void
187 mach_e_proc_exec(struct proc *p, struct exec_package *epp)
189 mach_e_proc_init(p, p->p_vmspace);
191 if (p->p_emul != epp->ep_esch->es_emul) {
192 struct lwp *l = LIST_FIRST(&p->p_lwps);
193 KASSERT(l != NULL);
194 mach_e_lwp_fork(NULL, l);
197 return;
200 void
201 mach_e_proc_fork(struct proc *p, struct proc *parent, int forkflags)
203 mach_e_proc_fork1(p, parent, 1);
204 return;
207 void
208 mach_e_proc_fork1(struct proc *p, struct proc *parent, int allocate)
210 struct mach_emuldata *med1;
211 struct mach_emuldata *med2;
212 int i;
215 * For Darwin binaries, p->p_emuldata has already been
216 * allocated, no need to throw it away and allocate it again.
218 if (allocate)
219 p->p_emuldata = NULL;
221 /* Use parent's vmspace because our vmspace may not be set up yet */
222 mach_e_proc_init(p, parent->p_vmspace);
224 med1 = p->p_emuldata;
225 med2 = parent->p_emuldata;
228 * Exception ports are inherited between forks,
229 * but we need to double their reference counts,
230 * since the ports are referenced by rights in the
231 * parent and in the child.
233 * XXX we need to convert all the parent's rights
234 * to the child namespace. This will make the
235 * following fixup obsolete.
237 for (i = 0; i <= MACH_EXC_MAX; i++) {
238 med1->med_exc[i] = med2->med_exc[i];
239 if (med1->med_exc[i] != NULL)
240 med1->med_exc[i]->mp_refcount *= 2;
243 return;
246 void
247 mach_e_proc_init(struct proc *p, struct vmspace *vmspace)
249 struct mach_emuldata *med;
250 struct mach_right *mr;
253 * Initialize various things if needed.
254 * XXX Not the best place for this.
256 if (mach_cold == 1)
257 mach_init();
260 * For Darwin binaries, p->p_emuldata is always allocated:
261 * from the previous program if it had the same emulation,
262 * or from darwin_e_proc_exec(). In the latter situation,
263 * everything has been set to zero.
265 if (!p->p_emuldata) {
266 #ifdef DIAGNOSTIC
267 if (p->p_emul != &emul_mach)
268 printf("mach_emuldata allocated for non Mach binary\n");
269 #endif
270 p->p_emuldata = malloc(sizeof(struct mach_emuldata),
271 M_EMULDATA, M_WAITOK | M_ZERO);
274 med = (struct mach_emuldata *)p->p_emuldata;
277 * p->p_emudata has med_inited set if we inherited it from
278 * the program that called exec(). In that situation, we
279 * must free anything that will not be used anymore.
281 if (med->med_inited != 0) {
282 rw_enter(&med->med_rightlock, RW_WRITER);
283 while ((mr = LIST_FIRST(&med->med_right)) != NULL)
284 mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
285 rw_exit(&med->med_rightlock);
288 * Do not touch special ports. Some other process (eg: gdb)
289 * might have grabbed them to control the process, and the
290 * controller intend to keep in control even after exec().
292 } else {
294 * p->p_emuldata is uninitialized. Go ahead and initialize it.
296 LIST_INIT(&med->med_right);
297 rw_init(&med->med_rightlock);
298 rw_init(&med->med_exclock);
301 * For debugging purpose, it's convenient to have each process
302 * using distinct port names, so we prefix the first port name
303 * by the PID. Darwin does not do that, but we can remove it
304 * when we want, it will not hurt.
306 med->med_nextright = p->p_pid << 16;
309 * Initialize special ports. Bootstrap port is shared
310 * among all Mach processes in our implementation.
312 med->med_kernel = mach_port_get();
313 med->med_host = mach_port_get();
315 med->med_kernel->mp_flags |= MACH_MP_INKERNEL;
316 med->med_host->mp_flags |= MACH_MP_INKERNEL;
318 med->med_kernel->mp_data = (void *)p;
319 med->med_host->mp_data = (void *)p;
321 med->med_kernel->mp_datatype = MACH_MP_PROC;
322 med->med_host->mp_datatype = MACH_MP_PROC;
324 MACH_PORT_REF(med->med_kernel);
325 MACH_PORT_REF(med->med_host);
327 med->med_bootstrap = mach_bootstrap_port;
328 MACH_PORT_REF(med->med_bootstrap);
332 * Exception ports are inherited accross exec() calls.
333 * If the structure is initialized, the ports are just
334 * here, so leave them untouched. If the structure is
335 * uninitalized, the ports are all set to zero, which
336 * is the default, so do not touch them either.
339 med->med_dirty_thid = 1;
340 med->med_suspend = 0;
341 med->med_inited = 1;
343 return;
346 void
347 mach_e_proc_exit(struct proc *p)
349 struct mach_emuldata *med;
350 struct mach_right *mr;
351 struct lwp *l;
352 int i;
354 /* There is only one lwp remaining... */
355 l = LIST_FIRST(&p->p_lwps);
356 KASSERT(l != NULL);
357 mach_e_lwp_exit(l);
359 med = (struct mach_emuldata *)p->p_emuldata;
361 rw_enter(&med->med_rightlock, RW_WRITER);
362 while ((mr = LIST_FIRST(&med->med_right)) != NULL)
363 mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
364 rw_exit(&med->med_rightlock);
366 MACH_PORT_UNREF(med->med_bootstrap);
369 * If the lock on this task exception handler is held,
370 * release it now as it will never be released by the
371 * exception handler.
373 if (rw_lock_held(&med->med_exclock))
374 wakeup(&med->med_exclock);
377 * If the kernel and host port are still referenced, remove
378 * the pointer to this process' struct proc, as it will
379 * become invalid once the process will exit.
381 med->med_kernel->mp_datatype = MACH_MP_NONE;
382 med->med_kernel->mp_data = NULL;
383 MACH_PORT_UNREF(med->med_kernel);
385 med->med_host->mp_datatype = MACH_MP_NONE;
386 med->med_host->mp_data = NULL;
387 MACH_PORT_UNREF(med->med_host);
389 for (i = 0; i <= MACH_EXC_MAX; i++)
390 if (med->med_exc[i] != NULL)
391 MACH_PORT_UNREF(med->med_exc[i]);
393 rw_destroy(&med->med_exclock);
394 rw_destroy(&med->med_rightlock);
395 free(med, M_EMULDATA);
396 p->p_emuldata = NULL;
398 return;
401 void
402 mach_e_lwp_fork(struct lwp *l1, struct lwp *l2)
404 struct mach_lwp_emuldata *mle;
406 mle = malloc(sizeof(*mle), M_EMULDATA, M_WAITOK);
407 l2->l_emuldata = mle;
409 mle->mle_kernel = mach_port_get();
410 MACH_PORT_REF(mle->mle_kernel);
412 mle->mle_kernel->mp_flags |= MACH_MP_INKERNEL;
413 mle->mle_kernel->mp_datatype = MACH_MP_LWP;
414 mle->mle_kernel->mp_data = (void *)l2;
416 #if 0
417 /* Nothing to copy from parent thread for now */
418 if (l1 != NULL);
419 #endif
421 return;
424 void
425 mach_e_lwp_exit(struct lwp *l)
427 struct mach_lwp_emuldata *mle;
429 mach_semaphore_cleanup(l);
431 #ifdef DIAGNOSTIC
432 if (l->l_emuldata == NULL) {
433 printf("lwp_emuldata already freed\n");
434 return;
436 #endif
437 mle = l->l_emuldata;
439 mle->mle_kernel->mp_data = NULL;
440 mle->mle_kernel->mp_datatype = MACH_MP_NONE;
441 MACH_PORT_UNREF(mle->mle_kernel);
443 free(mle, M_EMULDATA);
444 l->l_emuldata = NULL;
446 return;
449 static void
450 mach_init(void)
452 mach_semaphore_init();
453 mach_message_init();
454 mach_port_init();
456 mach_cold = 0;
458 return;