1 /* $NetBSD: mach_exec.c,v 1.61 2006/11/16 01:32:44 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas and 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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.61 2006/11/16 01:32:44 christos Exp $");
41
42 #include "opt_syscall_debug.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/proc.h>
47 #include <sys/exec.h>
48 #include <sys/queue.h>
49 #include <sys/exec_macho.h>
50 #include <sys/malloc.h>
51
52 #include <sys/syscall.h>
53
54 #include <uvm/uvm_extern.h>
55 #include <uvm/uvm_param.h>
56
57 #include <compat/mach/mach_types.h>
58 #include <compat/mach/mach_message.h>
59 #include <compat/mach/mach_port.h>
60 #include <compat/mach/mach_semaphore.h>
61 #include <compat/mach/mach_notify.h>
62 #include <compat/mach/mach_exec.h>
63
64 static int mach_cold = 1; /* Have we initialized COMPAT_MACH structures? */
65 static void mach_init(void);
66
67 extern struct sysent sysent[];
68 #ifdef SYSCALL_DEBUG
69 extern const char * const syscallnames[];
70 #endif
71 #ifndef __HAVE_SYSCALL_INTERN
72 void syscall(void);
73 #else
74 void mach_syscall_intern(struct proc *);
75 #endif
76
77 #ifdef COMPAT_16
78 extern char sigcode[], esigcode[];
79 struct uvm_object *emul_mach_object;
80 #endif
81
82 const struct emul emul_mach = {
83 "mach",
84 "/emul/mach",
85 #ifndef __HAVE_MINIMAL_EMUL
86 0,
87 0,
88 SYS_syscall,
89 SYS_NSYSENT,
90 #endif
91 sysent,
92 #ifdef SYSCALL_DEBUG
93 syscallnames,
94 #else
95 NULL,
96 #endif
97 sendsig,
98 mach_trapsignal,
99 NULL,
100 #ifdef COMPAT_16
101 sigcode,
102 esigcode,
103 &emul_mach_object,
104 #else
105 NULL,
106 NULL,
107 NULL,
108 #endif
109 setregs,
110 mach_e_proc_exec,
111 mach_e_proc_fork,
112 mach_e_proc_exit,
113 mach_e_lwp_fork,
114 mach_e_lwp_exit,
115 #ifdef __HAVE_SYSCALL_INTERN
116 mach_syscall_intern,
117 #else
118 syscall,
119 #endif
120 NULL, /* e_fault */
121 NULL, /* e_vm_default_addr */
122
123 uvm_default_mapaddr,
124 NULL, /* e_usertrap */
125 NULL, /* e_sa */
126 };
127
128 /*
129 * Copy arguments onto the stack in the normal way, but add some
130 * extra information in case of dynamic binding.
131 * XXX This needs a cleanup: it is not used anymore by the Darwin
132 * emulation, and it probably contains Darwin specific bits.
133 */
134 int
135 exec_mach_copyargs(l, pack, arginfo, stackp, argp)
136 struct lwp *l;
137 struct exec_package *pack;
138 struct ps_strings *arginfo;
139 char **stackp;
140 void *argp;
141 {
142 struct exec_macho_emul_arg *emea;
143 struct exec_macho_object_header *macho_hdr;
144 size_t len;
145 size_t zero = 0;
146 int error;
147
148 *stackp = (char *)(((unsigned long)*stackp - 1) & ~0xfUL);
149
150 emea = (struct exec_macho_emul_arg *)pack->ep_emul_arg;
151 macho_hdr = (struct exec_macho_object_header *)emea->macho_hdr;
152 if ((error = copyout(&macho_hdr, *stackp, sizeof(macho_hdr))) != 0)
153 return error;
154
155 *stackp += sizeof(macho_hdr);
156
157 if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) {
158 DPRINTF(("mach: copyargs failed\n"));
159 return error;
160 }
161
162 if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0)
163 return error;
164 *stackp += sizeof(zero);
165
166 if ((error = copyoutstr(emea->filename,
167 *stackp, MAXPATHLEN, &len)) != 0) {
168 DPRINTF(("mach: copyout path failed\n"));
169 return error;
170 }
171 *stackp += len + 1;
172
173 /* We don't need this anymore */
174 free(pack->ep_emul_arg, M_EXEC);
175 pack->ep_emul_arg = NULL;
176
177 len = len % sizeof(zero);
178 if (len) {
179 if ((error = copyout(&zero, *stackp, len)) != 0)
180 return error;
181 *stackp += len;
182 }
183
184 if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0)
185 return error;
186 *stackp += sizeof(zero);
187
188 return 0;
189 }
190
191 int
192 exec_mach_probe(path)
193 const char **path;
194 {
195 *path = emul_mach.e_path;
196 return 0;
197 }
198
199 void
200 mach_e_proc_exec(p, epp)
201 struct proc *p;
202 struct exec_package *epp;
203 {
204 mach_e_proc_init(p, p->p_vmspace);
205
206 if (p->p_emul != epp->ep_es->es_emul)
207 mach_e_lwp_fork(NULL, proc_representative_lwp(p));
208
209 return;
210 }
211
212 void
213 mach_e_proc_fork(struct proc *p, struct proc *parent, int forkflags)
214 {
215 mach_e_proc_fork1(p, parent, 1);
216 return;
217 }
218
219 void
220 mach_e_proc_fork1(p, parent, allocate)
221 struct proc *p;
222 struct proc *parent;
223 int allocate;
224 {
225 struct mach_emuldata *med1;
226 struct mach_emuldata *med2;
227 int i;
228
229 /*
230 * For Darwin binaries, p->p_emuldata has already been
231 * allocated, no need to throw it away and allocate it again.
232 */
233 if (allocate)
234 p->p_emuldata = NULL;
235
236 /* Use parent's vmspace because our vmspace may not be set up yet */
237 mach_e_proc_init(p, parent->p_vmspace);
238
239 med1 = p->p_emuldata;
240 med2 = parent->p_emuldata;
241
242 /*
243 * Exception ports are inherited between forks,
244 * but we need to double their reference counts,
245 * since the ports are referenced by rights in the
246 * parent and in the child.
247 *
248 * XXX we need to convert all the parent's rights
249 * to the child namespace. This will make the
250 * following fixup obsolete.
251 */
252 for (i = 0; i <= MACH_EXC_MAX; i++) {
253 med1->med_exc[i] = med2->med_exc[i];
254 if (med1->med_exc[i] != NULL)
255 med1->med_exc[i]->mp_refcount *= 2;
256 }
257
258 return;
259 }
260
261 void
262 mach_e_proc_init(struct proc *p, struct vmspace *vmspace)
263 {
264 struct mach_emuldata *med;
265 struct mach_right *mr;
266
267 /*
268 * Initialize various things if needed.
269 * XXX Not the best place for this.
270 */
271 if (mach_cold == 1)
272 mach_init();
273
274 /*
275 * For Darwin binaries, p->p_emuldata is always allocated:
276 * from the previous program if it had the same emulation,
277 * or from darwin_e_proc_exec(). In the latter situation,
278 * everything has been set to zero.
279 */
280 if (!p->p_emuldata) {
281 #ifdef DIAGNOSTIC
282 if (p->p_emul != &emul_mach)
283 printf("mach_emuldata allocated for non Mach binary\n");
284 #endif
285 p->p_emuldata = malloc(sizeof(struct mach_emuldata),
286 M_EMULDATA, M_WAITOK | M_ZERO);
287 }
288
289 med = (struct mach_emuldata *)p->p_emuldata;
290
291 /*
292 * p->p_emudata has med_inited set if we inherited it from
293 * the program that called exec(). In that situation, we
294 * must free anything that will not be used anymore.
295 */
296 if (med->med_inited != 0) {
297 lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
298 while ((mr = LIST_FIRST(&med->med_right)) != NULL)
299 mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
300 lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
301
302 /*
303 * Do not touch special ports. Some other process (eg: gdb)
304 * might have grabbed them to control the process, and the
305 * controller intend to keep in control even after exec().
306 */
307 } else {
308 /*
309 * p->p_emuldata is uninitialized. Go ahead and initialize it.
310 */
311 LIST_INIT(&med->med_right);
312 lockinit(&med->med_rightlock, PZERO|PCATCH, "mach_right", 0, 0);
313 lockinit(&med->med_exclock, PZERO, "exclock", 0, 0);
314
315 /*
316 * For debugging purpose, it's convenient to have each process
317 * using distinct port names, so we prefix the first port name
318 * by the PID. Darwin does not do that, but we can remove it
319 * when we want, it will not hurt.
320 */
321 med->med_nextright = p->p_pid << 16;
322
323 /*
324 * Initialize special ports. Bootstrap port is shared
325 * among all Mach processes in our implementation.
326 */
327 med->med_kernel = mach_port_get();
328 med->med_host = mach_port_get();
329
330 med->med_kernel->mp_flags |= MACH_MP_INKERNEL;
331 med->med_host->mp_flags |= MACH_MP_INKERNEL;
332
333 med->med_kernel->mp_data = (void *)p;
334 med->med_host->mp_data = (void *)p;
335
336 med->med_kernel->mp_datatype = MACH_MP_PROC;
337 med->med_host->mp_datatype = MACH_MP_PROC;
338
339 MACH_PORT_REF(med->med_kernel);
340 MACH_PORT_REF(med->med_host);
341
342 med->med_bootstrap = mach_bootstrap_port;
343 MACH_PORT_REF(med->med_bootstrap);
344 }
345
346 /*
347 * Exception ports are inherited accross exec() calls.
348 * If the structure is initialized, the ports are just
349 * here, so leave them untouched. If the structure is
350 * uninitalized, the ports are all set to zero, which
351 * is the default, so do not touch them either.
352 */
353
354 med->med_dirty_thid = 1;
355 med->med_suspend = 0;
356 med->med_inited = 1;
357
358 return;
359 }
360
361 void
362 mach_e_proc_exit(p)
363 struct proc *p;
364 {
365 struct mach_emuldata *med;
366 struct mach_right *mr;
367 int i;
368
369 /* There is only one lwp remaining... */
370 mach_e_lwp_exit(proc_representative_lwp(p));
371
372 med = (struct mach_emuldata *)p->p_emuldata;
373
374 lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
375 while ((mr = LIST_FIRST(&med->med_right)) != NULL)
376 mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
377 lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
378
379 MACH_PORT_UNREF(med->med_bootstrap);
380
381 /*
382 * If the lock on this task exception handler is held,
383 * release it now as it will never be released by the
384 * exception handler.
385 */
386 if (lockstatus(&med->med_exclock) != 0)
387 wakeup(&med->med_exclock);
388
389 /*
390 * If the kernel and host port are still referenced, remove
391 * the pointer to this process' struct proc, as it will
392 * become invalid once the process will exit.
393 */
394 med->med_kernel->mp_datatype = MACH_MP_NONE;
395 med->med_kernel->mp_data = NULL;
396 MACH_PORT_UNREF(med->med_kernel);
397
398 med->med_host->mp_datatype = MACH_MP_NONE;
399 med->med_host->mp_data = NULL;
400 MACH_PORT_UNREF(med->med_host);
401
402 for (i = 0; i <= MACH_EXC_MAX; i++)
403 if (med->med_exc[i] != NULL)
404 MACH_PORT_UNREF(med->med_exc[i]);
405
406 free(med, M_EMULDATA);
407 p->p_emuldata = NULL;
408
409 return;
410 }
411
412 void
413 mach_e_lwp_fork(struct lwp *l1, struct lwp *l2)
414 {
415 struct mach_lwp_emuldata *mle;
416
417 mle = malloc(sizeof(*mle), M_EMULDATA, M_WAITOK);
418 l2->l_emuldata = mle;
419
420 mle->mle_kernel = mach_port_get();
421 MACH_PORT_REF(mle->mle_kernel);
422
423 mle->mle_kernel->mp_flags |= MACH_MP_INKERNEL;
424 mle->mle_kernel->mp_datatype = MACH_MP_LWP;
425 mle->mle_kernel->mp_data = (void *)l2;
426
427 #if 0
428 /* Nothing to copy from parent thread for now */
429 if (l1 != NULL);
430 #endif
431
432 return;
433 }
434
435 void
436 mach_e_lwp_exit(l)
437 struct lwp *l;
438 {
439 struct mach_lwp_emuldata *mle;
440
441 mach_semaphore_cleanup(l);
442
443 #ifdef DIAGNOSTIC
444 if (l->l_emuldata == NULL) {
445 printf("lwp_emuldata already freed\n");
446 return;
447 }
448 #endif
449 mle = l->l_emuldata;
450
451 mle->mle_kernel->mp_data = NULL;
452 mle->mle_kernel->mp_datatype = MACH_MP_NONE;
453 MACH_PORT_UNREF(mle->mle_kernel);
454
455 free(mle, M_EMULDATA);
456 l->l_emuldata = NULL;
457
458 return;
459 }
460
461 static void
462 mach_init(void)
463 {
464 mach_semaphore_init();
465 mach_message_init();
466 mach_port_init();
467
468 mach_cold = 0;
469
470 return;
471 }
Cache object: 7bcbaf459ba8b66e4e82b08cd2807fc5
|