sunos_exec.c revision 1.2
1/*
2 * Copyright (c) 1993 Theo de Raadt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 *    derived from this software withough specific prior written permission
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 *	$Id: sunos_exec.c,v 1.2 1993/12/12 20:43:18 deraadt Exp $
28 */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/filedesc.h>
33#include <sys/kernel.h>
34#include <sys/proc.h>
35#include <sys/mount.h>
36#include <sys/malloc.h>
37#include <sys/namei.h>
38#include <sys/vnode.h>
39#include <sys/file.h>
40#include <sys/exec.h>
41#include <sys/resourcevar.h>
42#include <sys/wait.h>
43
44#include <sys/mman.h>
45#include <vm/vm.h>
46#include <vm/vm_param.h>
47#include <vm/vm_map.h>
48#include <vm/vm_kern.h>
49#include <vm/vm_pager.h>
50
51#include <machine/cpu.h>
52#include <machine/reg.h>
53#include <machine/exec.h>
54
55#include <compat/sunos/exec.h>
56
57#ifdef sparc
58#define	sun_exec_aout_prep_zmagic exec_aout_prep_zmagic
59#define	sun_exec_aout_prep_nmagic exec_aout_prep_nmagic
60#define	sun_exec_aout_prep_omagic exec_aout_prep_omagic
61#endif
62
63int
64sun_exec_aout_makecmds(p, epp)
65	struct proc *p;
66	struct exec_package *epp;
67{
68	struct sun_exec *sunmag;
69	int error = ENOEXEC;
70
71	sunmag = (struct sun_exec *)epp->ep_execp;
72	if(sunmag->a_machtype != SUN_M_NATIVE)
73		return (ENOEXEC);
74
75	switch (sunmag->a_magic) {
76	case ZMAGIC:
77		error = sun_exec_aout_prep_zmagic(p, epp);
78		break;
79	case NMAGIC:
80		error = sun_exec_aout_prep_nmagic(p, epp);
81		break;
82	case OMAGIC:
83		error = sun_exec_aout_prep_omagic(p, epp);
84		break;
85	}
86	if (error==0)
87		epp->ep_emul = EMUL_SUNOS;
88	return error;
89}
90
91/*
92 * the code below is only needed for sun3 emulation.
93 */
94#ifndef sparc
95
96/* suns keep data seg aligned to SEGSIZ because of sun custom mmu */
97#define SEGSIZ		0x20000
98#define N_TXTADDR(x,m)	__LDPGSZ
99#define N_DATADDR(x,m)	(((m)==OMAGIC) ? (N_TXTADDR(x,m) + (x).a_text) \
100			: (SEGSIZ + ((N_TXTADDR(x,m) + (x).a_text - 1) \
101				       & ~(SEGSIZ-1))))
102#define N_BSSADDR(x,m)	(N_DATADDR(x,m)+(x).a_data)
103
104#define N_TXTOFF(x,m)	((m)==ZMAGIC ? 0 : sizeof (struct exec))
105#define N_DATOFF(x,m)	(N_TXTOFF(x,m) + (x).a_text)
106
107/*
108 * sun_exec_aout_prep_zmagic(): Prepare a SunOS ZMAGIC binary's exec package
109 *
110 * First, set of the various offsets/lengths in the exec package.
111 *
112 * Then, mark the text image busy (so it can be demand paged) or error
113 * out if this is not possible.  Finally, set up vmcmds for the
114 * text, data, bss, and stack segments.
115 */
116int
117sun_exec_aout_prep_zmagic(p, epp)
118	struct proc *p;
119	struct exec_package *epp;
120{
121	struct exec *execp = epp->ep_execp;
122	struct exec_vmcmd *ccmdp;
123
124	epp->ep_taddr = N_TXTADDR(*execp, ZMAGIC);
125	epp->ep_tsize = execp->a_text;
126	epp->ep_daddr = N_DATADDR(*execp, ZMAGIC);
127	epp->ep_dsize = execp->a_data + execp->a_bss;
128	epp->ep_entry = execp->a_entry;
129
130	/*
131	 * check if vnode is in open for writing, because we want to
132	 * demand-page out of it.  if it is, don't do it, for various
133	 * reasons
134	 */
135	if ((execp->a_text != 0 || execp->a_data != 0) &&
136	    (epp->ep_vp->v_flag & VTEXT) == 0 && epp->ep_vp->v_writecount != 0) {
137#ifdef DIAGNOSTIC
138		if (epp->ep_vp->v_flag & VTEXT)
139			panic("exec: a VTEXT vnode has writecount != 0\n");
140#endif
141		epp->ep_vcp = NULL;
142		return ETXTBSY;
143	}
144	epp->ep_vp->v_flag |= VTEXT;
145
146	/* set up command for text segment */
147	epp->ep_vcp = new_vmcmd(vmcmd_map_pagedvn,
148	    execp->a_text,
149	    epp->ep_taddr,
150	    epp->ep_vp,
151	    N_TXTOFF(*execp, ZMAGIC),
152	    VM_PROT_READ | VM_PROT_EXECUTE);
153	ccmdp = epp->ep_vcp;
154
155	/* set up command for data segment */
156	ccmdp->ev_next = new_vmcmd(vmcmd_map_pagedvn,
157	    execp->a_data,
158	    epp->ep_daddr,
159	    epp->ep_vp,
160	    N_DATOFF(*execp, ZMAGIC),
161	    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
162	ccmdp = ccmdp->ev_next;
163
164	/* set up command for bss segment */
165	ccmdp->ev_next = new_vmcmd(vmcmd_map_zero,
166	    execp->a_bss,
167	    epp->ep_daddr + execp->a_data,
168	    0,
169	    0,
170	    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
171	ccmdp = ccmdp->ev_next;
172
173	return exec_aout_setup_stack(p, epp, ccmdp);
174}
175
176/*
177 * sun_exec_aout_prep_nmagic(): Prepare a SunOS NMAGIC binary's exec package
178 */
179int
180sun_exec_aout_prep_nmagic(p, epp)
181	struct proc *p;
182	struct exec_package *epp;
183{
184	struct exec *execp = epp->ep_execp;
185	struct exec_vmcmd *ccmdp;
186	long bsize, baddr;
187
188	epp->ep_taddr = N_TXTADDR(*execp, NMAGIC);
189	epp->ep_tsize = execp->a_text;
190	epp->ep_daddr = N_DATADDR(*execp, NMAGIC);
191	epp->ep_dsize = execp->a_data + execp->a_bss;
192	epp->ep_entry = execp->a_entry;
193
194	/* set up command for text segment */
195	epp->ep_vcp = new_vmcmd(vmcmd_map_readvn,
196	    execp->a_text,
197	    epp->ep_taddr,
198	    epp->ep_vp,
199	    N_TXTOFF(*execp, NMAGIC),
200	    VM_PROT_READ | VM_PROT_EXECUTE);
201	ccmdp = epp->ep_vcp;
202
203	/* set up command for data segment */
204	ccmdp->ev_next = new_vmcmd(vmcmd_map_readvn,
205	    execp->a_data,
206	    epp->ep_daddr,
207	    epp->ep_vp,
208	    N_DATOFF(*execp, NMAGIC),
209	    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
210	ccmdp = ccmdp->ev_next;
211
212	/* set up command for bss segment */
213	baddr = roundup(epp->ep_daddr + execp->a_data, NBPG);
214	bsize = epp->ep_daddr + epp->ep_dsize - baddr;
215	if (bsize > 0) {
216		ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, bsize, baddr,
217		    0, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
218		ccmdp = ccmdp->ev_next;
219	}
220
221	return exec_aout_setup_stack(p, epp, ccmdp);
222}
223
224/*
225 * sun_exec_aout_prep_omagic(): Prepare a SunOS OMAGIC binary's exec package
226 */
227int
228sun_exec_aout_prep_omagic(p, epp)
229	struct proc *p;
230	struct exec_package *epp;
231{
232	struct exec *execp = epp->ep_execp;
233	struct exec_vmcmd *ccmdp;
234	long bsize, baddr;
235
236	epp->ep_taddr = N_TXTADDR(*execp, OMAGIC);
237	epp->ep_tsize = execp->a_text;
238	epp->ep_daddr = N_DATADDR(*execp, OMAGIC);
239	epp->ep_dsize = execp->a_data + execp->a_bss;
240	epp->ep_entry = execp->a_entry;
241
242	/* set up command for text and data segments */
243	epp->ep_vcp = new_vmcmd(vmcmd_map_readvn,
244	    execp->a_text + execp->a_data,
245	    epp->ep_taddr,
246	    epp->ep_vp,
247	    N_TXTOFF(*execp, OMAGIC),
248	    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
249	ccmdp = epp->ep_vcp;
250
251	/* set up command for bss segment */
252	baddr = roundup(epp->ep_daddr + execp->a_data, __LDPGSZ);
253	bsize = epp->ep_daddr + epp->ep_dsize - baddr;
254	if (bsize > 0) {
255		ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, bsize, baddr,
256		    0, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
257		ccmdp = ccmdp->ev_next;
258	}
259
260	return exec_aout_setup_stack(p, epp, ccmdp);
261}
262#endif /* !sparc */
263