1 /* $NetBSD: netbsd32_exec_aout.c,v 1.23 2007/12/08 18:36:18 dsl Exp $ */
2 /* from: NetBSD: exec_aout.c,v 1.15 1996/09/26 23:34:46 cgd Exp */
5 * Copyright (c) 1998, 2001 Matthew R. Green.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Copyright (c) 1993, 1994 Christopher G. Demetriou
31 * All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by Christopher G. Demetriou.
44 * 4. The name of the author may not be used to endorse or promote products
45 * derived from this software without specific prior written permission
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
51 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
52 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
53 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
54 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
56 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 #include <sys/cdefs.h>
60 __KERNEL_RCSID(0, "$NetBSD: netbsd32_exec_aout.c,v 1.23 2007/12/08 18:36:18 dsl Exp $");
62 #include <sys/param.h>
63 #include <sys/systm.h>
65 #include <sys/malloc.h>
66 #include <sys/vnode.h>
68 #include <sys/exec_aout.h>
69 #include <sys/resourcevar.h>
70 #include <sys/signal.h>
71 #include <sys/signalvar.h>
73 #include <compat/netbsd32/netbsd32.h>
77 #include <compat/netbsd32/netbsd32_exec.h>
79 #include <machine/frame.h>
80 #include <machine/netbsd32_machdep.h>
82 int netbsd32_copyinargs(struct exec_package
*, struct ps_strings
*,
83 void *, size_t, const void *, const void *);
86 * exec_netbsd32_makecmds(): Check if it's an netbsd32 a.out format
89 * Given a lwp pointer and an exec package pointer, see if the referent
90 * of the epp is in netbsd32 a.out format. Check 'standard' magic
91 * numbers for this architecture.
93 * This function, in the former case, or the hook, in the latter, is
94 * responsible for creating a set of vmcmds which can be used to build
95 * the process's vm space and inserting them into the exec package.
99 exec_netbsd32_makecmds(struct lwp
*l
, struct exec_package
*epp
)
101 netbsd32_u_long midmag
, magic
;
104 struct netbsd32_exec
*execp
= epp
->ep_hdr
;
106 if (epp
->ep_hdrvalid
< sizeof(struct netbsd32_exec
))
109 midmag
= (netbsd32_u_long
)ntohl(execp
->a_midmag
);
110 mid
= (midmag
>> 16) & 0x3ff;
111 magic
= midmag
& 0xffff;
113 midmag
= mid
<< 16 | magic
;
115 /* this is already needed by setup_stack() */
116 epp
->ep_flags
|= EXEC_32
;
119 case (NETBSD32_MID_MACHINE
<< 16) | ZMAGIC
:
120 error
= netbsd32_exec_aout_prep_zmagic(l
, epp
);
122 case (NETBSD32_MID_MACHINE
<< 16) | NMAGIC
:
123 error
= netbsd32_exec_aout_prep_nmagic(l
, epp
);
125 case (NETBSD32_MID_MACHINE
<< 16) | OMAGIC
:
126 error
= netbsd32_exec_aout_prep_omagic(l
, epp
);
135 kill_vmcmds(&epp
->ep_vmcmds
);
136 epp
->ep_flags
&= ~EXEC_32
;
142 * netbsd32_exec_aout_prep_zmagic(): Prepare a 'native' ZMAGIC binary's
145 * First, set of the various offsets/lengths in the exec package.
147 * Then, mark the text image busy (so it can be demand paged) or error
148 * out if this is not possible. Finally, set up vmcmds for the
149 * text, data, bss, and stack segments.
153 netbsd32_exec_aout_prep_zmagic(struct lwp
*l
, struct exec_package
*epp
)
155 struct netbsd32_exec
*execp
= epp
->ep_hdr
;
158 epp
->ep_taddr
= AOUT_LDPGSZ
;
159 epp
->ep_tsize
= execp
->a_text
;
160 epp
->ep_daddr
= epp
->ep_taddr
+ execp
->a_text
;
161 epp
->ep_dsize
= execp
->a_data
+ execp
->a_bss
;
162 epp
->ep_entry
= execp
->a_entry
;
163 epp
->ep_vm_minaddr
= VM_MIN_ADDRESS
;
164 epp
->ep_vm_maxaddr
= VM_MAXUSER_ADDRESS32
;
166 error
= vn_marktext(epp
->ep_vp
);
170 /* set up command for text segment */
171 NEW_VMCMD(&epp
->ep_vmcmds
, vmcmd_map_pagedvn
, execp
->a_text
,
172 epp
->ep_taddr
, epp
->ep_vp
, 0, VM_PROT_READ
|VM_PROT_EXECUTE
);
174 /* set up command for data segment */
175 NEW_VMCMD(&epp
->ep_vmcmds
, vmcmd_map_pagedvn
, execp
->a_data
,
176 epp
->ep_daddr
, epp
->ep_vp
, execp
->a_text
,
177 VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
);
179 /* set up command for bss segment */
180 if (execp
->a_bss
> 0)
181 NEW_VMCMD(&epp
->ep_vmcmds
, vmcmd_map_zero
, execp
->a_bss
,
182 epp
->ep_daddr
+ execp
->a_data
, NULLVP
, 0,
183 VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
);
185 return (*epp
->ep_esch
->es_setup_stack
)(l
, epp
);
189 * netbsd32_exec_aout_prep_nmagic(): Prepare a 'native' NMAGIC binary's
194 netbsd32_exec_aout_prep_nmagic(struct lwp
*l
, struct exec_package
*epp
)
196 struct netbsd32_exec
*execp
= epp
->ep_hdr
;
199 epp
->ep_taddr
= AOUT_LDPGSZ
;
200 epp
->ep_tsize
= execp
->a_text
;
201 epp
->ep_daddr
= roundup(epp
->ep_taddr
+ execp
->a_text
, AOUT_LDPGSZ
);
202 epp
->ep_dsize
= execp
->a_data
+ execp
->a_bss
;
203 epp
->ep_entry
= execp
->a_entry
;
204 epp
->ep_vm_minaddr
= VM_MIN_ADDRESS
;
205 epp
->ep_vm_maxaddr
= VM_MAXUSER_ADDRESS32
;
207 /* set up command for text segment */
208 NEW_VMCMD(&epp
->ep_vmcmds
, vmcmd_map_readvn
, execp
->a_text
,
209 epp
->ep_taddr
, epp
->ep_vp
, sizeof(struct netbsd32_exec
),
210 VM_PROT_READ
|VM_PROT_EXECUTE
);
212 /* set up command for data segment */
213 NEW_VMCMD(&epp
->ep_vmcmds
, vmcmd_map_readvn
, execp
->a_data
,
214 epp
->ep_daddr
, epp
->ep_vp
, execp
->a_text
+ sizeof(struct netbsd32_exec
),
215 VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
);
217 /* set up command for bss segment */
218 baddr
= roundup(epp
->ep_daddr
+ execp
->a_data
, PAGE_SIZE
);
219 bsize
= epp
->ep_daddr
+ epp
->ep_dsize
- baddr
;
221 NEW_VMCMD(&epp
->ep_vmcmds
, vmcmd_map_zero
, bsize
, baddr
,
222 NULLVP
, 0, VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
);
224 return (*epp
->ep_esch
->es_setup_stack
)(l
, epp
);
228 * netbsd32_exec_aout_prep_omagic(): Prepare a 'native' OMAGIC binary's
233 netbsd32_exec_aout_prep_omagic(struct lwp
*l
, struct exec_package
*epp
)
235 struct netbsd32_exec
*execp
= epp
->ep_hdr
;
236 long dsize
, bsize
, baddr
;
238 epp
->ep_taddr
= AOUT_LDPGSZ
;
239 epp
->ep_tsize
= execp
->a_text
;
240 epp
->ep_daddr
= epp
->ep_taddr
+ execp
->a_text
;
241 epp
->ep_dsize
= execp
->a_data
+ execp
->a_bss
;
242 epp
->ep_entry
= execp
->a_entry
;
243 epp
->ep_vm_minaddr
= VM_MIN_ADDRESS
;
244 epp
->ep_vm_maxaddr
= VM_MAXUSER_ADDRESS32
;
246 /* set up command for text and data segments */
247 NEW_VMCMD(&epp
->ep_vmcmds
, vmcmd_map_readvn
,
248 execp
->a_text
+ execp
->a_data
, epp
->ep_taddr
, epp
->ep_vp
,
249 sizeof(struct netbsd32_exec
), VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
);
251 /* set up command for bss segment */
252 baddr
= roundup(epp
->ep_daddr
+ execp
->a_data
, PAGE_SIZE
);
253 bsize
= epp
->ep_daddr
+ epp
->ep_dsize
- baddr
;
255 NEW_VMCMD(&epp
->ep_vmcmds
, vmcmd_map_zero
, bsize
, baddr
,
256 NULLVP
, 0, VM_PROT_READ
|VM_PROT_WRITE
|VM_PROT_EXECUTE
);
259 * Make sure (# of pages) mapped above equals (vm_tsize + vm_dsize);
260 * obreak(2) relies on this fact. Both `vm_tsize' and `vm_dsize' are
261 * computed (in execve(2)) by rounding *up* `ep_tsize' and `ep_dsize'
262 * respectively to page boundaries.
263 * Compensate `ep_dsize' for the amount of data covered by the last
266 dsize
= epp
->ep_dsize
+ execp
->a_text
- roundup(execp
->a_text
,
268 epp
->ep_dsize
= (dsize
> 0) ? dsize
: 0;
269 return (*epp
->ep_esch
->es_setup_stack
)(l
, epp
);