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