sunos_exec.c revision 1.1
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.1 1993/11/28 18:03:19 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
70	sunmag = (struct sun_exec *)epp->ep_execp;
71	if(sunmag->a_machtype != SUN_M_NATIVE)
72		return (ENOEXEC);
73
74	epp->ep_emul = EMUL_SUNOS;
75	switch (sunmag->a_magic) {
76	case ZMAGIC:
77		return sun_exec_aout_prep_zmagic(p, epp);
78	case NMAGIC:
79		return sun_exec_aout_prep_nmagic(p, epp);
80	case OMAGIC:
81		return sun_exec_aout_prep_omagic(p, epp);
82	default:
83		break;
84	}
85	return (ENOEXEC);
86}
87
88/*
89 * the code below is only needed for sun3 emulation.
90 */
91#ifndef sparc
92
93/* suns keep data seg aligned to SEGSIZ because of sun custom mmu */
94#define SEGSIZ		0x20000
95#define N_TXTADDR(x,m)	__LDPGSZ
96#define N_DATADDR(x,m)	(((m)==OMAGIC) ? (N_TXTADDR(x,m) + (x).a_text) \
97			: (SEGSIZ + ((N_TXTADDR(x,m) + (x).a_text - 1) \
98				       & ~(SEGSIZ-1))))
99#define N_BSSADDR(x,m)	(N_DATADDR(x,m)+(x).a_data)
100
101#define N_TXTOFF(x,m)	((m)==ZMAGIC ? 0 : sizeof (struct exec))
102#define N_DATOFF(x,m)	(N_TXTOFF(x,m) + (x).a_text)
103
104/*
105 * sun_exec_aout_prep_zmagic(): Prepare a SunOS ZMAGIC binary's exec package
106 *
107 * First, set of 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 */
113int
114sun_exec_aout_prep_zmagic(p, epp)
115	struct proc *p;
116	struct exec_package *epp;
117{
118	struct exec *execp = epp->ep_execp;
119	struct exec_vmcmd *ccmdp;
120
121	epp->ep_taddr = N_TXTADDR(*execp, ZMAGIC);
122	epp->ep_tsize = execp->a_text;
123	epp->ep_daddr = N_DATADDR(*execp, ZMAGIC);
124	epp->ep_dsize = execp->a_data + execp->a_bss;
125	epp->ep_entry = execp->a_entry;
126
127	/*
128	 * check if vnode is in open for writing, because we want to
129	 * demand-page out of it.  if it is, don't do it, for various
130	 * reasons
131	 */
132	if ((execp->a_text != 0 || execp->a_data != 0) &&
133	    (epp->ep_vp->v_flag & VTEXT) == 0 && epp->ep_vp->v_writecount != 0) {
134#ifdef DIAGNOSTIC
135		if (epp->ep_vp->v_flag & VTEXT)
136			panic("exec: a VTEXT vnode has writecount != 0\n");
137#endif
138		epp->ep_vcp = NULL;
139		return ETXTBSY;
140	}
141	epp->ep_vp->v_flag |= VTEXT;
142
143	/* set up command for text segment */
144	epp->ep_vcp = new_vmcmd(vmcmd_map_pagedvn,
145	    execp->a_text,
146	    epp->ep_taddr,
147	    epp->ep_vp,
148	    N_TXTOFF(*execp, ZMAGIC),
149	    VM_PROT_READ | VM_PROT_EXECUTE);
150	ccmdp = epp->ep_vcp;
151
152	/* set up command for data segment */
153	ccmdp->ev_next = new_vmcmd(vmcmd_map_pagedvn,
154	    execp->a_data,
155	    epp->ep_daddr,
156	    epp->ep_vp,
157	    N_DATOFF(*execp, ZMAGIC),
158	    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
159	ccmdp = ccmdp->ev_next;
160
161	/* set up command for bss segment */
162	ccmdp->ev_next = new_vmcmd(vmcmd_map_zero,
163	    execp->a_bss,
164	    epp->ep_daddr + execp->a_data,
165	    0,
166	    0,
167	    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
168	ccmdp = ccmdp->ev_next;
169
170	return exec_aout_setup_stack(p, epp, ccmdp);
171}
172
173/*
174 * sun_exec_aout_prep_nmagic(): Prepare a SunOS NMAGIC binary's exec package
175 */
176int
177sun_exec_aout_prep_nmagic(p, epp)
178	struct proc *p;
179	struct exec_package *epp;
180{
181	struct exec *execp = epp->ep_execp;
182	struct exec_vmcmd *ccmdp;
183	long bsize, baddr;
184
185	epp->ep_taddr = N_TXTADDR(*execp, NMAGIC);
186	epp->ep_tsize = execp->a_text;
187	epp->ep_daddr = N_DATADDR(*execp, NMAGIC);
188	epp->ep_dsize = execp->a_data + execp->a_bss;
189	epp->ep_entry = execp->a_entry;
190
191	/* set up command for text segment */
192	epp->ep_vcp = new_vmcmd(vmcmd_map_readvn,
193	    execp->a_text,
194	    epp->ep_taddr,
195	    epp->ep_vp,
196	    N_TXTOFF(*execp, NMAGIC),
197	    VM_PROT_READ | VM_PROT_EXECUTE);
198	ccmdp = epp->ep_vcp;
199
200	/* set up command for data segment */
201	ccmdp->ev_next = new_vmcmd(vmcmd_map_readvn,
202	    execp->a_data,
203	    epp->ep_daddr,
204	    epp->ep_vp,
205	    N_DATOFF(*execp, NMAGIC),
206	    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
207	ccmdp = ccmdp->ev_next;
208
209	/* set up command for bss segment */
210	baddr = roundup(epp->ep_daddr + execp->a_data, NBPG);
211	bsize = epp->ep_daddr + epp->ep_dsize - baddr;
212	if (bsize > 0) {
213		ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, bsize, baddr,
214		    0, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
215		ccmdp = ccmdp->ev_next;
216	}
217
218	return exec_aout_setup_stack(p, epp, ccmdp);
219}
220
221/*
222 * sun_exec_aout_prep_omagic(): Prepare a SunOS OMAGIC binary's exec package
223 */
224int
225sun_exec_aout_prep_omagic(p, epp)
226	struct proc *p;
227	struct exec_package *epp;
228{
229	struct exec *execp = epp->ep_execp;
230	struct exec_vmcmd *ccmdp;
231	long bsize, baddr;
232
233	epp->ep_taddr = N_TXTADDR(*execp, OMAGIC);
234	epp->ep_tsize = execp->a_text;
235	epp->ep_daddr = N_DATADDR(*execp, OMAGIC);
236	epp->ep_dsize = execp->a_data + execp->a_bss;
237	epp->ep_entry = execp->a_entry;
238
239	/* set up command for text and data segments */
240	epp->ep_vcp = new_vmcmd(vmcmd_map_readvn,
241	    execp->a_text + execp->a_data,
242	    epp->ep_taddr,
243	    epp->ep_vp,
244	    N_TXTOFF(*execp, OMAGIC),
245	    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
246	ccmdp = epp->ep_vcp;
247
248	/* set up command for bss segment */
249	baddr = roundup(epp->ep_daddr + execp->a_data, __LDPGSZ);
250	bsize = epp->ep_daddr + epp->ep_dsize - baddr;
251	if (bsize > 0) {
252		ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, bsize, baddr,
253		    0, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
254		ccmdp = ccmdp->ev_next;
255	}
256
257	return exec_aout_setup_stack(p, epp, ccmdp);
258}
259#endif /* !sparc */
260