exec_ecoff.c revision 1.3.2.2 1 /* $NetBSD: exec_ecoff.c,v 1.3.2.2 1994/08/18 22:44:03 mycroft Exp $ */
2
3 /*
4 * Copyright (c) 1994 Adam Glass
5 * Copyright (c) 1993, 1994 Christopher G. Demetriou
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Christopher G. Demetriou.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/proc.h>
37 #include <sys/malloc.h>
38 #include <sys/vnode.h>
39 #include <sys/exec.h>
40 #include <sys/resourcevar.h>
41 #include <vm/vm.h>
42
43 #include <sys/exec_ecoff.h>
44
45 int exec_ecoff_prep_omagic __P((struct proc *, struct exec_package *,
46 struct ecoff_filehdr *,
47 struct ecoff_aouthdr *));
48 int exec_ecoff_prep_nmagic __P((struct proc *, struct exec_package *,
49 struct ecoff_filehdr *,
50 struct ecoff_aouthdr *));
51 int exec_ecoff_prep_zmagic __P((struct proc *, struct exec_package *,
52 struct ecoff_filehdr *,
53 struct ecoff_aouthdr *));
54 int exec_ecoff_setup_stack __P((struct proc *, struct exec_package *));
55
56 /*
57 * exec_ecoff_makecmds(): Check if it's an ecoff-format executable.
58 *
59 * Given a proc pointer and an exec package pointer, see if the referent
60 * of the epp is in ecoff format. Check 'standard' magic numbers for
61 * this architecture. If that fails, return failure.
62 *
63 * This function is responsible for creating a set of vmcmds which can be
64 * used to build the process's vm space and inserting them into the exec
65 * package.
66 */
67
68 int
69 exec_ecoff_makecmds(p, epp)
70 struct proc *p;
71 struct exec_package *epp;
72 {
73 u_long midmag, magic;
74 u_short mid;
75 int error;
76 struct ecoff_filehdr *efp = epp->ep_hdr;
77 struct ecoff_aouthdr *eap;
78
79 if (epp->ep_hdrvalid < ECOFF_HDR_SIZE)
80 return ENOEXEC;
81
82 if (ECOFF_BADMAG(efp))
83 return ENOEXEC;
84
85 eap = (struct ecoff_aouthdr *)
86 ((caddr_t)epp->ep_hdr + sizeof(struct ecoff_filehdr));
87 switch (eap->ea_magic) {
88 case ECOFF_OMAGIC:
89 error = exec_ecoff_prep_omagic(p, epp, efp, eap);
90 break;
91 case ECOFF_NMAGIC:
92 error = exec_ecoff_prep_nmagic(p, epp, efp, eap);
93 break;
94 case ECOFF_ZMAGIC:
95 error = exec_ecoff_prep_zmagic(p, epp, efp, eap);
96 break;
97 default:
98 return ENOEXEC;
99 }
100
101 if (error == 0)
102 error = cpu_exec_ecoff_hook(p, epp, eap);
103
104 if (error)
105 kill_vmcmds(&epp->ep_vmcmds);
106
107 bad:
108 return error;
109 }
110
111 /*
112 * exec_ecoff_setup_stack(): Set up the stack segment for an ecoff
113 * executable.
114 *
115 * Note that the ep_ssize parameter must be set to be the current stack
116 * limit; this is adjusted in the body of execve() to yield the
117 * appropriate stack segment usage once the argument length is
118 * calculated.
119 *
120 * This function returns an int for uniformity with other (future) formats'
121 * stack setup functions. They might have errors to return.
122 */
123
124 int
125 exec_ecoff_setup_stack(p, epp)
126 struct proc *p;
127 struct exec_package *epp;
128 {
129
130 epp->ep_maxsaddr = USRSTACK - MAXSSIZ;
131 epp->ep_minsaddr = USRSTACK;
132 epp->ep_ssize = p->p_rlimit[RLIMIT_STACK].rlim_cur;
133
134 /*
135 * set up commands for stack. note that this takes *two*, one to
136 * map the part of the stack which we can access, and one to map
137 * the part which we can't.
138 *
139 * arguably, it could be made into one, but that would require the
140 * addition of another mapping proc, which is unnecessary
141 *
142 * note that in memory, things assumed to be: 0 ....... ep_maxsaddr
143 * <stack> ep_minsaddr
144 */
145 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero,
146 ((epp->ep_minsaddr - epp->ep_ssize) - epp->ep_maxsaddr),
147 epp->ep_maxsaddr, NULLVP, 0, VM_PROT_NONE);
148 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, epp->ep_ssize,
149 (epp->ep_minsaddr - epp->ep_ssize), NULLVP, 0,
150 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
151
152 return 0;
153 }
154
155
156 /*
157 * exec_ecoff_prep_omagic(): Prepare a ECOFF OMAGIC binary's exec package
158 */
159
160 int
161 exec_ecoff_prep_omagic(p, epp, efp, eap)
162 struct proc *p;
163 struct exec_package *epp;
164 struct ecoff_filehdr *efp;
165 struct ecoff_aouthdr *eap;
166 {
167 epp->ep_taddr = ECOFF_SEGMENT_ALIGN(eap, eap->ea_text_start);
168 epp->ep_tsize = eap->ea_tsize;
169 epp->ep_daddr = ECOFF_SEGMENT_ALIGN(eap, eap->ea_data_start);
170 epp->ep_dsize = eap->ea_dsize + eap->ea_bsize;
171 epp->ep_entry = eap->ea_entry;
172
173 /* set up command for text and data segments */
174 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
175 eap->ea_tsize + eap->ea_dsize, epp->ep_taddr, epp->ep_vp,
176 ECOFF_TXTOFF(efp, eap),
177 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
178
179 /* set up command for bss segment */
180 if (eap->ea_bsize > 0)
181 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, eap->ea_bsize,
182 ECOFF_SEGMENT_ALIGN(eap, eap->ea_bss_start),
183 NULLVP, 0,
184 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
185
186 return exec_ecoff_setup_stack(p, epp);
187 }
188
189 /*
190 * exec_ecoff_prep_nmagic(): Prepare a 'native' NMAGIC ECOFF binary's exec
191 * package.
192 */
193
194 int
195 exec_ecoff_prep_nmagic(p, epp, efp, eap)
196 struct proc *p;
197 struct exec_package *epp;
198 struct ecoff_filehdr *efp;
199 struct ecoff_aouthdr *eap;
200 {
201 epp->ep_taddr = ECOFF_SEGMENT_ALIGN(eap, eap->ea_text_start);
202 epp->ep_tsize = eap->ea_tsize;
203 epp->ep_daddr = ECOFF_ROUND(eap->ea_data_start, ECOFF_LDPGSZ);
204 epp->ep_dsize = eap->ea_dsize + eap->ea_bsize;
205 epp->ep_entry = eap->ea_entry;
206
207 /* set up command for text segment */
208 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, epp->ep_tsize,
209 epp->ep_taddr, epp->ep_vp, ECOFF_TXTOFF(efp, eap),
210 VM_PROT_READ|VM_PROT_EXECUTE);
211
212 /* set up command for data segment */
213 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, epp->ep_dsize,
214 epp->ep_daddr, epp->ep_vp, ECOFF_DATOFF(efp, eap),
215 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
216
217 /* set up command for bss segment */
218 if (eap->ea_bsize > 0)
219 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, eap->ea_bsize,
220 ECOFF_SEGMENT_ALIGN(eap, eap->ea_bss_start),
221 NULLVP, 0,
222 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
223
224 return exec_ecoff_setup_stack(p, epp);
225 }
226
227 /*
228 * exec_ecoff_prep_zmagic(): Prepare a ECOFF ZMAGIC binary's exec package
229 *
230 * First, set the various offsets/lengths in the exec package.
231 *
232 * Then, mark the text image busy (so it can be demand paged) or error
233 * out if this is not possible. Finally, set up vmcmds for the
234 * text, data, bss, and stack segments.
235 */
236
237 int
238 exec_ecoff_prep_zmagic(p, epp, efp, eap)
239 struct proc *p;
240 struct exec_package *epp;
241 struct ecoff_filehdr *efp;
242 struct ecoff_aouthdr *eap;
243 {
244 epp->ep_taddr = ECOFF_SEGMENT_ALIGN(eap, eap->ea_text_start);
245 epp->ep_tsize = eap->ea_tsize;
246 epp->ep_daddr = ECOFF_SEGMENT_ALIGN(eap, eap->ea_data_start);
247 epp->ep_dsize = eap->ea_dsize + eap->ea_bsize;
248 epp->ep_entry = eap->ea_entry;
249
250 /*
251 * check if vnode is in open for writing, because we want to
252 * demand-page out of it. if it is, don't do it, for various
253 * reasons
254 */
255 if ((eap->ea_tsize != 0 || eap->ea_dsize != 0) &&
256 epp->ep_vp->v_writecount != 0) {
257 #ifdef DIAGNOSTIC
258 if (epp->ep_vp->v_flag & VTEXT)
259 panic("exec: a VTEXT vnode has writecount != 0\n");
260 #endif
261 return ETXTBSY;
262 }
263 epp->ep_vp->v_flag |= VTEXT;
264
265 /* set up command for text segment */
266 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, eap->ea_tsize,
267 epp->ep_taddr, epp->ep_vp, ECOFF_TXTOFF(efp, eap),
268 VM_PROT_READ|VM_PROT_EXECUTE);
269
270 /* set up command for data segment */
271 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, eap->ea_dsize,
272 epp->ep_daddr, epp->ep_vp,
273 ECOFF_DATOFF(efp, eap),
274 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
275
276 /* set up command for bss segment */
277 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, eap->ea_bsize,
278 ECOFF_SEGMENT_ALIGN(eap, eap->ea_bss_start), NULLVP, 0,
279 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
280
281 return exec_ecoff_setup_stack(p, epp);
282 }
283