2 * Copyright (c) 1994-1996 Søren Schmidt
5 * Based heavily on /sys/kern/imgact_aout.c which is:
6 * Copyright (c) 1993, David Greenman
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 * in this position and unchanged.
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. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * $FreeBSD: src/sys/i386/linux/imgact_linux.c,v 1.35.2.2 2001/11/03 01:41:08 ps Exp $
32 * $DragonFly: src/sys/emulation/linux/i386/imgact_linux.c,v 1.10 2006/12/28 21:24:02 dillon Exp $
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/resourcevar.h>
40 #include <sys/imgact.h>
41 #include <sys/imgact_aout.h>
42 #include <sys/kernel.h>
45 #include <sys/vnode.h>
48 #include <vm/vm_kern.h>
49 #include <vm/vm_param.h>
51 #include <vm/vm_map.h>
52 #include <vm/vm_extern.h>
56 static int exec_linux_imgact (struct image_params
*iparams
);
59 exec_linux_imgact(struct image_params
*imgp
)
61 const struct exec
*a_out
= (const struct exec
*) imgp
->image_header
;
62 struct vmspace
*vmspace
;
64 unsigned long virtual_offset
, file_offset
;
66 unsigned long bss_size
;
69 if (((a_out
->a_magic
>> 16) & 0xff) != 0x64)
73 * Set file/virtual offset based on a.out variant.
75 switch ((int)(a_out
->a_magic
& 0xffff)) {
81 virtual_offset
= 4096;
87 bss_size
= round_page(a_out
->a_bss
);
89 kprintf("imgact: text: %08lx, data: %08lx, bss: %08lx\n",
90 (u_long
)a_out
->a_text
, (u_long
)a_out
->a_data
, bss_size
);
94 * Check various fields in header for validity/bounds.
96 if (a_out
->a_entry
< virtual_offset
||
97 a_out
->a_entry
>= virtual_offset
+ a_out
->a_text
||
98 a_out
->a_text
& PAGE_MASK
|| a_out
->a_data
& PAGE_MASK
)
101 /* text + data can't exceed file size */
102 if (a_out
->a_data
+ a_out
->a_text
> imgp
->attr
->va_size
)
105 * text/data/bss must not exceed limits
107 if (a_out
->a_text
> maxtsiz
||
108 a_out
->a_data
+ bss_size
> imgp
->proc
->p_rlimit
[RLIMIT_DATA
].rlim_cur
)
112 * Destroy old process VM and create a new one (with a new stack)
114 exec_new_vmspace(imgp
, NULL
);
115 vmspace
= imgp
->proc
->p_vmspace
;
118 * Check if file_offset page aligned,.
119 * Currently we cannot handle misalinged file offsets,
120 * and so we read in the entire image (what a waste).
122 if (file_offset
& PAGE_MASK
) {
124 kprintf("imgact: Non page aligned binary %lu\n", file_offset
);
127 * Map text+data+bss read/write/execute
129 vmaddr
= virtual_offset
;
130 error
= vm_map_find(&vmspace
->vm_map
, NULL
, NULL
,
132 a_out
->a_text
+ a_out
->a_data
+ bss_size
,
134 FALSE
, VM_MAPTYPE_NORMAL
,
135 VM_PROT_ALL
, VM_PROT_ALL
, 0);
139 error
= vm_mmap(&kernel_map
, &buffer
,
140 round_page(a_out
->a_text
+ a_out
->a_data
+ file_offset
),
141 VM_PROT_READ
, VM_PROT_READ
, 0,
142 (caddr_t
) imgp
->vp
, trunc_page(file_offset
));
146 error
= copyout((caddr_t
)(void *)(uintptr_t)(buffer
+ file_offset
),
147 (caddr_t
)vmaddr
, a_out
->a_text
+ a_out
->a_data
);
149 vm_map_remove(&kernel_map
, buffer
,
150 buffer
+ round_page(a_out
->a_text
+ a_out
->a_data
+ file_offset
));
156 * remove write enable on the 'text' part
158 error
= vm_map_protect(&vmspace
->vm_map
,
160 vmaddr
+ a_out
->a_text
,
161 VM_PROT_EXECUTE
|VM_PROT_READ
,
168 kprintf("imgact: Page aligned binary %lu\n", file_offset
);
171 * Map text+data read/execute
173 vmaddr
= virtual_offset
;
174 error
= vm_mmap(&vmspace
->vm_map
, &vmaddr
,
175 a_out
->a_text
+ a_out
->a_data
,
176 VM_PROT_READ
| VM_PROT_EXECUTE
,
178 MAP_PRIVATE
| MAP_FIXED
,
179 (caddr_t
)imgp
->vp
, file_offset
);
184 kprintf("imgact: startaddr=%08lx, length=%08lx\n",
185 (u_long
)vmaddr
, a_out
->a_text
+ a_out
->a_data
);
188 * allow read/write of data
190 error
= vm_map_protect(&vmspace
->vm_map
,
191 vmaddr
+ a_out
->a_text
,
192 vmaddr
+ a_out
->a_text
+ a_out
->a_data
,
199 * Allocate anon demand-zeroed area for uninitialized data
202 vmaddr
= virtual_offset
+ a_out
->a_text
+ a_out
->a_data
;
203 error
= vm_map_find(&vmspace
->vm_map
, NULL
, NULL
,
206 FALSE
, VM_MAPTYPE_NORMAL
,
207 VM_PROT_ALL
, VM_PROT_ALL
,
212 kprintf("imgact: bssaddr=%08lx, length=%08lx\n",
213 (u_long
)vmaddr
, bss_size
);
217 /* Indicate that this file should not be modified */
218 imgp
->vp
->v_flag
|= VTEXT
;
220 /* Fill in process VM information */
221 vmspace
->vm_tsize
= round_page(a_out
->a_text
) >> PAGE_SHIFT
;
222 vmspace
->vm_dsize
= round_page(a_out
->a_data
+ bss_size
) >> PAGE_SHIFT
;
223 vmspace
->vm_taddr
= (caddr_t
)(void *)(uintptr_t)virtual_offset
;
224 vmspace
->vm_daddr
= (caddr_t
)(void *)(uintptr_t)
225 (virtual_offset
+ a_out
->a_text
);
227 /* Fill in image_params */
228 imgp
->interpreted
= 0;
229 imgp
->entry_addr
= a_out
->a_entry
;
231 imgp
->proc
->p_sysent
= &linux_sysvec
;
236 * Tell kern_execve.c about it, with a little help from the linker.
238 static struct execsw linux_execsw
= { exec_linux_imgact
, "linux a.out" };
239 EXEC_SET(linuxaout
, linux_execsw
);