1 /* $NetBSD: ibcs2_exec_coff.c,v 1.23 2007/12/08 19:29:38 pooka Exp $ */
4 * Copyright (c) 1994, 1995, 1998 Scott Bartram
5 * Copyright (c) 1994 Adam Glass
6 * Copyright (c) 1993, 1994 Christopher G. Demetriou
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
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>
44 #include <sys/malloc.h>
45 #include <sys/namei.h>
46 #include <sys/vnode.h>
47 #include <sys/mount.h>
49 #include <sys/exec_coff.h>
50 #include <sys/resourcevar.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
*,
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
*,
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
95 exec_ibcs2_coff_makecmds(struct lwp
*l
, struct exec_package
*epp
)
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"));
106 if (COFF_BADMAG(fp
)) {
107 DPRINTF(("ibcs2: bad coff magic\n"));
111 ap
= (void *)((char *)epp
->ep_hdr
+ sizeof(struct coff_filehdr
));
112 switch (ap
->a_magic
) {
114 error
= exec_ibcs2_coff_prep_omagic(l
, epp
, fp
, ap
);
117 error
= exec_ibcs2_coff_prep_nmagic(l
, epp
, fp
, ap
);
120 error
= exec_ibcs2_coff_prep_zmagic(l
, epp
, fp
, ap
);
127 kill_vmcmds(&epp
->ep_vmcmds
);
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
,
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
,
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
),
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
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
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
;
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
,
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
)) {
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
);
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
;
232 tsize
= epp
->ep_tsize
;
237 DPRINTF(("nmagic_vmcmds:"));
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
)));
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
,
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
;
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
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
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
;
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
,
323 DPRINTF(("section hdr %d read error %d\n", i
, error
));
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
));
333 /* DPRINTF(("found section: %x\n", sh->s_flags)); */
334 if (sh
->s_flags
== s_type
)
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
)
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
);
363 DPRINTF(("can't find text section: %d\n", 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)); */
375 error
= vn_marktext(epp
->ep_vp
);
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
);
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
);
388 /* set up command for data segment */
389 error
= coff_find_section(l
, epp
->ep_vp
, fp
, &sh
, COFF_STYP_DATA
);
391 DPRINTF(("can't find data section: %d\n", 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,
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
);
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
);
413 /* set up command for bss segment */
414 baddr
= round_page(epp
->ep_daddr
+ dsize
);
415 bsize
= epp
->ep_daddr
+ epp
->ep_dsize
- baddr
;
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
);
428 struct coff_slhdr
*slhdr
;
430 size_t len
= sh
.s_size
, path_index
, entry_len
;
435 tbuf
= malloc(len
, M_TEMP
, M_WAITOK
);
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
,
444 UIO_SYSSPACE
, IO_NODELOCKED
, l
->l_cred
,
447 DPRINTF(("shlib section read error %d\n", error
));
453 slhdr
= (struct coff_slhdr
*)bufp
;
455 if (slhdr
->path_index
> LONG_MAX
/ sizeof(long) ||
456 slhdr
->entry_len
> LONG_MAX
/ sizeof(long)) {
461 path_index
= slhdr
->path_index
* sizeof(long);
462 entry_len
= slhdr
->entry_len
* sizeof(long);
464 if (entry_len
> len
) {
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
);
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
,
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
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
);
507 coff_load_shlib(struct lwp
*l
, const char *path
, struct exec_package
*epp
)
510 int taddr
, tsize
, daddr
, dsize
, offset
;
513 struct coff_filehdr fh
, *fhp
= &fh
;
514 struct coff_scnhdr sh
, *shp
= &sh
;
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
);
524 DPRINTF(("coff_load_shlib: can't find library %s\n", path
));
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
);
532 DPRINTF(("filehdr read error %d\n", error
));
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
));
545 error
= coff_find_section(l
, vp
, fhp
, shp
, COFF_STYP_TEXT
);
547 DPRINTF(("can't find shlib text section\n"));
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
,
559 VM_PROT_READ
|VM_PROT_EXECUTE
);
562 error
= coff_find_section(l
, vp
, fhp
, shp
, COFF_STYP_DATA
);
564 DPRINTF(("can't find shlib data section\n"));
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
);
581 error
= coff_find_section(l
, vp
, fhp
, shp
, COFF_STYP_BSS
);
583 int baddr
= round_page(daddr
+ dsize
);
584 int bsize
= daddr
+ dsize
+ shp
->s_size
- baddr
;
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
);