exec_subr.c revision 1.4 1 /*
2 * Copyright (c) 1993, 1994 Christopher G. Demetriou
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Christopher G. Demetriou.
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software withough specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id: exec_subr.c,v 1.4 1994/01/16 03:07:33 cgd Exp $
31 */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/proc.h>
36 #include <sys/malloc.h>
37 #include <sys/vnode.h>
38 #include <sys/filedesc.h>
39 #include <sys/exec.h>
40 #include <sys/mman.h>
41
42 #include <vm/vm.h>
43 #include <vm/vm_user.h>
44
45 #ifdef DEBUG
46 /*
47 * new_vmcmd():
48 * create a new vmcmd structure and fill in its fields based
49 * on function call arguments. make sure objects ref'd by
50 * the vmcmd are 'held'.
51 *
52 * If not debugging, this is a macro, so it's expanded inline.
53 */
54
55 void
56 new_vmcmd(evsp, proc, len, addr, vp, offset, prot)
57 struct exec_vmcmd_set *evsp;
58 int (*proc) __P((struct proc * p, struct exec_vmcmd *));
59 u_long len;
60 u_long addr;
61 struct vnode *vp;
62 u_long offset;
63 u_int prot;
64 {
65 struct exec_vmcmd *vcp;
66
67 if (evsp->evs_used >= evsp->evs_cnt)
68 vmcmdset_extend(evsp);
69 vcp = &evsp->evs_cmds[evsp->evs_used++];
70 vcp->ev_proc = proc;
71 vcp->ev_len = len;
72 vcp->ev_addr = addr;
73 if ((vcp->ev_vp = vp) != NULL)
74 vref(vp);
75 vcp->ev_offset = offset;
76 vcp->ev_prot = prot;
77 }
78 #endif /* DEBUG */
79
80 void
81 vmcmdset_extend(evsp)
82 struct exec_vmcmd_set *evsp;
83 {
84 struct exec_vmcmd *nvcp;
85 u_int ocnt;
86
87 #ifdef DIAGNOSTIC
88 if (evsp->evs_used < evsp->evs_cnt)
89 panic("vmcmdset_extend: not necessary");
90 #endif
91
92 /* figure out number of entries in new set */
93 ocnt = evsp->evs_cnt;
94 evsp->evs_cnt += ocnt ? ocnt : EXEC_DEFAULT_VMCMD_SETSIZE;
95
96 /* allocate it */
97 MALLOC(nvcp, struct exec_vmcmd *,
98 (evsp->evs_cnt * sizeof(struct exec_vmcmd)), M_EXEC, M_WAITOK);
99
100 /* free the old struct, if there was one, and record the new one */
101 if (ocnt) {
102 bcopy(evsp->evs_cmds, nvcp, (ocnt * sizeof(struct exec_vmcmd)));
103 FREE(evsp->evs_cmds, M_EXEC);
104 }
105 evsp->evs_cmds = nvcp;
106 }
107
108 void
109 kill_vmcmds(evsp)
110 struct exec_vmcmd_set *evsp;
111 {
112 struct exec_vmcmd *vcp;
113 int i;
114
115 if (evsp->evs_cnt == 0)
116 return;
117
118 for (i = 0; i < evsp->evs_used; i++) {
119 vcp = &evsp->evs_cmds[i];
120 if (vcp->ev_vp != NULLVP)
121 vrele(vcp->ev_vp);
122 }
123 evsp->evs_used = evsp->evs_cnt = 0;
124 FREE(evsp->evs_cmds, M_EXEC);
125 }
126
127 /*
128 * vmcmd_map_pagedvn():
129 * handle vmcmd which specifies that a vnode should be mmap'd.
130 * appropriate for handling demand-paged text and data segments.
131 */
132
133 int
134 vmcmd_map_pagedvn(p, cmd)
135 struct proc *p;
136 struct exec_vmcmd *cmd;
137 {
138 /*
139 * note that if you're going to map part of an process as being
140 * paged from a vnode, that vnode had damn well better be marked as
141 * VTEXT. that's handled in the routine which sets up the vmcmd to
142 * call this routine.
143 */
144 return vm_mmap(&p->p_vmspace->vm_map, &cmd->ev_addr, cmd->ev_len,
145 cmd->ev_prot, VM_PROT_ALL, MAP_FIXED|MAP_FILE|MAP_COPY,
146 cmd->ev_vp, cmd->ev_offset);
147 }
148
149 /*
150 * vmcmd_map_readvn():
151 * handle vmcmd which specifies that a vnode should be read from.
152 * appropriate for non-demand-paged text/data segments, i.e. impure
153 * objects (a la OMAGIC and NMAGIC).
154 */
155 int
156 vmcmd_map_readvn(p, cmd)
157 struct proc *p;
158 struct exec_vmcmd *cmd;
159 {
160 int error;
161
162 error = vm_allocate(&p->p_vmspace->vm_map, &cmd->ev_addr,
163 cmd->ev_len, 0);
164 if (error)
165 return error;
166
167 error = vn_rdwr(UIO_READ, cmd->ev_vp, (caddr_t)cmd->ev_addr,
168 cmd->ev_len, cmd->ev_offset, UIO_USERSPACE, IO_UNIT|IO_NODELOCKED,
169 p->p_ucred, (int *)0, p);
170 if (error)
171 return error;
172
173 return vm_protect(&p->p_vmspace->vm_map, cmd->ev_addr, cmd->ev_len,
174 FALSE, cmd->ev_prot);
175 }
176
177 /*
178 * vmcmd_map_zero():
179 * handle vmcmd which specifies a zero-filled address space region. The
180 * address range must be first allocated, then protected appropriately.
181 */
182
183 int
184 vmcmd_map_zero(p, cmd)
185 struct proc *p;
186 struct exec_vmcmd *cmd;
187 {
188 int error;
189
190 error = vm_allocate(&p->p_vmspace->vm_map, &cmd->ev_addr,
191 cmd->ev_len, 0);
192 if (error)
193 return error;
194
195 return vm_protect(&p->p_vmspace->vm_map, cmd->ev_addr, cmd->ev_len,
196 FALSE, cmd->ev_prot);
197 }
198
199 void
200 exec_closefd(p, fd)
201 struct proc *p;
202 int fd;
203 {
204 if (p->p_fd->fd_lastfile == fd)
205 p->p_fd->fd_lastfile--;
206 if (p->p_fd->fd_freefile > fd)
207 p->p_fd->fd_freefile = fd;
208 closef(p->p_fd->fd_ofiles[fd], p);
209 p->p_fd->fd_ofiles[fd] = 0;
210 }
211