1 /*	$OpenBSD: exec_ecoff.c,v 1.9 2001/11/15 06:22:30 art Exp $	*/
2 /*	$NetBSD: exec_ecoff.c,v 1.8 1996/05/19 20:36:06 jonathan Exp $	*/
3 
4 /*
5  * Copyright (c) 1994 Adam Glass
6  * Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Christopher G. Demetriou.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/proc.h>
38 #include <sys/malloc.h>
39 #include <sys/vnode.h>
40 #include <sys/exec.h>
41 #include <sys/resourcevar.h>
42 #include <uvm/uvm_extern.h>
43 
44 #if defined(_KERN_DO_ECOFF)
45 
46 #include <sys/exec_ecoff.h>
47 
48 /*
49  * exec_ecoff_makecmds(): Check if it's an ecoff-format executable.
50  *
51  * Given a proc pointer and an exec package pointer, see if the referent
52  * of the epp is in ecoff format.  Check 'standard' magic numbers for
53  * this architecture.  If that fails, return failure.
54  *
55  * This function is  responsible for creating a set of vmcmds which can be
56  * used to build the process's vm space and inserting them into the exec
57  * package.
58  */
59 int
exec_ecoff_makecmds(p,epp)60 exec_ecoff_makecmds(p, epp)
61 	struct proc *p;
62 	struct exec_package *epp;
63 {
64 	int error;
65 	struct ecoff_exechdr *execp = epp->ep_hdr;
66 
67 	if (epp->ep_hdrvalid < ECOFF_HDR_SIZE)
68 		return ENOEXEC;
69 
70 	if (ECOFF_BADMAG(execp))
71 		return ENOEXEC;
72 
73 	switch (execp->a.magic) {
74 	case ECOFF_OMAGIC:
75 		error = exec_ecoff_prep_omagic(p, epp);
76 		break;
77 	case ECOFF_NMAGIC:
78 		error = exec_ecoff_prep_nmagic(p, epp);
79 		break;
80 	case ECOFF_ZMAGIC:
81 		error = exec_ecoff_prep_zmagic(p, epp);
82 		break;
83 	default:
84 		return ENOEXEC;
85 	}
86 
87 	if (error == 0)
88 		error = cpu_exec_ecoff_hook(p, epp);
89 
90 	if (error)
91 		kill_vmcmds(&epp->ep_vmcmds);
92 
93 	return error;
94 }
95 
96 /*
97  * exec_ecoff_prep_omagic(): Prepare a ECOFF OMAGIC binary's exec package
98  */
99 int
exec_ecoff_prep_omagic(p,epp)100 exec_ecoff_prep_omagic(p, epp)
101 	struct proc *p;
102 	struct exec_package *epp;
103 {
104 	struct ecoff_exechdr *execp = epp->ep_hdr;
105 	struct ecoff_aouthdr *eap = &execp->a;
106 
107 	epp->ep_taddr = ECOFF_SEGMENT_ALIGN(execp, eap->text_start);
108 	epp->ep_tsize = eap->tsize;
109 	epp->ep_daddr = ECOFF_SEGMENT_ALIGN(execp, eap->data_start);
110 	epp->ep_dsize = eap->dsize + eap->bsize;
111 	epp->ep_entry = eap->entry;
112 
113 	/* set up command for text and data segments */
114 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
115 	    eap->tsize + eap->dsize, epp->ep_taddr, epp->ep_vp,
116 	    ECOFF_TXTOFF(execp),
117 	    VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
118 
119 	/* set up command for bss segment */
120 	if (eap->bsize > 0)
121 		NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, eap->bsize,
122 		    ECOFF_SEGMENT_ALIGN(execp, eap->bss_start), NULLVP, 0,
123 		    VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
124 
125 	return exec_setup_stack(p, epp);
126 }
127 
128 /*
129  * exec_ecoff_prep_nmagic(): Prepare a 'native' NMAGIC ECOFF binary's exec
130  *                           package.
131  */
132 int
exec_ecoff_prep_nmagic(p,epp)133 exec_ecoff_prep_nmagic(p, epp)
134 	struct proc *p;
135 	struct exec_package *epp;
136 {
137 	struct ecoff_exechdr *execp = epp->ep_hdr;
138 	struct ecoff_aouthdr *eap = &execp->a;
139 
140 	epp->ep_taddr = ECOFF_SEGMENT_ALIGN(execp, eap->text_start);
141 	epp->ep_tsize = eap->tsize;
142 	epp->ep_daddr = ECOFF_ROUND(eap->data_start, ECOFF_LDPGSZ);
143 	epp->ep_dsize = eap->dsize + eap->bsize;
144 	epp->ep_entry = eap->entry;
145 
146 	/* set up command for text segment */
147 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, epp->ep_tsize,
148 	    epp->ep_taddr, epp->ep_vp, ECOFF_TXTOFF(execp),
149 	    VM_PROT_READ|VM_PROT_EXECUTE);
150 
151 	/* set up command for data segment */
152 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, epp->ep_dsize,
153 	    epp->ep_daddr, epp->ep_vp, ECOFF_DATOFF(execp),
154 	    VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
155 
156 	/* set up command for bss segment */
157 	if (eap->bsize > 0)
158 		NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, eap->bsize,
159 		    ECOFF_SEGMENT_ALIGN(execp, eap->bss_start), NULLVP, 0,
160 		    VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
161 
162 	return exec_setup_stack(p, epp);
163 }
164 
165 /*
166  * exec_ecoff_prep_zmagic(): Prepare a ECOFF ZMAGIC binary's exec package
167  *
168  * First, set the various offsets/lengths in the exec package.
169  *
170  * Then, mark the text image busy (so it can be demand paged) or error
171  * out if this is not possible.  Finally, set up vmcmds for the
172  * text, data, bss, and stack segments.
173  */
174 int
exec_ecoff_prep_zmagic(p,epp)175 exec_ecoff_prep_zmagic(p, epp)
176 	struct proc *p;
177 	struct exec_package *epp;
178 {
179 	struct ecoff_exechdr *execp = epp->ep_hdr;
180 	struct ecoff_aouthdr *eap = &execp->a;
181 
182 	epp->ep_taddr = ECOFF_SEGMENT_ALIGN(execp, eap->text_start);
183 	epp->ep_tsize = eap->tsize;
184 	epp->ep_daddr = ECOFF_SEGMENT_ALIGN(execp, eap->data_start);
185 	epp->ep_dsize = eap->dsize + eap->bsize;
186 	epp->ep_entry = eap->entry;
187 
188 	/*
189 	 * check if vnode is in open for writing, because we want to
190 	 * demand-page out of it.  if it is, don't do it, for various
191 	 * reasons
192 	 */
193 	if ((eap->tsize != 0 || eap->dsize != 0) &&
194 	    epp->ep_vp->v_writecount != 0) {
195 #ifdef DIAGNOSTIC
196 		if (epp->ep_vp->v_flag & VTEXT)
197 			panic("exec: a VTEXT vnode has writecount != 0");
198 #endif
199 		return ETXTBSY;
200 	}
201 	vn_marktext(epp->ep_vp);
202 
203 	/* set up command for text segment */
204 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, eap->tsize,
205 	    epp->ep_taddr, epp->ep_vp, ECOFF_TXTOFF(execp),
206 	    VM_PROT_READ|VM_PROT_EXECUTE);
207 
208 	/* set up command for data segment */
209 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, eap->dsize,
210 	    epp->ep_daddr, epp->ep_vp, ECOFF_DATOFF(execp),
211 	    VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
212 
213 	/* set up command for bss segment */
214 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, eap->bsize,
215 	    ECOFF_SEGMENT_ALIGN(execp, eap->bss_start), NULLVP, 0,
216 	    VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
217 
218 	return exec_setup_stack(p, epp);
219 }
220 
221 #endif /* _KERN_DO_ECOFF */
222