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 without 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.7 1994/05/23 03:04:57 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 44 #ifdef DEBUG 45 /* 46 * new_vmcmd(): 47 * create a new vmcmd structure and fill in its fields based 48 * on function call arguments. make sure objects ref'd by 49 * the vmcmd are 'held'. 50 * 51 * If not debugging, this is a macro, so it's expanded inline. 52 */ 53 54 void 55 new_vmcmd(evsp, proc, len, addr, vp, offset, prot) 56 struct exec_vmcmd_set *evsp; 57 int (*proc) __P((struct proc * p, struct exec_vmcmd *)); 58 u_long len; 59 u_long addr; 60 struct vnode *vp; 61 u_long offset; 62 u_int prot; 63 { 64 struct exec_vmcmd *vcp; 65 66 if (evsp->evs_used >= evsp->evs_cnt) 67 vmcmdset_extend(evsp); 68 vcp = &evsp->evs_cmds[evsp->evs_used++]; 69 vcp->ev_proc = proc; 70 vcp->ev_len = len; 71 vcp->ev_addr = addr; 72 if ((vcp->ev_vp = vp) != NULL) 73 vref(vp); 74 vcp->ev_offset = offset; 75 vcp->ev_prot = prot; 76 } 77 #endif /* DEBUG */ 78 79 void 80 vmcmdset_extend(evsp) 81 struct exec_vmcmd_set *evsp; 82 { 83 struct exec_vmcmd *nvcp; 84 u_int ocnt; 85 86 #ifdef DIAGNOSTIC 87 if (evsp->evs_used < evsp->evs_cnt) 88 panic("vmcmdset_extend: not necessary"); 89 #endif 90 91 /* figure out number of entries in new set */ 92 ocnt = evsp->evs_cnt; 93 evsp->evs_cnt += ocnt ? ocnt : EXEC_DEFAULT_VMCMD_SETSIZE; 94 95 /* allocate it */ 96 MALLOC(nvcp, struct exec_vmcmd *, 97 (evsp->evs_cnt * sizeof(struct exec_vmcmd)), M_EXEC, M_WAITOK); 98 99 /* free the old struct, if there was one, and record the new one */ 100 if (ocnt) { 101 bcopy(evsp->evs_cmds, nvcp, (ocnt * sizeof(struct exec_vmcmd))); 102 FREE(evsp->evs_cmds, M_EXEC); 103 } 104 evsp->evs_cmds = nvcp; 105 } 106 107 void 108 kill_vmcmds(evsp) 109 struct exec_vmcmd_set *evsp; 110 { 111 struct exec_vmcmd *vcp; 112 int i; 113 114 if (evsp->evs_cnt == 0) 115 return; 116 117 for (i = 0; i < evsp->evs_used; i++) { 118 vcp = &evsp->evs_cmds[i]; 119 if (vcp->ev_vp != NULLVP) 120 vrele(vcp->ev_vp); 121 } 122 evsp->evs_used = evsp->evs_cnt = 0; 123 FREE(evsp->evs_cmds, M_EXEC); 124 } 125 126 /* 127 * vmcmd_map_pagedvn(): 128 * handle vmcmd which specifies that a vnode should be mmap'd. 129 * appropriate for handling demand-paged text and data segments. 130 */ 131 132 int 133 vmcmd_map_pagedvn(p, cmd) 134 struct proc *p; 135 struct exec_vmcmd *cmd; 136 { 137 /* 138 * note that if you're going to map part of an process as being 139 * paged from a vnode, that vnode had damn well better be marked as 140 * VTEXT. that's handled in the routine which sets up the vmcmd to 141 * call this routine. 142 */ 143 return vm_mmap(&p->p_vmspace->vm_map, &cmd->ev_addr, cmd->ev_len, 144 cmd->ev_prot, VM_PROT_ALL, MAP_FIXED|MAP_COPY, (caddr_t)cmd->ev_vp, 145 cmd->ev_offset); 146 } 147 148 /* 149 * vmcmd_map_readvn(): 150 * handle vmcmd which specifies that a vnode should be read from. 151 * appropriate for non-demand-paged text/data segments, i.e. impure 152 * objects (a la OMAGIC and NMAGIC). 153 */ 154 int 155 vmcmd_map_readvn(p, cmd) 156 struct proc *p; 157 struct exec_vmcmd *cmd; 158 { 159 int error; 160 161 error = vm_allocate(&p->p_vmspace->vm_map, &cmd->ev_addr, 162 cmd->ev_len, 0); 163 if (error) 164 return error; 165 166 error = vn_rdwr(UIO_READ, cmd->ev_vp, (caddr_t)cmd->ev_addr, 167 cmd->ev_len, cmd->ev_offset, UIO_USERSPACE, IO_UNIT|IO_NODELOCKED, 168 p->p_ucred, (int *)0, p); 169 if (error) 170 return error; 171 172 return vm_map_protect(&p->p_vmspace->vm_map, trunc_page(cmd->ev_addr), 173 round_page(cmd->ev_addr + cmd->ev_len), cmd->ev_prot, FALSE); 174 } 175 176 /* 177 * vmcmd_map_zero(): 178 * handle vmcmd which specifies a zero-filled address space region. The 179 * address range must be first allocated, then protected appropriately. 180 */ 181 182 int 183 vmcmd_map_zero(p, cmd) 184 struct proc *p; 185 struct exec_vmcmd *cmd; 186 { 187 int error; 188 189 error = vm_allocate(&p->p_vmspace->vm_map, &cmd->ev_addr, 190 cmd->ev_len, 0); 191 if (error) 192 return error; 193 194 return vm_map_protect(&p->p_vmspace->vm_map, trunc_page(cmd->ev_addr), 195 round_page(cmd->ev_addr + cmd->ev_len), cmd->ev_prot, FALSE); 196 } 197 198 void 199 exec_closefd(p, fd) 200 struct proc *p; 201 int fd; 202 { 203 if (p->p_fd->fd_lastfile == fd) 204 p->p_fd->fd_lastfile--; 205 if (p->p_fd->fd_freefile > fd) 206 p->p_fd->fd_freefile = fd; 207 closef(p->p_fd->fd_ofiles[fd], p); 208 p->p_fd->fd_ofiles[fd] = 0; 209 } 210