1 /* $NetBSD: ibcs2_exec.c,v 1.76 2012/02/19 21:06:37 rmind Exp $ */
2
3 /*
4 * Copyright (c) 1994, 1995, 1998 Scott Bartram
5 * Copyright (c) 1994 Adam Glass
6 * Copyright (c) 1993, 1994 Christopher G. Demetriou
7 * All rights reserved.
8 *
9 * originally from kern/exec_ecoff.c
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Scott Bartram.
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: ibcs2_exec.c,v 1.76 2012/02/19 21:06:37 rmind Exp $");
39
40 #if defined(_KERNEL_OPT)
41 #include "opt_syscall_debug.h"
42 #endif
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/proc.h>
48 #include <sys/malloc.h>
49 #include <sys/namei.h>
50 #include <sys/vnode.h>
51 #include <sys/mount.h>
52 #include <sys/exec.h>
53
54 #include <uvm/uvm_extern.h>
55
56 #include <machine/ibcs2_machdep.h>
57
58 #include <compat/ibcs2/ibcs2_types.h>
59 #include <compat/ibcs2/ibcs2_exec.h>
60 #include <compat/ibcs2/ibcs2_signal.h>
61 #include <compat/ibcs2/ibcs2_errno.h>
62 #include <compat/ibcs2/ibcs2_syscall.h>
63
64 static void ibcs2_e_proc_exec(struct proc *, struct exec_package *);
65
66 extern struct sysent ibcs2_sysent[];
67 extern const char * const ibcs2_syscallnames[];
68 extern char ibcs2_sigcode[], ibcs2_esigcode[];
69 #ifndef __HAVE_SYSCALL_INTERN
70 void syscall(void);
71 #endif
72
73 #ifdef DEBUG_IBCS2
74 int ibcs2_debug = 1;
75 #endif
76
77 struct uvm_object *emul_ibcs2_object;
78
79 struct emul emul_ibcs2 = {
80 .e_name = "ibcs2",
81 .e_path = "/emul/ibcs2",
82 #ifndef __HAVE_MINIMAL_EMUL
83 .e_flags = 0,
84 .e_errno = native_to_ibcs2_errno,
85 .e_nosys = IBCS2_SYS_syscall,
86 .e_nsysent = IBCS2_SYS_NSYSENT,
87 #endif
88 .e_sysent = ibcs2_sysent,
89 #ifdef SYSCALL_DEBUG
90 .e_syscallnames = ibcs2_syscallnames,
91 #else
92 .e_syscallnames = NULL,
93 #endif
94 .e_sendsig = ibcs2_sendsig,
95 .e_trapsignal = trapsignal,
96 .e_tracesig = NULL,
97 .e_sigcode = ibcs2_sigcode,
98 .e_esigcode = ibcs2_esigcode,
99 .e_sigobject = &emul_ibcs2_object,
100 .e_setregs = ibcs2_setregs,
101 .e_proc_exec = ibcs2_e_proc_exec,
102 .e_proc_fork = NULL,
103 .e_proc_exit = NULL,
104 .e_lwp_fork = NULL,
105 .e_lwp_exit = NULL,
106 #ifdef __HAVE_SYSCALL_INTERN
107 .e_syscall_intern = ibcs2_syscall_intern,
108 #else
109 .e_syscall_intern = syscall,
110 #endif
111 .e_sysctlovly = NULL,
112 .e_fault = NULL,
113 .e_vm_default_addr = uvm_default_mapaddr,
114 .e_usertrap = NULL,
115 .e_ucsize = 0,
116 .e_startlwp = NULL
117 };
118
119 /*
120 * This is exec process hook. Find out if this is x.out executable, if
121 * yes, set flag appropriately, so that emul code which needs to adjust
122 * behaviour accordingly can do so.
123 */
124 static void
ibcs2_e_proc_exec(struct proc * p,struct exec_package * epp)125 ibcs2_e_proc_exec(struct proc *p, struct exec_package *epp)
126 {
127 if (epp->ep_esch->es_makecmds == exec_ibcs2_xout_makecmds)
128 p->p_emuldata = IBCS2_EXEC_XENIX;
129 else
130 p->p_emuldata = IBCS2_EXEC_OTHER;
131 }
132
133 /*
134 * ibcs2_exec_setup_stack(): Set up the stack segment for an
135 * executable.
136 *
137 * Note that the ep_ssize parameter must be set to be the current stack
138 * limit; this is adjusted in the body of execve() to yield the
139 * appropriate stack segment usage once the argument length is
140 * calculated.
141 *
142 * This function returns an int for uniformity with other (future) formats'
143 * stack setup functions. They might have errors to return.
144 */
145
146 int
ibcs2_exec_setup_stack(struct lwp * l,struct exec_package * epp)147 ibcs2_exec_setup_stack(struct lwp *l, struct exec_package *epp)
148 {
149 u_long max_stack_size;
150 u_long access_linear_min, access_size;
151 u_long noaccess_linear_min, noaccess_size;
152
153 #ifndef USRSTACK32
154 #define USRSTACK32 (0x00000000ffffffffL&~PGOFSET)
155 #endif
156
157 if (epp->ep_flags & EXEC_32) {
158 epp->ep_minsaddr = USRSTACK32;
159 max_stack_size = MAXSSIZ;
160 } else {
161 epp->ep_minsaddr = USRSTACK;
162 max_stack_size = MAXSSIZ;
163 }
164 epp->ep_maxsaddr = (u_long)STACK_GROW(epp->ep_minsaddr,
165 max_stack_size);
166 epp->ep_ssize = l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur;
167
168 /*
169 * set up commands for stack. note that this takes *two*, one to
170 * map the part of the stack which we can access, and one to map
171 * the part which we can't.
172 *
173 * arguably, it could be made into one, but that would require the
174 * addition of another mapping proc, which is unnecessary
175 */
176 access_size = epp->ep_ssize;
177 access_linear_min = (u_long)STACK_ALLOC(epp->ep_minsaddr, access_size);
178 noaccess_size = max_stack_size - access_size;
179 noaccess_linear_min = (u_long)STACK_ALLOC(STACK_GROW(epp->ep_minsaddr,
180 access_size), noaccess_size);
181 if (noaccess_size > 0) {
182 NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, noaccess_size,
183 noaccess_linear_min, NULL, 0, VM_PROT_NONE, VMCMD_STACK);
184 }
185 KASSERT(access_size > 0);
186 /* XXX: some ibcs2 binaries need an executable stack. */
187 NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, access_size,
188 access_linear_min, NULL, 0, VM_PROT_READ | VM_PROT_WRITE |
189 VM_PROT_EXECUTE, VMCMD_STACK);
190
191 return 0;
192 }
193