Deleted Added
full compact
imgact_coff.c (14584) imgact_coff.c (15494)
1/*-
2 * Copyright (c) 1994 Sean Eric Fagan
3 * Copyright (c) 1994 S�ren Schmidt
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer
11 * in this position and unchanged.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software withough specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
1/*-
2 * Copyright (c) 1994 Sean Eric Fagan
3 * Copyright (c) 1994 S�ren Schmidt
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer
11 * in this position and unchanged.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software withough specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $Id: imgact_coff.c,v 1.13 1996/03/12 06:13:08 peter Exp $
29 * $Id: imgact_coff.c,v 1.14 1996/03/12 06:20:19 peter Exp $
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/resourcevar.h>
35#include <sys/exec.h>
36#include <sys/mman.h>
37#include <sys/imgact.h>
38#include <sys/kernel.h>
39#include <sys/file.h>
40#include <sys/malloc.h>
41#include <sys/mount.h>
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/resourcevar.h>
35#include <sys/exec.h>
36#include <sys/mman.h>
37#include <sys/imgact.h>
38#include <sys/kernel.h>
39#include <sys/file.h>
40#include <sys/malloc.h>
41#include <sys/mount.h>
42#include <sys/namei.h>
42#include <sys/sysent.h>
43#include <sys/sysent.h>
44#include <sys/vnode.h>
43
44#include <vm/vm.h>
45#include <vm/vm_param.h>
46#include <vm/vm_prot.h>
47#include <vm/lock.h>
48#include <vm/pmap.h>
49#include <vm/vm_map.h>
50#include <vm/vm_kern.h>
51#include <vm/vm_extern.h>
52
53#include <i386/ibcs2/coff.h>
54#include <i386/ibcs2/ibcs2_util.h>
55
56extern struct sysentvec ibcs2_svr3_sysvec;
57
58extern int coff_load_file __P((struct proc *p, char *name));
59extern int exec_coff_imgact __P((struct image_params *imgp));
60
61static int load_coff_section __P((struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot));
62
63static int
64load_coff_section(vmspace, vp, offset, vmaddr, memsz, filsz, prot)
65 struct vmspace *vmspace;
66 struct vnode *vp;
67 vm_offset_t offset;
68 caddr_t vmaddr;
69 size_t memsz, filsz;
70 vm_prot_t prot;
71{
72 size_t map_len;
73 vm_offset_t map_offset;
74 vm_offset_t map_addr;
75 int error;
76 unsigned char *data_buf = 0;
77 size_t copy_len;
78
79 map_offset = trunc_page(offset);
80 map_addr = trunc_page(vmaddr);
81
82 if (memsz > filsz) {
83 /*
84 * We have the stupid situation that
85 * the section is longer than it is on file,
86 * which means it has zero-filled areas, and
87 * we have to work for it. Stupid iBCS!
88 */
89 map_len = trunc_page(offset + filsz) - trunc_page(map_offset);
90 } else {
91 /*
92 * The only stuff we care about is on disk, and we
93 * don't care if we map in more than is really there.
94 */
95 map_len = round_page(offset + filsz) - trunc_page(map_offset);
96 }
97
98 DPRINTF(("%s(%d): vm_mmap(&vmspace->vm_map, &0x%08lx, 0x%x, 0x%x, "
99 "VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, vp, 0x%x)\n",
100 __FILE__, __LINE__, map_addr, map_len, prot, map_offset));
101
102 if (error = vm_mmap(&vmspace->vm_map,
103 &map_addr,
104 map_len,
105 prot,
106 VM_PROT_ALL,
107 MAP_PRIVATE | MAP_FIXED,
108 (caddr_t) vp,
109 map_offset))
110 return error;
111
112 if (memsz == filsz) {
113 /* We're done! */
114 return 0;
115 }
116
117 /*
118 * Now we have screwball stuff, to accomodate stupid COFF.
119 * We have to map the remaining bit of the file into the kernel's
120 * memory map, allocate some anonymous memory, copy that last
121 * bit into it, and then we're done. *sigh*
122 * For clean-up reasons, we actally map in the file last.
123 */
124
125 copy_len = (offset + filsz) - trunc_page(offset + filsz);
126 map_addr = trunc_page(vmaddr + filsz);
127 map_len = round_page(vmaddr + memsz) - map_addr;
128
129 DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx,0x%x, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n", __FILE__, __LINE__, map_addr, map_len));
130
131 if (map_len != 0) {
132 error = vm_map_find(&vmspace->vm_map, NULL, 0, &map_addr,
133 map_len, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
134 if (error)
135 return error;
136 }
137
138 if (error = vm_mmap(kernel_map,
139 (vm_offset_t *) &data_buf,
140 PAGE_SIZE,
141 VM_PROT_READ,
142 VM_PROT_READ,
143 0,
144 (caddr_t) vp,
145 trunc_page(offset + filsz)))
146 return error;
147
148 error = copyout(data_buf, (caddr_t) map_addr, copy_len);
149
150 if (vm_map_remove(kernel_map,
151 (vm_offset_t) data_buf,
152 (vm_offset_t) data_buf + PAGE_SIZE))
153 panic("load_coff_section vm_map_remove failed");
154
155 return error;
156}
157
158int
159coff_load_file(struct proc *p, char *name)
160{
161 struct vmspace *vmspace = p->p_vmspace;
162 int error;
163 struct nameidata nd;
164 struct vnode *vp;
165 struct vattr attr;
166 struct filehdr *fhdr;
167 struct aouthdr *ahdr;
168 struct scnhdr *scns;
169 char *ptr = 0;
170 int nscns;
171 unsigned long text_offset = 0, text_address = 0, text_size = 0;
172 unsigned long data_offset = 0, data_address = 0, data_size = 0;
173 unsigned long bss_size = 0;
174 int i;
175
176 /* XXX use of 'curproc' should be 'p'?*/
177 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_SYSSPACE, name, curproc);
178
179 error = namei(&nd);
180 if (error)
181 return error;
182
183 vp = nd.ni_vp;
184 if (vp == NULL)
185 return ENOEXEC;
186
187 if (vp->v_writecount) {
188 error = ETXTBSY;
189 goto fail;
190 }
191
192 if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p))
193 goto fail;
194
195 if ((vp->v_mount->mnt_flag & MNT_NOEXEC)
196 || ((attr.va_mode & 0111) == 0)
197 || (attr.va_type != VREG))
198 goto fail;
199
200 if (attr.va_size == 0) {
201 error = ENOEXEC;
202 goto fail;
203 }
204
205 if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p))
206 goto fail;
207
208 if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p))
209 goto fail;
210
211 /*
212 * Lose the lock on the vnode. It's no longer needed, and must not
213 * exist for the pagefault paging to work below.
214 */
215 VOP_UNLOCK(vp);
216
217 if (error = vm_mmap(kernel_map,
218 (vm_offset_t *) &ptr,
219 PAGE_SIZE,
220 VM_PROT_READ,
221 VM_PROT_READ,
222 0,
223 (caddr_t) vp,
224 0))
225 goto fail;
226
227 fhdr = (struct filehdr *)ptr;
228
229 if (fhdr->f_magic != I386_COFF) {
230 error = ENOEXEC;
231 goto dealloc_and_fail;
232 }
233
234 nscns = fhdr->f_nscns;
235
236 if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) {
237 /*
238 * XXX -- just fail. I'm so lazy.
239 */
240 error = ENOEXEC;
241 goto dealloc_and_fail;
242 }
243
244 ahdr = (struct aouthdr*)(ptr + sizeof(struct filehdr));
245
246 scns = (struct scnhdr*)(ptr + sizeof(struct filehdr)
247 + sizeof(struct aouthdr));
248
249 for (i = 0; i < nscns; i++) {
250 if (scns[i].s_flags & STYP_NOLOAD)
251 continue;
252 else if (scns[i].s_flags & STYP_TEXT) {
253 text_address = scns[i].s_vaddr;
254 text_size = scns[i].s_size;
255 text_offset = scns[i].s_scnptr;
256 }
257 else if (scns[i].s_flags & STYP_DATA) {
258 data_address = scns[i].s_vaddr;
259 data_size = scns[i].s_size;
260 data_offset = scns[i].s_scnptr;
261 } else if (scns[i].s_flags & STYP_BSS) {
262 bss_size = scns[i].s_size;
263 }
264 }
265
266 if (error = load_coff_section(vmspace, vp, text_offset,
267 (caddr_t)text_address,
268 text_size, text_size,
269 VM_PROT_READ | VM_PROT_EXECUTE)) {
270 goto dealloc_and_fail;
271 }
272 if (error = load_coff_section(vmspace, vp, data_offset,
273 (caddr_t)data_address,
274 data_size + bss_size, data_size,
275 VM_PROT_ALL)) {
276 goto dealloc_and_fail;
277 }
278
279 error = 0;
280
281 dealloc_and_fail:
282 if (vm_map_remove(kernel_map,
283 (vm_offset_t) ptr,
284 (vm_offset_t) ptr + PAGE_SIZE))
285 panic(__FUNCTION__ " vm_map_remove failed");
286
287 fail:
288 vput(nd.ni_vp);
289 FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
290 return error;
291}
292
293int
294exec_coff_imgact(imgp)
295 struct image_params *imgp;
296{
297 struct filehdr *fhdr = (struct filehdr*)imgp->image_header;
298 struct aouthdr *ahdr;
299 struct scnhdr *scns;
300 int i;
301 struct vmspace *vmspace = imgp->proc->p_vmspace;
302 unsigned long vmaddr;
303 int nscns;
304 int error, len;
305 unsigned long text_offset = 0, text_address = 0, text_size = 0;
306 unsigned long data_offset = 0, data_address = 0, data_size = 0;
307 unsigned long bss_size = 0;
308 int need_hack_p;
309 unsigned long data_end;
310 unsigned long data_map_start, data_map_len, data_map_addr = 0;
311 unsigned long bss_address, bss_map_start, data_copy_len, bss_map_len;
312 unsigned char *data_buf = 0;
313 caddr_t hole;
314
315 if (fhdr->f_magic != I386_COFF ||
316 !(fhdr->f_flags & F_EXEC)) {
317
318 DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__));
319 return -1;
320 }
321
322 nscns = fhdr->f_nscns;
323 if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) {
324 /*
325 * For now, return an error -- need to be able to
326 * read in all of the section structures.
327 */
328
329 DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__));
330 return -1;
331 }
332
333 ahdr = (struct aouthdr*)((char*)(imgp->image_header) +
334 sizeof(struct filehdr));
335 imgp->entry_addr = ahdr->entry;
336
337 scns = (struct scnhdr*)((char*)(imgp->image_header) +
338 sizeof(struct filehdr) +
339 sizeof(struct aouthdr));
340
341 if (error = exec_extract_strings(imgp)) {
342 DPRINTF(("%s(%d): return %d\n", __FILE__, __LINE__, error));
343 return error;
344 }
345
346 exec_new_vmspace(imgp);
347
348 for (i = 0; i < nscns; i++) {
349
350 DPRINTF(("i = %d, scns[i].s_name = %s, scns[i].s_vaddr = %08lx, "
351 "scns[i].s_scnptr = %d\n", i, scns[i].s_name,
352 scns[i].s_vaddr, scns[i].s_scnptr));
353 if (scns[i].s_flags & STYP_NOLOAD) {
354 /*
355 * A section that is not loaded, for whatever
356 * reason. It takes precedance over other flag
357 * bits...
358 */
359 continue;
360 } else if (scns[i].s_flags & STYP_TEXT) {
361 text_address = scns[i].s_vaddr;
362 text_size = scns[i].s_size;
363 text_offset = scns[i].s_scnptr;
364 } else if (scns[i].s_flags & STYP_DATA) {
365 /* .data section */
366 data_address = scns[i].s_vaddr;
367 data_size = scns[i].s_size;
368 data_offset = scns[i].s_scnptr;
369 } else if (scns[i].s_flags & STYP_BSS) {
370 /* .bss section */
371 bss_size = scns[i].s_size;
372 } else if (scns[i].s_flags & STYP_LIB) {
373 char *buf = 0, *ptr;
374 int foff = trunc_page(scns[i].s_scnptr);
375 int off = scns[i].s_scnptr - foff;
376 int len = round_page(scns[i].s_size + PAGE_SIZE);
377 int j;
378
379 if (error = vm_mmap(kernel_map,
380 (vm_offset_t *) &buf,
381 len,
382 VM_PROT_READ,
383 VM_PROT_READ,
384 0,
385 (caddr_t) imgp->vp,
386 foff)) {
387 return ENOEXEC;
388 }
389 if(scns[i].s_size) {
390 char *libbuf;
391 int emul_path_len = strlen(ibcs2_emul_path);
392
393 libbuf = malloc(MAXPATHLEN + emul_path_len,
394 M_TEMP, M_WAITOK);
395 strcpy(libbuf, ibcs2_emul_path);
396
397 for (j = off; j < scns[i].s_size + off; j++) {
398 char *libname;
399
400 libname = buf + j + 4 * *(long*)(buf + j + 4);
401 j += 4* *(long*)(buf + j);
402
403 DPRINTF(("%s(%d): shared library %s\n",
404 __FILE__, __LINE__, libname));
405 strcpy(&libbuf[emul_path_len], libname);
406 error = coff_load_file(imgp->proc, libbuf);
407 if (error)
408 error = coff_load_file(imgp->proc,
409 libname);
410 if (error)
411 break;
412 }
413 free(libbuf, M_TEMP);
414 }
415 if (vm_map_remove(kernel_map,
416 (vm_offset_t) buf,
417 (vm_offset_t) buf + len))
418 panic("exec_coff_imgact vm_map_remove failed");
419 if (error)
420 return error;
421 }
422 }
423 /*
424 * Map in .text now
425 */
426
427 DPRINTF(("%s(%d): load_coff_section(vmspace, "
428 "imgp->vp, %08lx, %08lx, 0x%x, 0x%x, 0x%x)\n",
429 __FILE__, __LINE__, text_offset, text_address,
430 text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE));
431 if (error = load_coff_section(vmspace, imgp->vp,
432 text_offset, (caddr_t)text_address,
433 text_size, text_size,
434 VM_PROT_READ | VM_PROT_EXECUTE)) {
435 DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error));
436 return error;
437 }
438 /*
439 * Map in .data and .bss now
440 */
441
442
443 DPRINTF(("%s(%d): load_coff_section(vmspace, "
444 "imgp->vp, 0x%08lx, 0x%08lx, 0x%x, 0x%x, 0x%x)\n",
445 __FILE__, __LINE__, data_offset, data_address,
446 data_size + bss_size, data_size, VM_PROT_ALL));
447 if (error = load_coff_section(vmspace, imgp->vp,
448 data_offset, (caddr_t)data_address,
449 data_size + bss_size, data_size,
450 VM_PROT_ALL)) {
451
452 DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error));
453 return error;
454 }
455
456 imgp->interpreted = 0;
457 imgp->proc->p_sysent = &ibcs2_svr3_sysvec;
458
459 vmspace->vm_tsize = round_page(text_size) >> PAGE_SHIFT;
460 vmspace->vm_dsize = round_page(data_size + bss_size) >> PAGE_SHIFT;
461 vmspace->vm_taddr = (caddr_t)text_address;
462 vmspace->vm_daddr = (caddr_t)data_address;
463
464 hole = (caddr_t)trunc_page(vmspace->vm_daddr) + ctob(vmspace->vm_dsize);
465
466
467 DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n",
468 __FILE__, __LINE__, hole));
469 DPRINTF(("imgact: error = %d\n", error));
470
471 error = vm_map_find(&vmspace->vm_map, NULL, 0,
472 (vm_offset_t *) &hole, PAGE_SIZE, FALSE,
473 VM_PROT_ALL, VM_PROT_ALL, 0);
474
475 DPRINTF(("IBCS2: start vm_dsize = 0x%x, vm_daddr = 0x%x end = 0x%x\n",
476 ctob(vmspace->vm_dsize), vmspace->vm_daddr,
477 ctob(vmspace->vm_dsize) + vmspace->vm_daddr ));
478 DPRINTF(("%s(%d): returning successfully!\n", __FILE__, __LINE__));
479
480 /* Indicate that this file should not be modified */
481 imgp->vp->v_flag |= VTEXT;
482 return 0;
483}
484
485/*
486 * Tell kern_execve.c about it, with a little help from the linker.
487 * Since `const' objects end up in the text segment, TEXT_SET is the
488 * correct directive to use.
489 */
490const struct execsw coff_execsw = { exec_coff_imgact, "coff" };
491TEXT_SET(execsw_set, coff_execsw);
45
46#include <vm/vm.h>
47#include <vm/vm_param.h>
48#include <vm/vm_prot.h>
49#include <vm/lock.h>
50#include <vm/pmap.h>
51#include <vm/vm_map.h>
52#include <vm/vm_kern.h>
53#include <vm/vm_extern.h>
54
55#include <i386/ibcs2/coff.h>
56#include <i386/ibcs2/ibcs2_util.h>
57
58extern struct sysentvec ibcs2_svr3_sysvec;
59
60extern int coff_load_file __P((struct proc *p, char *name));
61extern int exec_coff_imgact __P((struct image_params *imgp));
62
63static int load_coff_section __P((struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot));
64
65static int
66load_coff_section(vmspace, vp, offset, vmaddr, memsz, filsz, prot)
67 struct vmspace *vmspace;
68 struct vnode *vp;
69 vm_offset_t offset;
70 caddr_t vmaddr;
71 size_t memsz, filsz;
72 vm_prot_t prot;
73{
74 size_t map_len;
75 vm_offset_t map_offset;
76 vm_offset_t map_addr;
77 int error;
78 unsigned char *data_buf = 0;
79 size_t copy_len;
80
81 map_offset = trunc_page(offset);
82 map_addr = trunc_page(vmaddr);
83
84 if (memsz > filsz) {
85 /*
86 * We have the stupid situation that
87 * the section is longer than it is on file,
88 * which means it has zero-filled areas, and
89 * we have to work for it. Stupid iBCS!
90 */
91 map_len = trunc_page(offset + filsz) - trunc_page(map_offset);
92 } else {
93 /*
94 * The only stuff we care about is on disk, and we
95 * don't care if we map in more than is really there.
96 */
97 map_len = round_page(offset + filsz) - trunc_page(map_offset);
98 }
99
100 DPRINTF(("%s(%d): vm_mmap(&vmspace->vm_map, &0x%08lx, 0x%x, 0x%x, "
101 "VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, vp, 0x%x)\n",
102 __FILE__, __LINE__, map_addr, map_len, prot, map_offset));
103
104 if (error = vm_mmap(&vmspace->vm_map,
105 &map_addr,
106 map_len,
107 prot,
108 VM_PROT_ALL,
109 MAP_PRIVATE | MAP_FIXED,
110 (caddr_t) vp,
111 map_offset))
112 return error;
113
114 if (memsz == filsz) {
115 /* We're done! */
116 return 0;
117 }
118
119 /*
120 * Now we have screwball stuff, to accomodate stupid COFF.
121 * We have to map the remaining bit of the file into the kernel's
122 * memory map, allocate some anonymous memory, copy that last
123 * bit into it, and then we're done. *sigh*
124 * For clean-up reasons, we actally map in the file last.
125 */
126
127 copy_len = (offset + filsz) - trunc_page(offset + filsz);
128 map_addr = trunc_page(vmaddr + filsz);
129 map_len = round_page(vmaddr + memsz) - map_addr;
130
131 DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx,0x%x, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n", __FILE__, __LINE__, map_addr, map_len));
132
133 if (map_len != 0) {
134 error = vm_map_find(&vmspace->vm_map, NULL, 0, &map_addr,
135 map_len, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
136 if (error)
137 return error;
138 }
139
140 if (error = vm_mmap(kernel_map,
141 (vm_offset_t *) &data_buf,
142 PAGE_SIZE,
143 VM_PROT_READ,
144 VM_PROT_READ,
145 0,
146 (caddr_t) vp,
147 trunc_page(offset + filsz)))
148 return error;
149
150 error = copyout(data_buf, (caddr_t) map_addr, copy_len);
151
152 if (vm_map_remove(kernel_map,
153 (vm_offset_t) data_buf,
154 (vm_offset_t) data_buf + PAGE_SIZE))
155 panic("load_coff_section vm_map_remove failed");
156
157 return error;
158}
159
160int
161coff_load_file(struct proc *p, char *name)
162{
163 struct vmspace *vmspace = p->p_vmspace;
164 int error;
165 struct nameidata nd;
166 struct vnode *vp;
167 struct vattr attr;
168 struct filehdr *fhdr;
169 struct aouthdr *ahdr;
170 struct scnhdr *scns;
171 char *ptr = 0;
172 int nscns;
173 unsigned long text_offset = 0, text_address = 0, text_size = 0;
174 unsigned long data_offset = 0, data_address = 0, data_size = 0;
175 unsigned long bss_size = 0;
176 int i;
177
178 /* XXX use of 'curproc' should be 'p'?*/
179 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_SYSSPACE, name, curproc);
180
181 error = namei(&nd);
182 if (error)
183 return error;
184
185 vp = nd.ni_vp;
186 if (vp == NULL)
187 return ENOEXEC;
188
189 if (vp->v_writecount) {
190 error = ETXTBSY;
191 goto fail;
192 }
193
194 if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p))
195 goto fail;
196
197 if ((vp->v_mount->mnt_flag & MNT_NOEXEC)
198 || ((attr.va_mode & 0111) == 0)
199 || (attr.va_type != VREG))
200 goto fail;
201
202 if (attr.va_size == 0) {
203 error = ENOEXEC;
204 goto fail;
205 }
206
207 if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p))
208 goto fail;
209
210 if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p))
211 goto fail;
212
213 /*
214 * Lose the lock on the vnode. It's no longer needed, and must not
215 * exist for the pagefault paging to work below.
216 */
217 VOP_UNLOCK(vp);
218
219 if (error = vm_mmap(kernel_map,
220 (vm_offset_t *) &ptr,
221 PAGE_SIZE,
222 VM_PROT_READ,
223 VM_PROT_READ,
224 0,
225 (caddr_t) vp,
226 0))
227 goto fail;
228
229 fhdr = (struct filehdr *)ptr;
230
231 if (fhdr->f_magic != I386_COFF) {
232 error = ENOEXEC;
233 goto dealloc_and_fail;
234 }
235
236 nscns = fhdr->f_nscns;
237
238 if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) {
239 /*
240 * XXX -- just fail. I'm so lazy.
241 */
242 error = ENOEXEC;
243 goto dealloc_and_fail;
244 }
245
246 ahdr = (struct aouthdr*)(ptr + sizeof(struct filehdr));
247
248 scns = (struct scnhdr*)(ptr + sizeof(struct filehdr)
249 + sizeof(struct aouthdr));
250
251 for (i = 0; i < nscns; i++) {
252 if (scns[i].s_flags & STYP_NOLOAD)
253 continue;
254 else if (scns[i].s_flags & STYP_TEXT) {
255 text_address = scns[i].s_vaddr;
256 text_size = scns[i].s_size;
257 text_offset = scns[i].s_scnptr;
258 }
259 else if (scns[i].s_flags & STYP_DATA) {
260 data_address = scns[i].s_vaddr;
261 data_size = scns[i].s_size;
262 data_offset = scns[i].s_scnptr;
263 } else if (scns[i].s_flags & STYP_BSS) {
264 bss_size = scns[i].s_size;
265 }
266 }
267
268 if (error = load_coff_section(vmspace, vp, text_offset,
269 (caddr_t)text_address,
270 text_size, text_size,
271 VM_PROT_READ | VM_PROT_EXECUTE)) {
272 goto dealloc_and_fail;
273 }
274 if (error = load_coff_section(vmspace, vp, data_offset,
275 (caddr_t)data_address,
276 data_size + bss_size, data_size,
277 VM_PROT_ALL)) {
278 goto dealloc_and_fail;
279 }
280
281 error = 0;
282
283 dealloc_and_fail:
284 if (vm_map_remove(kernel_map,
285 (vm_offset_t) ptr,
286 (vm_offset_t) ptr + PAGE_SIZE))
287 panic(__FUNCTION__ " vm_map_remove failed");
288
289 fail:
290 vput(nd.ni_vp);
291 FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
292 return error;
293}
294
295int
296exec_coff_imgact(imgp)
297 struct image_params *imgp;
298{
299 struct filehdr *fhdr = (struct filehdr*)imgp->image_header;
300 struct aouthdr *ahdr;
301 struct scnhdr *scns;
302 int i;
303 struct vmspace *vmspace = imgp->proc->p_vmspace;
304 unsigned long vmaddr;
305 int nscns;
306 int error, len;
307 unsigned long text_offset = 0, text_address = 0, text_size = 0;
308 unsigned long data_offset = 0, data_address = 0, data_size = 0;
309 unsigned long bss_size = 0;
310 int need_hack_p;
311 unsigned long data_end;
312 unsigned long data_map_start, data_map_len, data_map_addr = 0;
313 unsigned long bss_address, bss_map_start, data_copy_len, bss_map_len;
314 unsigned char *data_buf = 0;
315 caddr_t hole;
316
317 if (fhdr->f_magic != I386_COFF ||
318 !(fhdr->f_flags & F_EXEC)) {
319
320 DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__));
321 return -1;
322 }
323
324 nscns = fhdr->f_nscns;
325 if ((nscns * sizeof(struct scnhdr)) > PAGE_SIZE) {
326 /*
327 * For now, return an error -- need to be able to
328 * read in all of the section structures.
329 */
330
331 DPRINTF(("%s(%d): return -1\n", __FILE__, __LINE__));
332 return -1;
333 }
334
335 ahdr = (struct aouthdr*)((char*)(imgp->image_header) +
336 sizeof(struct filehdr));
337 imgp->entry_addr = ahdr->entry;
338
339 scns = (struct scnhdr*)((char*)(imgp->image_header) +
340 sizeof(struct filehdr) +
341 sizeof(struct aouthdr));
342
343 if (error = exec_extract_strings(imgp)) {
344 DPRINTF(("%s(%d): return %d\n", __FILE__, __LINE__, error));
345 return error;
346 }
347
348 exec_new_vmspace(imgp);
349
350 for (i = 0; i < nscns; i++) {
351
352 DPRINTF(("i = %d, scns[i].s_name = %s, scns[i].s_vaddr = %08lx, "
353 "scns[i].s_scnptr = %d\n", i, scns[i].s_name,
354 scns[i].s_vaddr, scns[i].s_scnptr));
355 if (scns[i].s_flags & STYP_NOLOAD) {
356 /*
357 * A section that is not loaded, for whatever
358 * reason. It takes precedance over other flag
359 * bits...
360 */
361 continue;
362 } else if (scns[i].s_flags & STYP_TEXT) {
363 text_address = scns[i].s_vaddr;
364 text_size = scns[i].s_size;
365 text_offset = scns[i].s_scnptr;
366 } else if (scns[i].s_flags & STYP_DATA) {
367 /* .data section */
368 data_address = scns[i].s_vaddr;
369 data_size = scns[i].s_size;
370 data_offset = scns[i].s_scnptr;
371 } else if (scns[i].s_flags & STYP_BSS) {
372 /* .bss section */
373 bss_size = scns[i].s_size;
374 } else if (scns[i].s_flags & STYP_LIB) {
375 char *buf = 0, *ptr;
376 int foff = trunc_page(scns[i].s_scnptr);
377 int off = scns[i].s_scnptr - foff;
378 int len = round_page(scns[i].s_size + PAGE_SIZE);
379 int j;
380
381 if (error = vm_mmap(kernel_map,
382 (vm_offset_t *) &buf,
383 len,
384 VM_PROT_READ,
385 VM_PROT_READ,
386 0,
387 (caddr_t) imgp->vp,
388 foff)) {
389 return ENOEXEC;
390 }
391 if(scns[i].s_size) {
392 char *libbuf;
393 int emul_path_len = strlen(ibcs2_emul_path);
394
395 libbuf = malloc(MAXPATHLEN + emul_path_len,
396 M_TEMP, M_WAITOK);
397 strcpy(libbuf, ibcs2_emul_path);
398
399 for (j = off; j < scns[i].s_size + off; j++) {
400 char *libname;
401
402 libname = buf + j + 4 * *(long*)(buf + j + 4);
403 j += 4* *(long*)(buf + j);
404
405 DPRINTF(("%s(%d): shared library %s\n",
406 __FILE__, __LINE__, libname));
407 strcpy(&libbuf[emul_path_len], libname);
408 error = coff_load_file(imgp->proc, libbuf);
409 if (error)
410 error = coff_load_file(imgp->proc,
411 libname);
412 if (error)
413 break;
414 }
415 free(libbuf, M_TEMP);
416 }
417 if (vm_map_remove(kernel_map,
418 (vm_offset_t) buf,
419 (vm_offset_t) buf + len))
420 panic("exec_coff_imgact vm_map_remove failed");
421 if (error)
422 return error;
423 }
424 }
425 /*
426 * Map in .text now
427 */
428
429 DPRINTF(("%s(%d): load_coff_section(vmspace, "
430 "imgp->vp, %08lx, %08lx, 0x%x, 0x%x, 0x%x)\n",
431 __FILE__, __LINE__, text_offset, text_address,
432 text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE));
433 if (error = load_coff_section(vmspace, imgp->vp,
434 text_offset, (caddr_t)text_address,
435 text_size, text_size,
436 VM_PROT_READ | VM_PROT_EXECUTE)) {
437 DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error));
438 return error;
439 }
440 /*
441 * Map in .data and .bss now
442 */
443
444
445 DPRINTF(("%s(%d): load_coff_section(vmspace, "
446 "imgp->vp, 0x%08lx, 0x%08lx, 0x%x, 0x%x, 0x%x)\n",
447 __FILE__, __LINE__, data_offset, data_address,
448 data_size + bss_size, data_size, VM_PROT_ALL));
449 if (error = load_coff_section(vmspace, imgp->vp,
450 data_offset, (caddr_t)data_address,
451 data_size + bss_size, data_size,
452 VM_PROT_ALL)) {
453
454 DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error));
455 return error;
456 }
457
458 imgp->interpreted = 0;
459 imgp->proc->p_sysent = &ibcs2_svr3_sysvec;
460
461 vmspace->vm_tsize = round_page(text_size) >> PAGE_SHIFT;
462 vmspace->vm_dsize = round_page(data_size + bss_size) >> PAGE_SHIFT;
463 vmspace->vm_taddr = (caddr_t)text_address;
464 vmspace->vm_daddr = (caddr_t)data_address;
465
466 hole = (caddr_t)trunc_page(vmspace->vm_daddr) + ctob(vmspace->vm_dsize);
467
468
469 DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n",
470 __FILE__, __LINE__, hole));
471 DPRINTF(("imgact: error = %d\n", error));
472
473 error = vm_map_find(&vmspace->vm_map, NULL, 0,
474 (vm_offset_t *) &hole, PAGE_SIZE, FALSE,
475 VM_PROT_ALL, VM_PROT_ALL, 0);
476
477 DPRINTF(("IBCS2: start vm_dsize = 0x%x, vm_daddr = 0x%x end = 0x%x\n",
478 ctob(vmspace->vm_dsize), vmspace->vm_daddr,
479 ctob(vmspace->vm_dsize) + vmspace->vm_daddr ));
480 DPRINTF(("%s(%d): returning successfully!\n", __FILE__, __LINE__));
481
482 /* Indicate that this file should not be modified */
483 imgp->vp->v_flag |= VTEXT;
484 return 0;
485}
486
487/*
488 * Tell kern_execve.c about it, with a little help from the linker.
489 * Since `const' objects end up in the text segment, TEXT_SET is the
490 * correct directive to use.
491 */
492const struct execsw coff_execsw = { exec_coff_imgact, "coff" };
493TEXT_SET(execsw_set, coff_execsw);