1 /* $NetBSD: netbsd32_exec_aout.c,v 1.16 2003/08/08 18:57:06 christos Exp $ */ 2 /* from: NetBSD: exec_aout.c,v 1.15 1996/09/26 23:34:46 cgd Exp */ 3 4 /* 5 * Copyright (c) 1998, 2001 Matthew R. Green. 6 * Copyright (c) 1993, 1994 Christopher G. Demetriou 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Christopher G. Demetriou. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: netbsd32_exec_aout.c,v 1.16 2003/08/08 18:57:06 christos Exp $"); 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/proc.h> 41 #include <sys/malloc.h> 42 #include <sys/vnode.h> 43 #include <sys/exec.h> 44 #include <sys/exec_aout.h> 45 #include <sys/resourcevar.h> 46 #include <sys/signal.h> 47 #include <sys/signalvar.h> 48 49 #include <compat/netbsd32/netbsd32.h> 50 #ifndef EXEC_AOUT 51 #define EXEC_AOUT 52 #endif 53 #include <compat/netbsd32/netbsd32_exec.h> 54 55 #include <machine/frame.h> 56 #include <machine/netbsd32_machdep.h> 57 58 int netbsd32_copyinargs __P((struct exec_package *, struct ps_strings *, 59 void *, size_t, const void *, const void *)); 60 61 /* 62 * exec_netbsd32_makecmds(): Check if it's an netbsd32 a.out format 63 * executable. 64 * 65 * Given a proc pointer and an exec package pointer, see if the referent 66 * of the epp is in netbsd32 a.out format. Check 'standard' magic 67 * numbers for this architecture. 68 * 69 * This function, in the former case, or the hook, in the latter, is 70 * responsible for creating a set of vmcmds which can be used to build 71 * the process's vm space and inserting them into the exec package. 72 */ 73 74 int 75 exec_netbsd32_makecmds(p, epp) 76 struct proc *p; 77 struct exec_package *epp; 78 { 79 netbsd32_u_long midmag, magic; 80 u_short mid; 81 int error; 82 struct netbsd32_exec *execp = epp->ep_hdr; 83 84 if (epp->ep_hdrvalid < sizeof(struct netbsd32_exec)) 85 return ENOEXEC; 86 87 midmag = (netbsd32_u_long)ntohl(execp->a_midmag); 88 mid = (midmag >> 16) & 0x3ff; 89 magic = midmag & 0xffff; 90 91 midmag = mid << 16 | magic; 92 93 switch (midmag) { 94 case (MID_SPARC << 16) | ZMAGIC: 95 error = netbsd32_exec_aout_prep_zmagic(p, epp); 96 break; 97 case (MID_SPARC << 16) | NMAGIC: 98 error = netbsd32_exec_aout_prep_nmagic(p, epp); 99 break; 100 case (MID_SPARC << 16) | OMAGIC: 101 error = netbsd32_exec_aout_prep_omagic(p, epp); 102 break; 103 default: 104 /* Invalid magic */ 105 error = ENOEXEC; 106 break; 107 } 108 109 if (error == 0) { 110 /* set up our emulation information */ 111 epp->ep_flags |= EXEC_32; 112 } else 113 kill_vmcmds(&epp->ep_vmcmds); 114 115 return error; 116 } 117 118 /* 119 * netbsd32_exec_aout_prep_zmagic(): Prepare a 'native' ZMAGIC binary's 120 * exec package 121 * 122 * First, set of the various offsets/lengths in the exec package. 123 * 124 * Then, mark the text image busy (so it can be demand paged) or error 125 * out if this is not possible. Finally, set up vmcmds for the 126 * text, data, bss, and stack segments. 127 */ 128 129 int 130 netbsd32_exec_aout_prep_zmagic(p, epp) 131 struct proc *p; 132 struct exec_package *epp; 133 { 134 struct netbsd32_exec *execp = epp->ep_hdr; 135 int error; 136 137 epp->ep_taddr = AOUT_LDPGSZ; 138 epp->ep_tsize = execp->a_text; 139 epp->ep_daddr = epp->ep_taddr + execp->a_text; 140 epp->ep_dsize = execp->a_data + execp->a_bss; 141 epp->ep_entry = execp->a_entry; 142 epp->ep_vm_minaddr = VM_MIN_ADDRESS; 143 epp->ep_vm_maxaddr = VM_MAXUSER_ADDRESS32; 144 145 error = vn_marktext(epp->ep_vp); 146 if (error) 147 return (error); 148 149 /* set up command for text segment */ 150 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text, 151 epp->ep_taddr, epp->ep_vp, 0, VM_PROT_READ|VM_PROT_EXECUTE); 152 153 /* set up command for data segment */ 154 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data, 155 epp->ep_daddr, epp->ep_vp, execp->a_text, 156 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 157 158 /* set up command for bss segment */ 159 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss, 160 epp->ep_daddr + execp->a_data, NULLVP, 0, 161 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 162 163 return (*epp->ep_esch->es_setup_stack)(p, epp); 164 } 165 166 /* 167 * netbsd32_exec_aout_prep_nmagic(): Prepare a 'native' NMAGIC binary's 168 * exec package 169 */ 170 171 int 172 netbsd32_exec_aout_prep_nmagic(p, epp) 173 struct proc *p; 174 struct exec_package *epp; 175 { 176 struct netbsd32_exec *execp = epp->ep_hdr; 177 long bsize, baddr; 178 179 epp->ep_taddr = AOUT_LDPGSZ; 180 epp->ep_tsize = execp->a_text; 181 epp->ep_daddr = roundup(epp->ep_taddr + execp->a_text, AOUT_LDPGSZ); 182 epp->ep_dsize = execp->a_data + execp->a_bss; 183 epp->ep_entry = execp->a_entry; 184 epp->ep_vm_minaddr = VM_MIN_ADDRESS; 185 epp->ep_vm_maxaddr = VM_MAXUSER_ADDRESS32; 186 187 /* set up command for text segment */ 188 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_text, 189 epp->ep_taddr, epp->ep_vp, sizeof(struct netbsd32_exec), 190 VM_PROT_READ|VM_PROT_EXECUTE); 191 192 /* set up command for data segment */ 193 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_data, 194 epp->ep_daddr, epp->ep_vp, execp->a_text + sizeof(struct netbsd32_exec), 195 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 196 197 /* set up command for bss segment */ 198 baddr = roundup(epp->ep_daddr + execp->a_data, PAGE_SIZE); 199 bsize = epp->ep_daddr + epp->ep_dsize - baddr; 200 if (bsize > 0) 201 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr, 202 NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 203 204 return (*epp->ep_esch->es_setup_stack)(p, epp); 205 } 206 207 /* 208 * netbsd32_exec_aout_prep_omagic(): Prepare a 'native' OMAGIC binary's 209 * exec package 210 */ 211 212 int 213 netbsd32_exec_aout_prep_omagic(p, epp) 214 struct proc *p; 215 struct exec_package *epp; 216 { 217 struct netbsd32_exec *execp = epp->ep_hdr; 218 long dsize, bsize, baddr; 219 220 epp->ep_taddr = AOUT_LDPGSZ; 221 epp->ep_tsize = execp->a_text; 222 epp->ep_daddr = epp->ep_taddr + execp->a_text; 223 epp->ep_dsize = execp->a_data + execp->a_bss; 224 epp->ep_entry = execp->a_entry; 225 epp->ep_vm_minaddr = VM_MIN_ADDRESS; 226 epp->ep_vm_maxaddr = VM_MAXUSER_ADDRESS32; 227 228 /* set up command for text and data segments */ 229 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, 230 execp->a_text + execp->a_data, epp->ep_taddr, epp->ep_vp, 231 sizeof(struct netbsd32_exec), VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 232 233 /* set up command for bss segment */ 234 baddr = roundup(epp->ep_daddr + execp->a_data, PAGE_SIZE); 235 bsize = epp->ep_daddr + epp->ep_dsize - baddr; 236 if (bsize > 0) 237 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr, 238 NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); 239 240 /* 241 * Make sure (# of pages) mapped above equals (vm_tsize + vm_dsize); 242 * obreak(2) relies on this fact. Both `vm_tsize' and `vm_dsize' are 243 * computed (in execve(2)) by rounding *up* `ep_tsize' and `ep_dsize' 244 * respectively to page boundaries. 245 * Compensate `ep_dsize' for the amount of data covered by the last 246 * text page. 247 */ 248 dsize = epp->ep_dsize + execp->a_text - roundup(execp->a_text, 249 PAGE_SIZE); 250 epp->ep_dsize = (dsize > 0) ? dsize : 0; 251 return (*epp->ep_esch->es_setup_stack)(p, epp); 252 } 253