1 /* $OpenBSD: freebsd_exec.c,v 1.17 2006/01/19 17:54:50 mickey Exp $ */
2 /* $NetBSD: freebsd_exec.c,v 1.2 1996/05/18 16:02:08 christos Exp $ */
3
4 /*
5 * Copyright (c) 1993, 1994 Christopher G. Demetriou
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Christopher G. Demetriou.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/proc.h>
37 #include <sys/malloc.h>
38 #include <sys/vnode.h>
39 #include <sys/exec.h>
40 #include <sys/resourcevar.h>
41 #include <uvm/uvm_extern.h>
42 #include <sys/exec_elf.h>
43 #include <sys/exec_olf.h>
44
45 #include <machine/freebsd_machdep.h>
46
47 #include <compat/freebsd/freebsd_syscall.h>
48 #include <compat/freebsd/freebsd_exec.h>
49 #include <compat/freebsd/freebsd_util.h>
50
51 extern struct sysent freebsd_sysent[];
52 #ifdef SYSCALL_DEBUG
53 extern char *freebsd_syscallnames[];
54 #endif
55
56 extern const char freebsd_emul_path[];
57
58 struct emul emul_freebsd_aout = {
59 "freebsd",
60 NULL,
61 freebsd_sendsig,
62 FREEBSD_SYS_syscall,
63 FREEBSD_SYS_MAXSYSCALL,
64 freebsd_sysent,
65 #ifdef SYSCALL_DEBUG
66 freebsd_syscallnames,
67 #else
68 NULL,
69 #endif
70 0,
71 copyargs,
72 setregs,
73 NULL,
74 freebsd_sigcode,
75 freebsd_esigcode,
76 };
77
78 struct emul emul_freebsd_elf = {
79 "freebsd",
80 NULL,
81 freebsd_sendsig,
82 FREEBSD_SYS_syscall,
83 FREEBSD_SYS_MAXSYSCALL,
84 freebsd_sysent,
85 #ifdef SYSCALL_DEBUG
86 freebsd_syscallnames,
87 #else
88 NULL,
89 #endif
90 FREEBSD_ELF_AUX_ARGSIZ,
91 elf32_copyargs,
92 setregs,
93 exec_elf32_fixup,
94 freebsd_sigcode,
95 freebsd_esigcode,
96 };
97
98 /*
99 * exec_aout_makecmds(): Check if it's an a.out-format executable.
100 *
101 * Given a proc pointer and an exec package pointer, see if the referent
102 * of the epp is in a.out format. First check 'standard' magic numbers for
103 * this architecture. If that fails, try a cpu-dependent hook.
104 *
105 * This function, in the former case, or the hook, in the latter, is
106 * responsible for creating a set of vmcmds which can be used to build
107 * the process's vm space and inserting them into the exec package.
108 */
109
110 int
111 exec_freebsd_aout_makecmds(p, epp)
112 struct proc *p;
113 struct exec_package *epp;
114 {
115 u_long midmag;
116 int error = ENOEXEC;
117 struct exec *execp = epp->ep_hdr;
118
119 if (epp->ep_hdrvalid < sizeof(struct exec))
120 return ENOEXEC;
121
122 midmag = FREEBSD_N_GETMID(*execp) << 16 | FREEBSD_N_GETMAGIC(*execp);
123
124 /* assume FreeBSD's MID_MACHINE and [ZQNO]MAGIC is same as NetBSD's */
125 switch (midmag) {
126 case (MID_MACHINE << 16) | ZMAGIC:
127 error = exec_aout_prep_oldzmagic(p, epp);
128 break;
129 case (MID_MACHINE << 16) | QMAGIC:
130 error = exec_aout_prep_zmagic(p, epp);
131 break;
132 case (MID_MACHINE << 16) | NMAGIC:
133 error = exec_aout_prep_nmagic(p, epp);
134 break;
135 case (MID_MACHINE << 16) | OMAGIC:
136 error = exec_aout_prep_omagic(p, epp);
137 break;
138 }
139 if (error == 0)
140 epp->ep_emul = &emul_freebsd_aout;
141 else
142 kill_vmcmds(&epp->ep_vmcmds);
143
144 return error;
145 }
146
147 int
148 exec_freebsd_elf32_makecmds(struct proc *p, struct exec_package *epp)
149 {
150 if (!(emul_freebsd_elf.e_flags & EMUL_ENABLED))
151 return (ENOEXEC);
152 return exec_elf32_makecmds(p, epp);
153
154 }
155
156 int
157 freebsd_elf_probe(p, epp, itp, pos, os)
158 struct proc *p;
159 struct exec_package *epp;
160 char *itp;
161 u_long *pos;
162 u_int8_t *os;
163 {
164 Elf32_Ehdr *eh = epp->ep_hdr;
165 char *bp, *brand;
166 int error;
167 size_t len;
168
169 /*
170 * Older FreeBSD ELF binaries use a brand; newer ones use EI_OSABI
171 */
172 if (eh->e_ident[EI_OSABI] != ELFOSABI_FREEBSD) {
173 brand = elf32_check_brand(eh);
174 if (brand == NULL || strcmp(brand, "FreeBSD") != 0)
175 return (EINVAL);
176 }
177 if (itp) {
178 if ((error = emul_find(p, NULL, freebsd_emul_path, itp, &bp, 0)))
179 return (error);
180 if ((error = copystr(bp, itp, MAXPATHLEN, &len)))
181 return (error);
182 free(bp, M_TEMP);
183 }
184 epp->ep_emul = &emul_freebsd_elf;
185 *pos = ELF32_NO_ADDR;
186 if (*os == OOS_NULL)
187 *os = OOS_FREEBSD;
188 return (0);
189 }