1 /* 2 * Copyright (c) 1993 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_aout.c,v 1.1 1993/09/05 01:33:35 cgd Exp $ 31 */ 32 33 #include "param.h" 34 #include "systm.h" 35 #include "filedesc.h" 36 #include "kernel.h" 37 #include "proc.h" 38 #include "mount.h" 39 #include "malloc.h" 40 #include "namei.h" 41 #include "vnode.h" 42 #include "file.h" 43 #include "exec.h" 44 #include "resourcevar.h" 45 #include "wait.h" 46 47 #include "machine/cpu.h" 48 #include "machine/reg.h" 49 #include "machine/exec.h" 50 51 #include "mman.h" 52 #include "vm/vm.h" 53 #include "vm/vm_param.h" 54 #include "vm/vm_map.h" 55 #include "vm/vm_kern.h" 56 #include "vm/vm_pager.h" 57 58 /* 59 * exec_aout_makecmds(): Check if it's an a.out-format executable. 60 * 61 * Given a proc pointer and an exec package pointer, see if the referent 62 * of the epp is in a.out format. First check 'standard' magic numbers for 63 * this architecture. If that fails, try a cpu-dependent hook. 64 * 65 * This function, in the former case, or the hook, in the latter, is 66 * responsible for creating a set of vmcmds which can be used to build 67 * the process's vm space and inserting them into the exec package. 68 * 69 * XXX: NMAGIC and OMAGIC are currently not supported. 70 */ 71 72 int 73 exec_aout_makecmds(p, epp) 74 struct proc *p; 75 struct exec_package *epp; 76 { 77 u_long midmag, magic; 78 u_short mid; 79 int error; 80 81 midmag = ntohl(epp->ep_execp->a_midmag); 82 mid = (midmag >> 16) & 0x3ff; 83 magic = midmag & 0xffff; 84 85 #ifdef EXEC_DEBUG 86 printf("exec_makecmds: a_midmag is %x, magic=%x mid=%x\n", 87 epp->ep_execp->a_midmag, magic, mid); 88 #endif 89 90 midmag = mid << 16 | magic; 91 92 switch (midmag) { 93 case (MID_MACHINE << 16) | ZMAGIC: 94 error = exec_aout_prep_zmagic(p, epp); 95 break; 96 case (MID_MACHINE << 16) | OMAGIC: 97 case (MID_MACHINE << 16) | NMAGIC: 98 default: 99 error = cpu_exec_aout_makecmds(p, epp); 100 } 101 102 if (error && epp->ep_vcp) 103 kill_vmcmd(&epp->ep_vcp); 104 105 bad: 106 107 #ifdef EXEC_DEBUG 108 printf("exec_makecmds returning with error = %d\n", error); 109 #endif 110 return error; 111 } 112 113 /* 114 * exec_aout_prep_zmagic(): Prepare a 'native' ZMAGIC binary's exec package 115 * 116 * First, set of the various offsets/lengths in the exec package. 117 * Note that the ep_ssize parameter must be set to be the current stack 118 * limit; this is adjusted in the body of execve() to yield the 119 * appropriate stack segment usage once the argument length is 120 * calculated. 121 * 122 * Then, mark the text image busy (so it can be demand paged) or error 123 * out if this is not possible. Finally, set up vmcmds for the 124 * text, data, bss, and stack segments. 125 */ 126 127 int 128 exec_aout_prep_zmagic(p, epp) 129 struct proc *p; 130 struct exec_package *epp; 131 { 132 struct exec *execp = epp->ep_execp; 133 struct exec_vmcmd *ccmdp; 134 135 epp->ep_taddr = USRTEXT; 136 epp->ep_tsize = execp->a_text; 137 epp->ep_daddr = epp->ep_taddr + execp->a_text; 138 epp->ep_dsize = execp->a_data + execp->a_bss; 139 epp->ep_maxsaddr = USRSTACK - MAXSSIZ; 140 epp->ep_minsaddr = USRSTACK; 141 epp->ep_ssize = p->p_rlimit[RLIMIT_STACK].rlim_cur; 142 epp->ep_entry = execp->a_entry; 143 144 /* 145 * check if vnode is in open for writing, because we want to 146 * demand-page out of it. if it is, don't do it, for various 147 * reasons 148 */ 149 if ((execp->a_text != 0 || execp->a_data != 0) && 150 (epp->ep_vp->v_flag & VTEXT) == 0 && epp->ep_vp->v_writecount != 0) { 151 #ifdef DIAGNOSTIC 152 if (epp->ep_vp->v_flag & VTEXT) 153 panic("exec: a VTEXT vnode has writecount != 0\n"); 154 #endif 155 epp->ep_vcp = NULL; 156 return ETXTBSY; 157 } 158 epp->ep_vp->v_flag |= VTEXT; 159 160 /* set up command for text segment */ 161 epp->ep_vcp = new_vmcmd(vmcmd_map_pagedvn, 162 execp->a_text, 163 epp->ep_taddr, 164 epp->ep_vp, 165 0, 166 VM_PROT_READ | VM_PROT_EXECUTE); 167 ccmdp = epp->ep_vcp; 168 169 /* set up command for data segment */ 170 ccmdp->ev_next = new_vmcmd(vmcmd_map_pagedvn, 171 execp->a_data, 172 epp->ep_daddr, 173 epp->ep_vp, 174 execp->a_text, 175 VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); 176 ccmdp = ccmdp->ev_next; 177 178 /* set up command for bss segment */ 179 ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, 180 execp->a_bss, 181 epp->ep_daddr + execp->a_data, 182 0, 183 0, 184 VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); 185 ccmdp = ccmdp->ev_next; 186 187 /* 188 * set up commands for stack. note that this takes *two*, one to 189 * map the part of the stack which we can access, and one to map 190 * the part which we can't. 191 * 192 * arguably, it could be made into one, but that would require the 193 * addition of another mapping proc, which is unnecessary 194 * 195 * note that in memory, things assumed to be: 0 ....... ep_maxsaddr 196 * <stack> ep_minsaddr 197 */ 198 ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, 199 ((epp->ep_minsaddr - epp->ep_ssize) - epp->ep_maxsaddr), 200 epp->ep_maxsaddr, 201 0, 202 0, 203 VM_PROT_NONE); 204 ccmdp = ccmdp->ev_next; 205 ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, 206 epp->ep_ssize, 207 (epp->ep_minsaddr - epp->ep_ssize), 208 0, 209 0, 210 VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); 211 212 return 0; 213 } 214