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