1 /* $NetBSD: mach_exec.c,v 1.55.2.1 2005/09/18 20:09:49 tron 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.55.2.1 2005/09/18 20:09:49 tron 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,
121 NULL,
122
123 uvm_default_mapaddr,
124 };
125
126 /*
127 * Copy arguments onto the stack in the normal way, but add some
128 * extra information in case of dynamic binding.
129 * XXX This needs a cleanup: it is not used anymore by the Darwin
130 * emulation, and it probably contains Darwin specific bits.
131 */
132 int
133 exec_mach_copyargs(p, pack, arginfo, stackp, argp)
134 struct proc *p;
135 struct exec_package *pack;
136 struct ps_strings *arginfo;
137 char **stackp;
138 void *argp;
139 {
140 struct exec_macho_emul_arg *emea;
141 struct exec_macho_object_header *macho_hdr;
142 size_t len;
143 size_t zero = 0;
144 int error;
145
146 *stackp = (char *)(((unsigned long)*stackp - 1) & ~0xfUL);
147
148 emea = (struct exec_macho_emul_arg *)pack->ep_emul_arg;
149 macho_hdr = (struct exec_macho_object_header *)emea->macho_hdr;
150 if ((error = copyout(&macho_hdr, *stackp, sizeof(macho_hdr))) != 0)
151 return error;
152
153 *stackp += sizeof(macho_hdr);
154
155 if ((error = copyargs(p, pack, arginfo, stackp, argp)) != 0) {
156 DPRINTF(("mach: copyargs failed\n"));
157 return error;
158 }
159
160 if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0)
161 return error;
162 *stackp += sizeof(zero);
163
164 if ((error = copyoutstr(emea->filename,
165 *stackp, MAXPATHLEN, &len)) != 0) {
166 DPRINTF(("mach: copyout path failed\n"));
167 return error;
168 }
169 *stackp += len + 1;
170
171 /* We don't need this anymore */
172 free(pack->ep_emul_arg, M_EXEC);
173 pack->ep_emul_arg = NULL;
174
175 len = len % sizeof(zero);
176 if (len) {
177 if ((error = copyout(&zero, *stackp, len)) != 0)
178 return error;
179 *stackp += len;
180 }
181
182 if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0)
183 return error;
184 *stackp += sizeof(zero);
185
186 return 0;
187 }
188
189 int
190 exec_mach_probe(path)
191 char **path;
192 {
193 *path = (char *)emul_mach.e_path;
194 return 0;
195 }
196
197 void
198 mach_e_proc_exec(p, epp)
199 struct proc *p;
200 struct exec_package *epp;
201 {
202 mach_e_proc_init(p, p->p_vmspace);
203
204 if (p->p_emul != epp->ep_es->es_emul)
205 mach_e_lwp_fork(NULL, proc_representative_lwp(p));
206
207 return;
208 }
209
210 void
211 mach_e_proc_fork(p, parent, forkflags)
212 struct proc *p;
213 struct proc *parent;
214 int forkflags;
215 {
216 mach_e_proc_fork1(p, parent, 1);
217 return;
218 }
219
220 void
221 mach_e_proc_fork1(p, parent, allocate)
222 struct proc *p;
223 struct proc *parent;
224 int allocate;
225 {
226 struct mach_emuldata *med1;
227 struct mach_emuldata *med2;
228 int i;
229
230 /*
231 * For Darwin binaries, p->p_emuldata has already been
232 * allocated, no need to throw it away and allocate it again.
233 */
234 if (allocate)
235 p->p_emuldata = NULL;
236
237 /* Use parent's vmspace because our vmspace may not be set up yet */
238 mach_e_proc_init(p, parent->p_vmspace);
239
240 med1 = p->p_emuldata;
241 med2 = parent->p_emuldata;
242
243 /*
244 * Exception ports are inherited between forks,
245 * but we need to double their reference counts,
246 * since the ports are referenced by rights in the
247 * parent and in the child.
248 *
249 * XXX we need to convert all the parent's rights
250 * to the child namespace. This will make the
251 * following fixup obsolete.
252 */
253 for (i = 0; i <= MACH_EXC_MAX; i++) {
254 med1->med_exc[i] = med2->med_exc[i];
255 if (med1->med_exc[i] != NULL)
256 med1->med_exc[i]->mp_refcount *= 2;
257 }
258
259 return;
260 }
261
262 void
263 mach_e_proc_init(p, vmspace)
264 struct proc *p;
265 struct vmspace *vmspace;
266 {
267 struct mach_emuldata *med;
268 struct mach_right *mr;
269
270 /*
271 * Initialize various things if needed.
272 * XXX Not the best place for this.
273 */
274 if (mach_cold == 1)
275 mach_init();
276
277 /*
278 * For Darwin binaries, p->p_emuldata is always allocated:
279 * from the previous program if it had the same emulation,
280 * or from darwin_e_proc_exec(). In the latter situation,
281 * everything has been set to zero.
282 */
283 if (!p->p_emuldata) {
284 #ifdef DIAGNOSTIC
285 if (p->p_emul != &emul_mach)
286 printf("mach_emuldata allocated for non Mach binary\n");
287 #endif
288 p->p_emuldata = malloc(sizeof(struct mach_emuldata),
289 M_EMULDATA, M_WAITOK | M_ZERO);
290 }
291
292 med = (struct mach_emuldata *)p->p_emuldata;
293
294 /*
295 * p->p_emudata has med_inited set if we inherited it from
296 * the program that called exec(). In that situation, we
297 * must free anything that will not be used anymore.
298 */
299 if (med->med_inited != 0) {
300 lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
301 while ((mr = LIST_FIRST(&med->med_right)) != NULL)
302 mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
303 lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
304
305 /*
306 * Do not touch special ports. Some other process (eg: gdb)
307 * might have grabbed them to control the process, and the
308 * controller intend to keep in control even after exec().
309 */
310 } else {
311 /*
312 * p->p_emuldata is uninitialized. Go ahead and initialize it.
313 */
314 LIST_INIT(&med->med_right);
315 lockinit(&med->med_rightlock, PZERO|PCATCH, "mach_right", 0, 0);
316 lockinit(&med->med_exclock, PZERO, "exclock", 0, 0);
317
318 /*
319 * For debugging purpose, it's convenient to have each process
320 * using distinct port names, so we prefix the first port name
321 * by the PID. Darwin does not do that, but we can remove it
322 * when we want, it will not hurt.
323 */
324 med->med_nextright = p->p_pid << 16;
325
326 /*
327 * Initialize special ports. Bootstrap port is shared
328 * among all Mach processes in our implementation.
329 */
330 med->med_kernel = mach_port_get();
331 med->med_host = mach_port_get();
332
333 med->med_kernel->mp_flags |= MACH_MP_INKERNEL;
334 med->med_host->mp_flags |= MACH_MP_INKERNEL;
335
336 med->med_kernel->mp_data = (void *)p;
337 med->med_host->mp_data = (void *)p;
338
339 med->med_kernel->mp_datatype = MACH_MP_PROC;
340 med->med_host->mp_datatype = MACH_MP_PROC;
341
342 MACH_PORT_REF(med->med_kernel);
343 MACH_PORT_REF(med->med_host);
344
345 med->med_bootstrap = mach_bootstrap_port;
346 MACH_PORT_REF(med->med_bootstrap);
347 }
348
349 /*
350 * Exception ports are inherited accross exec() calls.
351 * If the structure is initialized, the ports are just
352 * here, so leave them untouched. If the structure is
353 * uninitalized, the ports are all set to zero, which
354 * is the default, so do not touch them either.
355 */
356
357 med->med_dirty_thid = 1;
358 med->med_suspend = 0;
359 med->med_inited = 1;
360
361 return;
362 }
363
364 void
365 mach_e_proc_exit(p)
366 struct proc *p;
367 {
368 struct mach_emuldata *med;
369 struct mach_right *mr;
370 int i;
371
372 /* There is only one lwp remaining... */
373 mach_e_lwp_exit(proc_representative_lwp(p));
374
375 med = (struct mach_emuldata *)p->p_emuldata;
376
377 lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
378 while ((mr = LIST_FIRST(&med->med_right)) != NULL)
379 mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
380 lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
381
382 MACH_PORT_UNREF(med->med_bootstrap);
383
384 /*
385 * If the lock on this task exception handler is held,
386 * release it now as it will never be released by the
387 * exception handler.
388 */
389 if (lockstatus(&med->med_exclock) != 0)
390 wakeup(&med->med_exclock);
391
392 /*
393 * If the kernel and host port are still referenced, remove
394 * the pointer to this process' struct proc, as it will
395 * become invalid once the process will exit.
396 */
397 med->med_kernel->mp_datatype = MACH_MP_NONE;
398 med->med_kernel->mp_data = NULL;
399 MACH_PORT_UNREF(med->med_kernel);
400
401 med->med_host->mp_datatype = MACH_MP_NONE;
402 med->med_host->mp_data = NULL;
403 MACH_PORT_UNREF(med->med_host);
404
405 for (i = 0; i <= MACH_EXC_MAX; i++)
406 if (med->med_exc[i] != NULL)
407 MACH_PORT_UNREF(med->med_exc[i]);
408
409 free(med, M_EMULDATA);
410 p->p_emuldata = NULL;
411
412 return;
413 }
414
415 void
416 mach_e_lwp_fork(l1, l2)
417 struct lwp *l1;
418 struct lwp *l2;
419 {
420 struct mach_lwp_emuldata *mle;
421
422 mle = malloc(sizeof(*mle), M_EMULDATA, M_WAITOK);
423 l2->l_emuldata = mle;
424
425 mle->mle_kernel = mach_port_get();
426 MACH_PORT_REF(mle->mle_kernel);
427
428 mle->mle_kernel->mp_flags |= MACH_MP_INKERNEL;
429 mle->mle_kernel->mp_datatype = MACH_MP_LWP;
430 mle->mle_kernel->mp_data = (void *)l2;
431
432 #if 0
433 /* Nothing to copy from parent thread for now */
434 if (l1 != NULL);
435 #endif
436
437 return;
438 }
439
440 void
441 mach_e_lwp_exit(l)
442 struct lwp *l;
443 {
444 struct mach_lwp_emuldata *mle;
445
446 mach_semaphore_cleanup(l);
447
448 #ifdef DIAGNOSTIC
449 if (l->l_emuldata == NULL) {
450 printf("lwp_emuldata already freed\n");
451 return;
452 }
453 #endif
454 mle = l->l_emuldata;
455
456 mle->mle_kernel->mp_data = NULL;
457 mle->mle_kernel->mp_datatype = MACH_MP_NONE;
458 MACH_PORT_UNREF(mle->mle_kernel);
459
460 free(mle, M_EMULDATA);
461 l->l_emuldata = NULL;
462
463 return;
464 }
465
466 static void
467 mach_init(void)
468 {
469 mach_semaphore_init();
470 mach_message_init();
471 mach_port_init();
472
473 mach_cold = 0;
474
475 return;
476 }
Cache object: 0473eb7c832d48b6af2a602e0a2f4e71
|