Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / compat / ibcs2 / ibcs2_exec_coff.c
bloba48b395e34faefd3027ace121d5dd1ec934922bd
1 /* $NetBSD: ibcs2_exec_coff.c,v 1.23 2007/12/08 19:29:38 pooka Exp $ */
3 /*
4 * Copyright (c) 1994, 1995, 1998 Scott Bartram
5 * Copyright (c) 1994 Adam Glass
6 * Copyright (c) 1993, 1994 Christopher G. Demetriou
7 * All rights reserved.
9 * originally from kern/exec_ecoff.c
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Scott Bartram.
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: ibcs2_exec_coff.c,v 1.23 2007/12/08 19:29:38 pooka Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/proc.h>
44 #include <sys/malloc.h>
45 #include <sys/namei.h>
46 #include <sys/vnode.h>
47 #include <sys/mount.h>
48 #include <sys/exec.h>
49 #include <sys/exec_coff.h>
50 #include <sys/resourcevar.h>
52 #include <sys/mman.h>
54 #include <sys/cpu.h>
55 #include <machine/reg.h>
56 #include <machine/ibcs2_machdep.h>
58 #include <compat/ibcs2/ibcs2_types.h>
59 #include <compat/ibcs2/ibcs2_exec.h>
60 #include <compat/ibcs2/ibcs2_errno.h>
61 #include <compat/ibcs2/ibcs2_util.h>
64 int exec_ibcs2_coff_prep_omagic(struct lwp *, struct exec_package *,
65 struct coff_filehdr *,
66 struct coff_aouthdr *);
67 int exec_ibcs2_coff_prep_nmagic(struct lwp *, struct exec_package *,
68 struct coff_filehdr *,
69 struct coff_aouthdr *);
70 int exec_ibcs2_coff_prep_zmagic(struct lwp *, struct exec_package *,
71 struct coff_filehdr *,
72 struct coff_aouthdr *);
73 void cpu_exec_ibcs2_coff_setup(int, struct proc *, struct exec_package *,
74 void *);
76 static int coff_load_shlib(struct lwp *, const char *,
77 struct exec_package *);
78 static int coff_find_section(struct lwp *, struct vnode *,
79 struct coff_filehdr *, struct coff_scnhdr *,
80 int);
83 * exec_ibcs2_coff_makecmds(): Check if it's an coff-format executable.
85 * Given a proc pointer and an exec package pointer, see if the referent
86 * of the epp is in coff format. Check 'standard' magic numbers for
87 * this architecture. If that fails, return failure.
89 * This function is responsible for creating a set of vmcmds which can be
90 * used to build the process's vm space and inserting them into the exec
91 * package.
94 int
95 exec_ibcs2_coff_makecmds(struct lwp *l, struct exec_package *epp)
97 int error;
98 struct coff_filehdr *fp = epp->ep_hdr;
99 struct coff_aouthdr *ap;
101 if (epp->ep_hdrvalid < COFF_HDR_SIZE) {
102 DPRINTF(("ibcs2: bad coff hdr size\n"));
103 return ENOEXEC;
106 if (COFF_BADMAG(fp)) {
107 DPRINTF(("ibcs2: bad coff magic\n"));
108 return ENOEXEC;
111 ap = (void *)((char *)epp->ep_hdr + sizeof(struct coff_filehdr));
112 switch (ap->a_magic) {
113 case COFF_OMAGIC:
114 error = exec_ibcs2_coff_prep_omagic(l, epp, fp, ap);
115 break;
116 case COFF_NMAGIC:
117 error = exec_ibcs2_coff_prep_nmagic(l, epp, fp, ap);
118 break;
119 case COFF_ZMAGIC:
120 error = exec_ibcs2_coff_prep_zmagic(l, epp, fp, ap);
121 break;
122 default:
123 return ENOEXEC;
126 if (error)
127 kill_vmcmds(&epp->ep_vmcmds);
129 return error;
133 * exec_ibcs2_coff_prep_omagic(): Prepare a COFF OMAGIC binary's exec package
137 exec_ibcs2_coff_prep_omagic(struct lwp *l, struct exec_package *epp, struct coff_filehdr *fp, struct coff_aouthdr *ap)
139 epp->ep_taddr = COFF_SEGMENT_ALIGN(fp, ap, ap->a_tstart);
140 epp->ep_tsize = ap->a_tsize;
141 epp->ep_daddr = COFF_SEGMENT_ALIGN(fp, ap, ap->a_dstart);
142 epp->ep_dsize = ap->a_dsize;
143 epp->ep_entry = ap->a_entry;
145 DPRINTF(("ibcs2_omagic: text=%#lx/%#lx, data=%#lx/%#lx, bss=%#lx/%#lx, entry=%#lx\n",
146 epp->ep_taddr, epp->ep_tsize,
147 epp->ep_daddr, epp->ep_dsize,
148 ap->a_dstart + ap->a_dsize, ap->a_bsize,
149 epp->ep_entry));
151 /* set up command for text and data segments */
152 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
153 ap->a_tsize + ap->a_dsize, epp->ep_taddr, epp->ep_vp,
154 COFF_TXTOFF(fp, ap),
155 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
157 /* set up command for bss segment */
158 if (ap->a_bsize > 0) {
159 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, ap->a_bsize,
160 COFF_SEGMENT_ALIGN(fp, ap, ap->a_dstart + ap->a_dsize),
161 NULLVP, 0,
162 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
163 epp->ep_dsize += ap->a_bsize;
165 /* The following is to make obreak(2) happy. It expects daddr
166 * to on a page boundary and will round up dsize to a page
167 * address.
169 if (trunc_page(epp->ep_daddr) != epp->ep_daddr) {
170 epp->ep_dsize += epp->ep_daddr - trunc_page(epp->ep_daddr);
171 epp->ep_daddr = trunc_page(epp->ep_daddr);
172 if (epp->ep_taddr + epp->ep_tsize > epp->ep_daddr)
173 epp->ep_tsize = epp->ep_daddr - epp->ep_taddr;
176 return (*epp->ep_esch->es_setup_stack)(l, epp);
180 * exec_ibcs2_coff_prep_nmagic(): Prepare a 'native' NMAGIC COFF binary's exec
181 * package.
185 exec_ibcs2_coff_prep_nmagic(struct lwp *l, struct exec_package *epp, struct coff_filehdr *fp, struct coff_aouthdr *ap)
187 long toverlap, doverlap;
188 u_long tsize, tend;
190 epp->ep_taddr = ap->a_tstart;
191 epp->ep_tsize = ap->a_tsize;
192 epp->ep_daddr = ap->a_dstart;
193 epp->ep_dsize = ap->a_dsize;
194 epp->ep_entry = ap->a_entry;
196 DPRINTF(("ibcs2_nmagic: text=%#lx/%#lx, data=%#lx/%#lx, bss=%#lx/%#lx, entry=%#lx\n",
197 epp->ep_taddr, epp->ep_tsize,
198 epp->ep_daddr, epp->ep_dsize,
199 ap->a_dstart + ap->a_dsize, ap->a_bsize,
200 epp->ep_entry));
202 /* Do the text and data pages overlap?
204 tend = epp->ep_taddr + epp->ep_tsize - 1;
205 if (trunc_page(tend) == trunc_page(epp->ep_daddr)) {
206 /* If the first page of text is the first page of data,
207 * then we consider it all data.
209 if (trunc_page(epp->ep_taddr) == trunc_page(epp->ep_daddr)) {
210 tsize = 0;
211 } else {
212 tsize = trunc_page(tend) - epp->ep_taddr;
215 /* If the text and data file and VA offsets are the
216 * same, simply bring the data segment to start on
217 * the start of the page.
219 if (epp->ep_daddr - epp->ep_taddr ==
220 COFF_DATOFF(fp, ap) - COFF_TXTOFF(fp, ap)) {
221 u_long diff = epp->ep_daddr - trunc_page(epp->ep_daddr);
222 toverlap = 0;
223 doverlap = -diff;
224 } else {
225 /* otherwise copy the individual pieces */
226 toverlap = epp->ep_tsize - tsize;
227 doverlap = round_page(epp->ep_daddr) - epp->ep_daddr;
228 if (doverlap > epp->ep_dsize)
229 doverlap = epp->ep_dsize;
231 } else {
232 tsize = epp->ep_tsize;
233 toverlap = 0;
234 doverlap = 0;
237 DPRINTF(("nmagic_vmcmds:"));
238 if (tsize > 0) {
239 /* set up command for text segment */
240 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, tsize,
241 epp->ep_taddr, epp->ep_vp, COFF_TXTOFF(fp, ap),
242 VM_PROT_READ|VM_PROT_EXECUTE);
243 DPRINTF((" map_readvn(%#lx/%#lx@%#lx)",
244 epp->ep_taddr, tsize, (u_long) COFF_TXTOFF(fp, ap)));
246 if (toverlap > 0) {
247 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, toverlap,
248 epp->ep_taddr + tsize, epp->ep_vp,
249 COFF_TXTOFF(fp, ap) + tsize,
250 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
251 DPRINTF((" map_readvn(%#lx/%#lx@%#lx)",
252 epp->ep_taddr + tsize, toverlap,
253 COFF_TXTOFF(fp, ap) + tsize));
254 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_readvn, doverlap,
255 epp->ep_daddr, epp->ep_vp,
256 COFF_DATOFF(fp, ap),
257 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
258 DPRINTF((" readvn(%#lx/%#lx@%#lx)", epp->ep_daddr, doverlap,
259 COFF_DATOFF(fp, ap)));
262 if (epp->ep_dsize > doverlap || doverlap < 0) {
263 /* set up command for data segment */
264 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
265 epp->ep_dsize - doverlap, epp->ep_daddr + doverlap,
266 epp->ep_vp, COFF_DATOFF(fp, ap) + doverlap,
267 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
268 DPRINTF((" map_readvn(%#lx/%#lx@%#lx)",
269 epp->ep_daddr + doverlap, epp->ep_dsize - doverlap,
270 COFF_DATOFF(fp, ap) + doverlap));
273 /* Handle page remainders for pagedvn.
276 /* set up command for bss segment */
277 if (ap->a_bsize > 0) {
278 u_long dend = round_page(epp->ep_daddr + epp->ep_dsize);
279 u_long dspace = dend - (epp->ep_daddr + epp->ep_dsize);
280 if (ap->a_bsize > dspace) {
281 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero,
282 ap->a_bsize - dspace, dend, NULLVP, 0,
283 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
284 DPRINTF((" map_zero(%#lx/%#lx)",
285 dend, ap->a_bsize - dspace));
287 epp->ep_dsize += ap->a_bsize;
289 DPRINTF(("\n"));
290 /* The following is to make obreak(2) happy. It expects daddr
291 * to on a page boundary and will round up dsize to a page
292 * address.
294 if (trunc_page(epp->ep_daddr) != epp->ep_daddr) {
295 epp->ep_dsize += epp->ep_daddr - trunc_page(epp->ep_daddr);
296 epp->ep_daddr = trunc_page(epp->ep_daddr);
297 if (epp->ep_taddr + epp->ep_tsize > epp->ep_daddr)
298 epp->ep_tsize = epp->ep_daddr - epp->ep_taddr;
301 return (*epp->ep_esch->es_setup_stack)(l, epp);
305 * coff_find_section - load specified section header
307 * TODO - optimize by reading all section headers in at once
310 static int
311 coff_find_section(struct lwp *l, struct vnode *vp, struct coff_filehdr *fp, struct coff_scnhdr *sh, int s_type)
313 int i, pos, siz, error;
314 size_t resid;
316 pos = COFF_HDR_SIZE;
317 for (i = 0; i < fp->f_nscns; i++, pos += sizeof(struct coff_scnhdr)) {
318 siz = sizeof(struct coff_scnhdr);
319 error = vn_rdwr(UIO_READ, vp, (void *) sh,
320 siz, pos, UIO_SYSSPACE, IO_NODELOCKED, l->l_cred,
321 &resid, NULL);
322 if (error) {
323 DPRINTF(("section hdr %d read error %d\n", i, error));
324 return error;
326 siz -= resid;
327 if (siz != sizeof(struct coff_scnhdr)) {
328 DPRINTF(("incomplete read: hdr %d ask=%d, rem=%lu got %d\n",
329 s_type, sizeof(struct coff_scnhdr),
330 (u_long) resid, siz));
331 return ENOEXEC;
333 /* DPRINTF(("found section: %x\n", sh->s_flags)); */
334 if (sh->s_flags == s_type)
335 return 0;
337 return ENOEXEC;
341 * exec_ibcs2_coff_prep_zmagic(): Prepare a COFF ZMAGIC binary's exec package
343 * First, set the various offsets/lengths in the exec package.
345 * Then, mark the text image busy (so it can be demand paged) or error
346 * out if this is not possible. Finally, set up vmcmds for the
347 * text, data, bss, and stack segments.
351 exec_ibcs2_coff_prep_zmagic(struct lwp *l, struct exec_package *epp, struct coff_filehdr *fp, struct coff_aouthdr *ap)
353 int error;
354 u_long offset;
355 long dsize, baddr, bsize;
356 struct coff_scnhdr sh;
358 /* DPRINTF(("enter exec_ibcs2_coff_prep_zmagic\n")); */
360 /* set up command for text segment */
361 error = coff_find_section(l, epp->ep_vp, fp, &sh, COFF_STYP_TEXT);
362 if (error) {
363 DPRINTF(("can't find text section: %d\n", error));
364 return error;
366 /* DPRINTF(("COFF text addr %x size %d offset %d\n", sh.s_vaddr,
367 sh.s_size, sh.s_scnptr)); */
368 epp->ep_taddr = COFF_ALIGN(sh.s_vaddr);
369 offset = sh.s_scnptr - (sh.s_vaddr - epp->ep_taddr);
370 epp->ep_tsize = sh.s_size + (sh.s_vaddr - epp->ep_taddr);
372 /* DPRINTF(("VMCMD: addr %x size %d offset %d\n", epp->ep_taddr,
373 epp->ep_tsize, offset)); */
374 #ifdef notyet
375 error = vn_marktext(epp->ep_vp);
376 if (error)
377 return (error);
379 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, epp->ep_tsize,
380 epp->ep_taddr, epp->ep_vp, offset,
381 VM_PROT_READ|VM_PROT_EXECUTE);
382 #else
383 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, epp->ep_tsize,
384 epp->ep_taddr, epp->ep_vp, offset,
385 VM_PROT_READ|VM_PROT_EXECUTE);
386 #endif
388 /* set up command for data segment */
389 error = coff_find_section(l, epp->ep_vp, fp, &sh, COFF_STYP_DATA);
390 if (error) {
391 DPRINTF(("can't find data section: %d\n", error));
392 return error;
394 /* DPRINTF(("COFF data addr %x size %d offset %d\n", sh.s_vaddr,
395 sh.s_size, sh.s_scnptr)); */
396 epp->ep_daddr = COFF_ALIGN(sh.s_vaddr);
397 offset = sh.s_scnptr - (sh.s_vaddr - epp->ep_daddr);
398 dsize = sh.s_size + (sh.s_vaddr - epp->ep_daddr);
399 epp->ep_dsize = dsize + ap->a_bsize;
401 /* DPRINTF(("VMCMD: addr %x size %d offset %d\n", epp->ep_daddr,
402 dsize, offset)); */
403 #ifdef notyet
404 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, dsize,
405 epp->ep_daddr, epp->ep_vp, offset,
406 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
407 #else
408 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
409 dsize, epp->ep_daddr, epp->ep_vp, offset,
410 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
411 #endif
413 /* set up command for bss segment */
414 baddr = round_page(epp->ep_daddr + dsize);
415 bsize = epp->ep_daddr + epp->ep_dsize - baddr;
416 if (bsize > 0) {
417 /* DPRINTF(("VMCMD: addr %x size %d offset %d\n",
418 baddr, bsize, 0)); */
419 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero,
420 bsize, baddr, NULLVP, 0,
421 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
424 /* load any shared libraries */
425 error = coff_find_section(l, epp->ep_vp, fp, &sh, COFF_STYP_SHLIB);
426 if (!error) {
427 size_t resid;
428 struct coff_slhdr *slhdr;
429 char *tbuf, *bufp;
430 size_t len = sh.s_size, path_index, entry_len;
432 if (len > 64 * 1024)
433 return ENOEXEC;
435 tbuf = malloc(len, M_TEMP, M_WAITOK);
436 if (tbuf == NULL)
437 return ENOEXEC;
439 /* DPRINTF(("COFF shlib size %d offset %d\n",
440 sh.s_size, sh.s_scnptr)); */
442 error = vn_rdwr(UIO_READ, epp->ep_vp, tbuf,
443 len, sh.s_scnptr,
444 UIO_SYSSPACE, IO_NODELOCKED, l->l_cred,
445 &resid, NULL);
446 if (error) {
447 DPRINTF(("shlib section read error %d\n", error));
448 free(tbuf, M_TEMP);
449 return ENOEXEC;
451 bufp = tbuf;
452 while (len) {
453 slhdr = (struct coff_slhdr *)bufp;
455 if (slhdr->path_index > LONG_MAX / sizeof(long) ||
456 slhdr->entry_len > LONG_MAX / sizeof(long)) {
457 free(tbuf, M_TEMP);
458 return ENOEXEC;
461 path_index = slhdr->path_index * sizeof(long);
462 entry_len = slhdr->entry_len * sizeof(long);
464 if (entry_len > len) {
465 free(tbuf, M_TEMP);
466 return ENOEXEC;
469 /* DPRINTF(("path_index: %d entry_len: %d name: %s\n",
470 path_index, entry_len, slhdr->sl_name)); */
472 error = coff_load_shlib(l, slhdr->sl_name, epp);
473 if (error) {
474 free(tbuf, M_TEMP);
475 return ENOEXEC;
477 bufp += entry_len;
478 len -= entry_len;
480 free(tbuf, M_TEMP);
483 /* set up entry point */
484 epp->ep_entry = ap->a_entry;
486 DPRINTF(("ibcs2_zmagic: text addr: %#lx size: %#lx data addr: %#lx size: %#lx entry: %#lx\n",
487 epp->ep_taddr, epp->ep_tsize,
488 epp->ep_daddr, epp->ep_dsize,
489 epp->ep_entry));
491 /* The following is to make obreak(2) happy. It expects daddr
492 * to on a page boundary and will round up dsize to a page
493 * address.
495 if (trunc_page(epp->ep_daddr) != epp->ep_daddr) {
496 epp->ep_dsize += epp->ep_daddr - trunc_page(epp->ep_daddr);
497 epp->ep_daddr = trunc_page(epp->ep_daddr);
498 if (epp->ep_taddr + epp->ep_tsize > epp->ep_daddr)
499 epp->ep_tsize = epp->ep_daddr - epp->ep_taddr;
503 return (*epp->ep_esch->es_setup_stack)(l, epp);
506 static int
507 coff_load_shlib(struct lwp *l, const char *path, struct exec_package *epp)
509 int error, siz;
510 int taddr, tsize, daddr, dsize, offset;
511 size_t resid;
512 struct vnode *vp;
513 struct coff_filehdr fh, *fhp = &fh;
514 struct coff_scnhdr sh, *shp = &sh;
517 * 1. open shlib file
518 * 2. read filehdr
519 * 3. map text, data, and bss out of it using VM_*
521 /* first get the vnode */
522 error = namei_simple_kernel(path, NSM_FOLLOW_TRYEMULROOT, &vp);
523 if (error != 0) {
524 DPRINTF(("coff_load_shlib: can't find library %s\n", path));
525 return error;
528 siz = sizeof(struct coff_filehdr);
529 error = vn_rdwr(UIO_READ, vp, (void *) fhp, siz, 0,
530 UIO_SYSSPACE, IO_NODELOCKED, l->l_cred, &resid, l);
531 if (error) {
532 DPRINTF(("filehdr read error %d\n", error));
533 vrele(vp);
534 return error;
536 siz -= resid;
537 if (siz != sizeof(struct coff_filehdr)) {
538 DPRINTF(("coff_load_shlib: incomplete read: ask=%d, rem=%lu got %d\n",
539 sizeof(struct coff_filehdr), (u_long) resid, siz));
540 vrele(vp);
541 return ENOEXEC;
544 /* load text */
545 error = coff_find_section(l, vp, fhp, shp, COFF_STYP_TEXT);
546 if (error) {
547 DPRINTF(("can't find shlib text section\n"));
548 vrele(vp);
549 return error;
551 /* DPRINTF(("COFF text addr %x size %d offset %d\n", sh.s_vaddr,
552 sh.s_size, sh.s_scnptr)); */
553 taddr = COFF_ALIGN(shp->s_vaddr);
554 offset = shp->s_scnptr - (shp->s_vaddr - taddr);
555 tsize = shp->s_size + (shp->s_vaddr - taddr);
556 /* DPRINTF(("VMCMD: addr %x size %d offset %d\n", taddr, tsize, offset)); */
557 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, tsize, taddr,
558 vp, offset,
559 VM_PROT_READ|VM_PROT_EXECUTE);
561 /* load data */
562 error = coff_find_section(l, vp, fhp, shp, COFF_STYP_DATA);
563 if (error) {
564 DPRINTF(("can't find shlib data section\n"));
565 vrele(vp);
566 return error;
568 /* DPRINTF(("COFF data addr %x size %d offset %d\n", shp->s_vaddr,
569 shp->s_size, shp->s_scnptr)); */
570 daddr = COFF_ALIGN(shp->s_vaddr);
571 offset = shp->s_scnptr - (shp->s_vaddr - daddr);
572 dsize = shp->s_size + (shp->s_vaddr - daddr);
573 /* epp->ep_dsize = dsize + ap->a_bsize; */
575 /* DPRINTF(("VMCMD: addr %x size %d offset %d\n", daddr, dsize, offset)); */
576 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
577 dsize, daddr, vp, offset,
578 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
580 /* load bss */
581 error = coff_find_section(l, vp, fhp, shp, COFF_STYP_BSS);
582 if (!error) {
583 int baddr = round_page(daddr + dsize);
584 int bsize = daddr + dsize + shp->s_size - baddr;
585 if (bsize > 0) {
586 /* DPRINTF(("VMCMD: addr %x size %d offset %d\n",
587 baddr, bsize, 0)); */
588 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero,
589 bsize, baddr, NULLVP, 0,
590 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
593 vrele(vp);
595 return 0;