1 /* $NetBSD: darwin_mman.c,v 1.30 2009/01/11 02:45:47 christos Exp $ */
4 * Copyright (c) 2002, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: darwin_mman.c,v 1.30 2009/01/11 02:45:47 christos Exp $");
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/signal.h>
40 #include <sys/mount.h>
42 #include <sys/fcntl.h>
44 #include <sys/filedesc.h>
45 #include <sys/vnode.h>
48 #include <sys/syscallargs.h>
50 #include <compat/sys/signal.h>
52 #include <compat/mach/mach_types.h>
53 #include <compat/mach/mach_vm.h>
55 #include <compat/darwin/darwin_types.h>
56 #include <compat/darwin/darwin_audit.h>
57 #include <compat/darwin/darwin_syscallargs.h>
60 darwin_sys_load_shared_file(struct lwp
*l
, const struct darwin_sys_load_shared_file_args
*uap
, register_t
*retval
)
63 syscallarg(char *) filename;
64 syscallarg(void *) addr;
65 syscallarg(u_long) len;
66 syscallarg(void **) base;
67 syscallarg(int) count:
68 syscallarg(mach_sf_mapping_t *) mappings;
69 syscallarg(int *) flags;
72 struct vnode
*vp
= NULL
;
74 struct proc
*p
= l
->l_proc
;
77 mach_sf_mapping_t
*mapp
= NULL
;
79 struct sys_open_args open_cup
;
80 struct sys_close_args close_cup
;
85 vaddr_t max_addr
, addr
;
89 struct exec_vmcmd evc
;
91 filename
= malloc(MAXPATHLEN
, M_TEMP
, M_WAITOK
);
92 if ((error
= copyin(SCARG(uap
, filename
), filename
, MAXPATHLEN
)) != 0)
95 if ((error
= copyin(SCARG(uap
, base
), &base
, sizeof(base
))) != 0)
98 if ((error
= copyin(SCARG(uap
, flags
), &flags
, sizeof(base
))) != 0)
102 DPRINTF(("darwin_sys_load_shared_file: filename = %p ",
103 SCARG(uap
, filename
)));
104 DPRINTF(("addr = %p len = 0x%08lx base = %p ",
105 SCARG(uap
, addr
), SCARG(uap
, len
), SCARG(uap
, base
)));
106 DPRINTF(("count = %d mappings = %p flags = %p ",
107 SCARG(uap
, count
), SCARG(uap
, mappings
), SCARG(uap
, flags
)));
108 DPRINTF(("*base = 0x%08lx *flags = %d filename=`%s'\n",
109 base
, flags
, filename
));
112 SCARG(&open_cup
, path
) = SCARG(uap
, filename
);
113 SCARG(&open_cup
, flags
) = O_RDONLY
;
114 SCARG(&open_cup
, mode
) = 0;
115 if ((error
= sys_open(l
, &open_cup
, &fdc
)) != 0)
127 if (SCARG(uap
, count
) < 0 ||
128 SCARG(uap
, count
) > PAGE_SIZE
/ sizeof(*mapp
)) {
132 maplen
= SCARG(uap
, count
) * sizeof(*mapp
);
133 mapp
= malloc(maplen
, M_TEMP
, M_WAITOK
);
135 if ((error
= copyin(SCARG(uap
, mappings
), mapp
, maplen
)) != 0)
139 for (i
= 0; i
< SCARG(uap
, count
); i
++) {
140 DPRINTF(("mapp[%d].mapping_offset = 0x%08lx\n",
141 i
, mapp
[i
].mapping_offset
));
142 DPRINTF(("mapp[%d].size = 0x%08lx\n", i
, (long)mapp
[i
].size
));
143 DPRINTF(("mapp[%d].file_offset = 0x%08lx\n",
144 i
, mapp
[i
].file_offset
));
145 DPRINTF(("mapp[%d].protection = %d\n",
146 i
, mapp
[i
].protection
));
147 DPRINTF(("mapp[%d].cksum = %ld\n", i
, mapp
[i
].cksum
));
151 /* Check if we can load at the default addresses */
153 vm_map_lock(&p
->p_vmspace
->vm_map
);
154 for (i
= 0; i
< SCARG(uap
, count
); i
++)
155 if ((uvm_map_findspace(&p
->p_vmspace
->vm_map
,
156 base
+ mapp
[i
].mapping_offset
, mapp
[i
].size
,
157 &uaddr
, NULL
, 0, 0, UVM_FLAG_FIXED
)) == NULL
)
159 vm_map_unlock(&p
->p_vmspace
->vm_map
);
161 /* If we cannot, we need a relocation */
162 if (need_relocation
) {
163 DPRINTF(("Relocating\n"));
164 /* Compute the length of the region enclosing all sections */
166 for (i
= 0; i
< SCARG(uap
, count
); i
++) {
167 addr
= (vaddr_t
)(mapp
[i
].mapping_offset
168 + base
+ mapp
[i
].size
);
172 len
= max_addr
- base
;
173 DPRINTF(("base = 0x%08lx max_addr = 0x%08lx len = 0x%08x\n",
174 base
, max_addr
, len
));
176 /* Find some place to map this region */
177 vm_map_lock(&p
->p_vmspace
->vm_map
);
178 if ((uvm_map_findspace(&p
->p_vmspace
->vm_map
, base
,
179 len
, &uaddr
, NULL
, 0, PAGE_SIZE
, 0)) == NULL
) {
180 DPRINTF(("Impossible to find some space\n"));
181 vm_map_unlock(&p
->p_vmspace
->vm_map
);
185 vm_map_unlock(&p
->p_vmspace
->vm_map
);
187 /* Update the base address */
189 DPRINTF(("New base address: base = 0x%08lx\n", base
));
192 /* Do the actual mapping */
193 for (i
= 0; i
< SCARG(uap
, count
); i
++) {
194 memset(&evc
, 0, sizeof(evc
));
195 evc
.ev_addr
= base
+ mapp
[i
].mapping_offset
;
196 evc
.ev_len
= mapp
[i
].size
;
197 evc
.ev_prot
= mapp
[i
].protection
& VM_PROT_ALL
;
199 if (mapp
[i
].protection
& MACH_VM_PROT_ZF
)
200 evc
.ev_proc
= vmcmd_map_zero
;
202 evc
.ev_proc
= vmcmd_map_readvn
;
203 evc
.ev_offset
= mapp
[i
].file_offset
;
206 DPRINTF(("map section %d: start = 0x%08lx, len = 0x%08lx\n",
207 i
, evc
.ev_addr
, evc
.ev_len
));
209 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
210 if ((error
= (*evc
.ev_proc
)(l
, &evc
)) != 0) {
212 DPRINTF(("Failed\n"));
216 DPRINTF(("Success\n"));
224 SCARG(&close_cup
, fd
) = fd
;
225 if ((error
= sys_close(l
, &close_cup
, retval
)) != 0)
228 if ((error
= copyout(&base
, SCARG(uap
, base
), sizeof(base
))) != 0)
231 if ((error
= copyout(&flags
, SCARG(uap
, flags
), sizeof(base
))) != 0)
234 free(filename
, M_TEMP
);