1 /* $NetBSD: darwin_exec.c,v 1.59 2009/08/16 15:35:52 manu Exp $ */
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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 "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.59 2009/08/16 15:35:52 manu Exp $");
36 #include "opt_syscall_debug.h"
37 #include "wsdisplay.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
43 #include <sys/malloc.h>
44 #include <sys/syscall.h>
45 #include <sys/sysctl.h>
47 #include <sys/exec_macho.h>
49 #include <uvm/uvm_extern.h>
50 #include <uvm/uvm_param.h>
52 #include <dev/wscons/wsconsio.h>
54 #include <compat/sys/signal.h>
56 #include <compat/common/compat_util.h>
58 #include <compat/mach/mach_types.h>
59 #include <compat/mach/mach_message.h>
60 #include <compat/mach/mach_exec.h>
61 #include <compat/mach/mach_port.h>
63 #include <compat/darwin/darwin_exec.h>
64 #include <compat/darwin/darwin_commpage.h>
65 #include <compat/darwin/darwin_signal.h>
66 #include <compat/darwin/darwin_syscall.h>
67 #include <compat/darwin/darwin_sysctl.h>
68 #include <compat/darwin/darwin_iokit.h>
69 #include <compat/darwin/darwin_iohidsystem.h>
71 #include <machine/darwin_machdep.h>
73 #if defined(NWSDISPLAY) && NWSDISPLAY > 0
74 /* Redefined from sys/dev/wscons/wsdisplay.c */
75 extern const struct cdevsw wsdisplay_cdevsw
;
78 static void darwin_e_proc_exec(struct proc
*, struct exec_package
*);
79 static void darwin_e_proc_fork(struct proc
*, struct proc
*, int);
80 static void darwin_e_proc_exit(struct proc
*);
81 static void darwin_e_proc_init(struct proc
*, struct vmspace
*);
83 extern struct sysent darwin_sysent
[];
85 extern const char * const darwin_syscallnames
[];
87 #ifndef __HAVE_SYSCALL_INTERN
90 void mach_syscall_intern(struct proc
*);
93 struct emul emul_darwin
= {
96 #ifndef __HAVE_MINIMAL_EMUL
120 #ifdef __HAVE_SYSCALL_INTERN
136 * Copy arguments onto the stack in the normal way, but add some
137 * extra information in case of dynamic binding.
140 exec_darwin_copyargs(struct lwp
*l
, struct exec_package
*pack
, struct ps_strings
*arginfo
, char **stackp
, void *argp
)
142 struct exec_macho_emul_arg
*emea
;
143 struct exec_macho_object_header
*macho_hdr
;
144 struct proc
*p
= l
->l_proc
;
145 char **cpp
, *dp
, *sp
, *progname
;
152 * Prepare the comm pages
154 if ((error
= darwin_commpage_map(p
)) != 0)
160 *stackp
= (char *)(((unsigned long)*stackp
- 1) & ~0xfUL
);
162 emea
= (struct exec_macho_emul_arg
*)pack
->ep_emul_arg
;
164 if (emea
->dynamic
== 1) {
165 macho_hdr
= (struct exec_macho_object_header
*)emea
->macho_hdr
;
166 error
= copyout(&macho_hdr
, *stackp
, sizeof(macho_hdr
));
169 *stackp
+= sizeof(macho_hdr
);
172 cpp
= (char **)*stackp
;
173 argc
= arginfo
->ps_nargvstr
;
174 envc
= arginfo
->ps_nenvstr
;
175 if ((error
= copyout(&argc
, cpp
++, sizeof(argc
))) != 0)
178 dp
= (char *) (cpp
+ argc
+ envc
+ 4);
180 if ((error
= copyoutstr(emea
->filename
, dp
,
181 (ARG_MAX
< MAXPATHLEN
) ? ARG_MAX
: MAXPATHLEN
, &len
)) != 0)
187 arginfo
->ps_argvstr
= cpp
; /* remember location of argv for later */
188 for (; --argc
>= 0; sp
+= len
, dp
+= len
)
189 if ((error
= copyout(&dp
, cpp
++, sizeof(dp
))) != 0 ||
190 (error
= copyoutstr(sp
, dp
, ARG_MAX
, &len
)) != 0)
193 if ((error
= copyout(&nullp
, cpp
++, sizeof(nullp
))) != 0)
196 arginfo
->ps_envstr
= cpp
; /* remember location of envp for later */
197 for (; --envc
>= 0; sp
+= len
, dp
+= len
)
198 if ((error
= copyout(&dp
, cpp
++, sizeof(dp
))) != 0 ||
199 (error
= copyoutstr(sp
, dp
, ARG_MAX
, &len
)) != 0)
202 if ((error
= copyout(&nullp
, cpp
++, sizeof(nullp
))) != 0)
205 if ((error
= copyout(&progname
, cpp
++, sizeof(progname
))) != 0)
208 if ((error
= copyout(&nullp
, cpp
++, sizeof(nullp
))) != 0)
211 *stackp
= (char *)cpp
;
213 /* We don't need this anymore */
214 free(pack
->ep_emul_arg
, M_TEMP
);
215 pack
->ep_emul_arg
= NULL
;
221 exec_darwin_probe(const char **path
)
223 *path
= emul_darwin
.e_path
;
228 darwin_e_proc_exec(struct proc
*p
, struct exec_package
*epp
)
230 struct darwin_emuldata
*ded
;
232 darwin_e_proc_init(p
, p
->p_vmspace
);
234 /* Setup the mach_emuldata part of darwin_emuldata */
235 mach_e_proc_exec(p
, epp
);
237 ded
= (struct darwin_emuldata
*)p
->p_emuldata
;
238 if (p
->p_pid
== darwin_init_pid
)
239 ded
->ded_fakepid
= 1;
241 printf("pid %d exec'd: fakepid = %d\n", p
->p_pid
, ded
->ded_fakepid
);
248 darwin_e_proc_fork(struct proc
*p
, struct proc
*parent
, int forkflags
)
250 struct darwin_emuldata
*ded1
;
251 struct darwin_emuldata
*ded2
;
255 p
->p_emuldata
= NULL
;
257 /* Use parent's vmspace because our vmspace may not be setup yet */
258 darwin_e_proc_init(p
, parent
->p_vmspace
);
261 * Setup the mach_emuldata part of darwin_emuldata
262 * The null third argument asks to not re-allocate
263 * p->p_emuldata again.
265 mach_e_proc_fork1(p
, parent
, 0);
267 ded1
= p
->p_emuldata
;
268 ded2
= parent
->p_emuldata
;
270 ed1
= (char *)ded1
+ sizeof(struct mach_emuldata
);
271 ed2
= (char *)ded2
+ sizeof(struct mach_emuldata
);
272 len
= sizeof(struct darwin_emuldata
) - sizeof(struct mach_emuldata
);
274 (void)memcpy(ed1
, ed2
, len
);
276 if ((ded2
->ded_fakepid
== 1) && (darwin_init_pid
!= 0)) {
278 ded1
->ded_fakepid
= 2;
280 ded1
->ded_fakepid
= 0;
283 printf("pid %d fork'd: fakepid = %d\n", p
->p_pid
, ded1
->ded_fakepid
);
290 darwin_e_proc_init(struct proc
*p
, struct vmspace
*vmspace
)
292 struct darwin_emuldata
*ded
;
294 if (!p
->p_emuldata
) {
295 p
->p_emuldata
= malloc(sizeof(struct darwin_emuldata
),
296 M_EMULDATA
, M_WAITOK
| M_ZERO
);
299 ded
= (struct darwin_emuldata
*)p
->p_emuldata
;
300 ded
->ded_fakepid
= 0;
301 ded
->ded_wsdev
= NODEV
;
302 ded
->ded_vramoffset
= NULL
;
304 /* Initalize the mach_emuldata part of darwin_emuldata */
305 mach_e_proc_init(p
, vmspace
);
311 darwin_e_proc_exit(struct proc
*p
)
313 struct darwin_emuldata
*ded
;
317 l
= LIST_FIRST(&p
->p_lwps
);
319 * mach_init is setting the bootstrap port for other processes.
320 * If mach_init dies, we want to restore the original bootstrap
323 if (ded
->ded_fakepid
== 2)
324 mach_bootstrap_port
= mach_saved_bootstrap_port
;
327 * Terminate the iohidsystem kernel thread.
328 * We need to post a fake event in case
329 * the thread is sleeping for an event.
331 if (ded
->ded_hidsystem_finished
!= NULL
) {
332 *ded
->ded_hidsystem_finished
= 1;
333 darwin_iohidsystem_postfake(l
);
334 wakeup(ded
->ded_hidsystem_finished
);
337 #if defined(NWSDISPLAY) && NWSDISPLAY > 0
339 * Restore text mode and black and white colormap
341 if (ded
->ded_wsdev
!= NODEV
) {
344 mode
= WSDISPLAYIO_MODE_EMUL
;
345 error
= (*wsdisplay_cdevsw
.d_ioctl
)(ded
->ded_wsdev
,
346 WSDISPLAYIO_SMODE
, (void *)&mode
, 0, l
);
349 printf("Unable to switch back to text mode\n");
351 #if 0 /* Comment out stackgap use - this needs to be done another way */
353 void *sg
= stackgap_init(p
, 0);
354 struct wsdisplay_cmap cmap
;
361 red
= stackgap_alloc(p
, &sg
, 256);
362 green
= stackgap_alloc(p
, &sg
, 256);
363 blue
= stackgap_alloc(p
, &sg
, 256);
365 (void)memset(kred
, 255, 256);
366 (void)memset(kgreen
, 255, 256);
367 (void)memset(kblue
, 255, 256);
379 if (((error
= copyout(kred
, red
, 256)) != 0) ||
380 ((error
= copyout(kgreen
, green
, 256)) != 0) ||
381 ((error
= copyout(kblue
, blue
, 256)) != 0))
382 error
= (*wsdisplay_cdevsw
.d_ioctl
)(ded
->ded_wsdev
,
383 WSDISPLAYIO_PUTCMAP
, (void *)&cmap
, 0, l
);
386 printf("Cannot revert colormap (error %d)\n", error
);
391 #endif /* defined(NWSDISPLAY) && NWSDISPLAY > 0 */
394 * Cleanup mach_emuldata part of darwin_emuldata
395 * It will also free p->p_emuldata.
403 darwin_exec_setup_stack(struct lwp
*l
, struct exec_package
*epp
)
405 u_long max_stack_size
;
406 u_long access_linear_min
, access_size
;
407 u_long noaccess_linear_min
, noaccess_size
;
409 if (epp
->ep_flags
& EXEC_32
) {
410 epp
->ep_minsaddr
= DARWIN_USRSTACK32
;
411 max_stack_size
= MAXSSIZ
;
413 epp
->ep_minsaddr
= DARWIN_USRSTACK
;
414 max_stack_size
= MAXSSIZ
;
416 epp
->ep_maxsaddr
= (u_long
)STACK_GROW(epp
->ep_minsaddr
,
418 epp
->ep_ssize
= l
->l_proc
->p_rlimit
[RLIMIT_STACK
].rlim_cur
;
421 * set up commands for stack. note that this takes *two*, one to
422 * map the part of the stack which we can access, and one to map
423 * the part which we can't.
425 * arguably, it could be made into one, but that would require the
426 * addition of another mapping proc, which is unnecessary
428 access_size
= epp
->ep_ssize
;
429 access_linear_min
= (u_long
)STACK_ALLOC(epp
->ep_minsaddr
, access_size
);
430 noaccess_size
= max_stack_size
- access_size
;
431 noaccess_linear_min
= (u_long
)STACK_ALLOC(STACK_GROW(epp
->ep_minsaddr
,
432 access_size
), noaccess_size
);
433 if (noaccess_size
> 0) {
434 NEW_VMCMD2(&epp
->ep_vmcmds
, vmcmd_map_zero
, noaccess_size
,
435 noaccess_linear_min
, NULL
, 0, VM_PROT_NONE
, VMCMD_STACK
);
437 KASSERT(access_size
> 0);
438 NEW_VMCMD2(&epp
->ep_vmcmds
, vmcmd_map_zero
, access_size
,
439 access_linear_min
, NULL
, 0, VM_PROT_READ
| VM_PROT_WRITE
,