xref: /netbsd-src/sys/kern/exec_elf32.c (revision dc306354b0b29af51801a7632f1e95265a68cd81)
1 /*	$NetBSD: exec_elf32.c,v 1.41 1999/01/06 11:52:53 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 1994 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Christos Zoulas.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * Copyright (c) 1996 Christopher G. Demetriou
41  * All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  * 3. The name of the author may not be used to endorse or promote products
52  *    derived from this software without specific prior written permission
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
55  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
56  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
58  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
63  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */
65 
66 /* If not included by exec_elf64.c, ELFSIZE won't be defined. */
67 #ifndef ELFSIZE
68 #define	ELFSIZE		32
69 #endif
70 
71 #include "opt_compat_linux.h"
72 #include "opt_compat_ibcs2.h"
73 #include "opt_compat_svr4.h"
74 
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/kernel.h>
78 #include <sys/proc.h>
79 #include <sys/malloc.h>
80 #include <sys/namei.h>
81 #include <sys/vnode.h>
82 #include <sys/exec.h>
83 #include <sys/exec_elf.h>
84 #include <sys/fcntl.h>
85 #include <sys/syscall.h>
86 #include <sys/signalvar.h>
87 #include <sys/mount.h>
88 #include <sys/stat.h>
89 
90 #include <sys/mman.h>
91 #include <vm/vm.h>
92 #include <vm/vm_param.h>
93 #include <vm/vm_map.h>
94 
95 #include <machine/cpu.h>
96 #include <machine/reg.h>
97 
98 #ifdef COMPAT_LINUX
99 #include <compat/linux/common/linux_exec.h>
100 #endif
101 
102 #ifdef COMPAT_SVR4
103 #include <compat/svr4/svr4_exec.h>
104 #endif
105 
106 #ifdef COMPAT_IBCS2
107 #include <compat/ibcs2/ibcs2_exec.h>
108 #endif
109 
110 int	ELFNAME(check_header) __P((Elf_Ehdr *, int));
111 int	ELFNAME(load_file) __P((struct proc *, struct exec_package *, char *,
112 	    struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *));
113 void	ELFNAME(load_psection) __P((struct exec_vmcmd_set *, struct vnode *,
114 	    Elf_Phdr *, Elf_Addr *, u_long *, int *));
115 
116 static int ELFNAME2(netbsd,signature) __P((struct proc *, struct exec_package *,
117     Elf_Ehdr *));
118 static int ELFNAME2(netbsd,probe) __P((struct proc *, struct exec_package *,
119     Elf_Ehdr *, char *, Elf_Addr *));
120 
121 extern char sigcode[], esigcode[];
122 #ifdef SYSCALL_DEBUG
123 extern char *syscallnames[];
124 #endif
125 
126 struct emul ELFNAMEEND(emul_netbsd) = {
127 	"netbsd",
128 	NULL,
129 	sendsig,
130 	SYS_syscall,
131 	SYS_MAXSYSCALL,
132 	sysent,
133 #ifdef SYSCALL_DEBUG
134 	syscallnames,
135 #else
136 	NULL,
137 #endif
138 	ELF_AUX_ENTRIES * sizeof(AuxInfo),
139 	ELFNAME(copyargs),
140 	setregs,
141 	sigcode,
142 	esigcode,
143 };
144 
145 int (*ELFNAME(probe_funcs)[]) __P((struct proc *, struct exec_package *,
146     Elf_Ehdr *, char *, Elf_Addr *)) = {
147 	ELFNAME2(netbsd,probe),
148 #if defined(COMPAT_LINUX)
149 	ELFNAME2(linux,probe),
150 #endif
151 #if defined(COMPAT_SVR4) && (ELFSIZE == 32)
152 	ELFNAME2(svr4,probe),			/* XXX not 64-bit safe */
153 #endif
154 #if defined(COMPAT_IBCS2) && (ELFSIZE == 32)
155 	ELFNAME2(ibcs2,probe),			/* XXX not 64-bit safe */
156 #endif
157 };
158 
159 /* round up and down to page boundaries. */
160 #define	ELF_ROUND(a, b)		(((a) + (b) - 1) & ~((b) - 1))
161 #define	ELF_TRUNC(a, b)		((a) & ~((b) - 1))
162 
163 /*
164  * Copy arguments onto the stack in the normal way, but add some
165  * extra information in case of dynamic binding.
166  */
167 void *
168 ELFNAME(copyargs)(pack, arginfo, stack, argp)
169 	struct exec_package *pack;
170 	struct ps_strings *arginfo;
171 	void *stack;
172 	void *argp;
173 {
174 	size_t len;
175 	AuxInfo ai[ELF_AUX_ENTRIES], *a;
176 	struct elf_args *ap;
177 
178 	stack = copyargs(pack, arginfo, stack, argp);
179 	if (!stack)
180 		return NULL;
181 
182 	a = ai;
183 
184 	/*
185 	 * Push extra arguments on the stack needed by dynamically
186 	 * linked binaries
187 	 */
188 	if ((ap = (struct elf_args *)pack->ep_emul_arg)) {
189 
190 		a->au_id = AUX_phdr;
191 		a->au_v = ap->arg_phaddr;
192 		a++;
193 
194 		a->au_id = AUX_phent;
195 		a->au_v = ap->arg_phentsize;
196 		a++;
197 
198 		a->au_id = AUX_phnum;
199 		a->au_v = ap->arg_phnum;
200 		a++;
201 
202 		a->au_id = AUX_pagesz;
203 		a->au_v = NBPG;
204 		a++;
205 
206 		a->au_id = AUX_base;
207 		a->au_v = ap->arg_interp;
208 		a++;
209 
210 		a->au_id = AUX_flags;
211 		a->au_v = 0;
212 		a++;
213 
214 		a->au_id = AUX_entry;
215 		a->au_v = ap->arg_entry;
216 		a++;
217 
218 		free((char *)ap, M_TEMP);
219 		pack->ep_emul_arg = NULL;
220 	}
221 
222 	a->au_id = AUX_null;
223 	a->au_v = 0;
224 	a++;
225 
226 	len = (a - ai) * sizeof(AuxInfo);
227 	if (copyout(ai, stack, len))
228 		return NULL;
229 	(caddr_t)stack += len;
230 
231 	return stack;
232 }
233 
234 /*
235  * elf_check_header():
236  *
237  * Check header for validity; return 0 of ok ENOEXEC if error
238  */
239 int
240 ELFNAME(check_header)(eh, type)
241 	Elf_Ehdr *eh;
242 	int type;
243 {
244 
245 	if (memcmp(eh->e_ident, Elf_e_ident, Elf_e_siz) != 0)
246 		return ENOEXEC;
247 
248 	switch (eh->e_machine) {
249 
250 	ELFDEFNNAME(MACHDEP_ID_CASES)
251 
252 	default:
253 		return ENOEXEC;
254 	}
255 
256 	if (eh->e_type != type)
257 		return ENOEXEC;
258 
259 	return 0;
260 }
261 
262 /*
263  * elf_load_psection():
264  *
265  * Load a psection at the appropriate address
266  */
267 void
268 ELFNAME(load_psection)(vcset, vp, ph, addr, size, prot)
269 	struct exec_vmcmd_set *vcset;
270 	struct vnode *vp;
271 	Elf_Phdr *ph;
272 	Elf_Addr *addr;
273 	u_long *size;
274 	int *prot;
275 {
276 	u_long uaddr, msize, psize, rm, rf;
277 	long diff, offset;
278 
279 	/*
280 	 * If the user specified an address, then we load there.
281 	 */
282 	if (*addr != ELFDEFNNAME(NO_ADDR)) {
283 		if (ph->p_align > 1) {
284 			*addr = ELF_ROUND(*addr, ph->p_align);
285 			uaddr = ELF_TRUNC(ph->p_vaddr, ph->p_align);
286 		} else
287 			uaddr = ph->p_vaddr;
288 		diff = ph->p_vaddr - uaddr;
289 	} else {
290 		*addr = uaddr = ph->p_vaddr;
291 		if (ph->p_align > 1)
292 			*addr = ELF_TRUNC(uaddr, ph->p_align);
293 		diff = uaddr - *addr;
294 	}
295 
296 	*prot |= (ph->p_flags & Elf_pf_r) ? VM_PROT_READ : 0;
297 	*prot |= (ph->p_flags & Elf_pf_w) ? VM_PROT_WRITE : 0;
298 	*prot |= (ph->p_flags & Elf_pf_x) ? VM_PROT_EXECUTE : 0;
299 
300 	offset = ph->p_offset - diff;
301 	*size = ph->p_filesz + diff;
302 	msize = ph->p_memsz + diff;
303 	psize = round_page(*size);
304 
305 	if ((ph->p_flags & Elf_pf_w) != 0) {
306 		/*
307 		 * Because the pagedvn pager can't handle zero fill of the last
308 		 * data page if it's not page aligned we map the last page
309 		 * readvn.
310 		 */
311 		psize = trunc_page(*size);
312 		NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp,
313 		    offset, *prot);
314 		if(psize != *size)
315 			NEW_VMCMD(vcset, vmcmd_map_readvn, *size - psize,
316 			    *addr + psize, vp, offset + psize, *prot);
317 	} else
318 		NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp,
319 		    offset, *prot);
320 
321 	/*
322 	 * Check if we need to extend the size of the segment
323 	 */
324 	rm = round_page(*addr + msize);
325 	rf = round_page(*addr + *size);
326 
327 	if (rm != rf) {
328 		NEW_VMCMD(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP,
329 		    0, *prot);
330 		*size = msize;
331 	}
332 }
333 
334 /*
335  * elf_read_from():
336  *
337  *	Read from vnode into buffer at offset.
338  */
339 int
340 ELFNAME(read_from)(p, vp, off, buf, size)
341 	struct vnode *vp;
342 	u_long off;
343 	struct proc *p;
344 	caddr_t buf;
345 	int size;
346 {
347 	int error;
348 	size_t resid;
349 
350 	if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE,
351 	    0, p->p_ucred, &resid, p)) != 0)
352 		return error;
353 	/*
354 	 * See if we got all of it
355 	 */
356 	if (resid != 0)
357 		return ENOEXEC;
358 	return 0;
359 }
360 
361 /*
362  * elf_load_file():
363  *
364  * Load a file (interpreter/library) pointed to by path
365  * [stolen from coff_load_shlib()]. Made slightly generic
366  * so it might be used externally.
367  */
368 int
369 ELFNAME(load_file)(p, epp, path, vcset, entry, ap, last)
370 	struct proc *p;
371 	struct exec_package *epp;
372 	char *path;
373 	struct exec_vmcmd_set *vcset;
374 	u_long *entry;
375 	struct elf_args	*ap;
376 	Elf_Addr *last;
377 {
378 	int error, i;
379 	struct nameidata nd;
380 	struct vnode *vp;
381 	struct vattr attr;
382 	Elf_Ehdr eh;
383 	Elf_Phdr *ph = NULL;
384 	u_long phsize;
385 	char *bp = NULL;
386 	Elf_Addr addr = *last;
387 
388 	bp = path;
389 	/*
390 	 * 1. open file
391 	 * 2. read filehdr
392 	 * 3. map text, data, and bss out of it using VM_*
393 	 */
394 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
395 	if ((error = namei(&nd)) != 0)
396 		return error;
397 	vp = nd.ni_vp;
398 
399 	/*
400 	 * Similarly, if it's not marked as executable, or it's not a regular
401 	 * file, we don't allow it to be used.
402 	 */
403 	if (vp->v_type != VREG) {
404 		error = EACCES;
405 		goto badunlock;
406 	}
407 	if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0)
408 		goto badunlock;
409 
410 	/* get attributes */
411 	if ((error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) != 0)
412 		goto badunlock;
413 
414 	/*
415 	 * Check mount point.  Though we're not trying to exec this binary,
416 	 * we will be executing code from it, so if the mount point
417 	 * disallows execution or set-id-ness, we punt or kill the set-id.
418 	 */
419 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
420 		error = EACCES;
421 		goto badunlock;
422 	}
423 	if (vp->v_mount->mnt_flag & MNT_NOSUID)
424 		epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
425 
426 #ifdef notyet /* XXX cgd 960926 */
427 	XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?)
428 #endif
429 	VOP_UNLOCK(vp, 0);
430 
431 	if ((error = ELFNAME(read_from)(p, vp, 0, (caddr_t) &eh,
432 	    sizeof(eh))) != 0)
433 		goto bad;
434 
435 	if ((error = ELFNAME(check_header)(&eh, Elf_et_dyn)) != 0)
436 		goto bad;
437 
438 	phsize = eh.e_phnum * sizeof(Elf_Phdr);
439 	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
440 
441 	if ((error = ELFNAME(read_from)(p, vp, eh.e_phoff,
442 	    (caddr_t) ph, phsize)) != 0)
443 		goto bad;
444 
445 	/*
446 	 * Load all the necessary sections
447 	 */
448 	for (i = 0; i < eh.e_phnum; i++) {
449 		u_long size = 0;
450 		int prot = 0;
451 
452 		switch (ph[i].p_type) {
453 		case Elf_pt_load:
454 			ELFNAME(load_psection)(vcset, vp, &ph[i], &addr,
455 			    &size, &prot);
456 			/* If entry is within this section it must be text */
457 			if (eh.e_entry >= ph[i].p_vaddr &&
458 			    eh.e_entry < (ph[i].p_vaddr + size)) {
459 				/* XXX */
460 				*entry = addr + eh.e_entry;
461 #ifdef mips
462 				*entry -= ph[i].p_vaddr;
463 #endif
464 				ap->arg_interp = addr;
465 			}
466 			addr += size;
467 			break;
468 
469 		case Elf_pt_dynamic:
470 		case Elf_pt_phdr:
471 		case Elf_pt_note:
472 			break;
473 
474 		default:
475 			break;
476 		}
477 	}
478 
479 	free((char *)ph, M_TEMP);
480 	*last = addr;
481 	vrele(vp);
482 	return 0;
483 
484 badunlock:
485 	VOP_UNLOCK(vp, 0);
486 
487 bad:
488 	if (ph != NULL)
489 		free((char *)ph, M_TEMP);
490 #ifdef notyet /* XXX cgd 960926 */
491 	(maybe) VOP_CLOSE it
492 #endif
493 	vrele(vp);
494 	return error;
495 }
496 
497 /*
498  * exec_elf_makecmds(): Prepare an Elf binary's exec package
499  *
500  * First, set of the various offsets/lengths in the exec package.
501  *
502  * Then, mark the text image busy (so it can be demand paged) or error
503  * out if this is not possible.  Finally, set up vmcmds for the
504  * text, data, bss, and stack segments.
505  */
506 int
507 ELFNAME2(exec,makecmds)(p, epp)
508 	struct proc *p;
509 	struct exec_package *epp;
510 {
511 	Elf_Ehdr *eh = epp->ep_hdr;
512 	Elf_Phdr *ph, *pp;
513 	Elf_Addr phdr = 0, pos = 0;
514 	int error, i, n, nload;
515 	char interp[MAXPATHLEN];
516 	u_long phsize;
517 
518 	if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
519 		return ENOEXEC;
520 
521 	if (ELFNAME(check_header)(eh, Elf_et_exec))
522 		return ENOEXEC;
523 
524 	/*
525 	 * check if vnode is in open for writing, because we want to
526 	 * demand-page out of it.  if it is, don't do it, for various
527 	 * reasons
528 	 */
529 	if (epp->ep_vp->v_writecount != 0) {
530 #ifdef DIAGNOSTIC
531 		if (epp->ep_vp->v_flag & VTEXT)
532 			panic("exec: a VTEXT vnode has writecount != 0\n");
533 #endif
534 		return ETXTBSY;
535 	}
536 	/*
537 	 * Allocate space to hold all the program headers, and read them
538 	 * from the file
539 	 */
540 	phsize = eh->e_phnum * sizeof(Elf_Phdr);
541 	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
542 
543 	if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff,
544 	    (caddr_t) ph, phsize)) != 0)
545 		goto bad;
546 
547 	epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR);
548 	epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR);
549 
550 	interp[0] = '\0';
551 
552 	for (i = 0; i < eh->e_phnum; i++) {
553 		pp = &ph[i];
554 		if (pp->p_type == Elf_pt_interp) {
555 			if (pp->p_filesz >= sizeof(interp))
556 				goto bad;
557 			if ((error = ELFNAME(read_from)(p, epp->ep_vp,
558 			    pp->p_offset, (caddr_t) interp,
559 			    pp->p_filesz)) != 0)
560 				goto bad;
561 			break;
562 		}
563 	}
564 
565 	/*
566 	 * Setup things for native emulation.
567 	 */
568 	epp->ep_emul = &ELFNAMEEND(emul_netbsd);
569 	pos = ELFDEFNNAME(NO_ADDR);
570 
571 	/*
572 	 * On the same architecture, we may be emulating different systems.
573 	 * See which one will accept this executable. This currently only
574 	 * applies to SVR4, and IBCS2 on the i386 and Linux on the i386
575 	 * and the Alpha.
576 	 *
577 	 * Probe functions would normally see if the interpreter (if any)
578 	 * exists. Emulation packages may possibly replace the interpreter in
579 	 * interp[] with a changed path (/emul/xxx/<path>), and also
580 	 * set the ep_emul field in the exec package structure.
581 	 */
582 	n = sizeof(ELFNAME(probe_funcs)) / sizeof(ELFNAME(probe_funcs)[0]);
583 	if (n != 0) {
584 		error = ENOEXEC;
585 		for (i = 0; i < n && error; i++)
586 			error = ELFNAME(probe_funcs)[i](p, epp, eh,
587 			    interp, &pos);
588 #ifdef notyet
589 		/*
590 		 * We should really use a signature in our native binaries
591 		 * and have our own probe function for matching binaries,
592 		 * before trying the emulations. For now, if the emulation
593 		 * probes failed we default to native.
594 		 */
595 		if (error)
596 			goto bad;
597 #endif
598 	}
599 
600 	/*
601 	 * Load all the necessary sections
602 	 */
603 	for (i = nload = 0; i < eh->e_phnum; i++) {
604 		Elf_Addr  addr = ELFDEFNNAME(NO_ADDR);
605 		u_long size = 0;
606 		int prot = 0;
607 
608 		pp = &ph[i];
609 
610 		switch (ph[i].p_type) {
611 		case Elf_pt_load:
612 			/*
613 			 * XXX
614 			 * Can handle only 2 sections: text and data
615 			 */
616 			if (nload++ == 2)
617 				goto bad;
618 			ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp,
619 			    &ph[i], &addr, &size, &prot);
620 
621 			/*
622 			 * Decide whether it's text or data by looking
623 			 * at the entry point.
624 			 */
625 			if (eh->e_entry >= addr &&
626 			    eh->e_entry < (addr + size)) {
627 				epp->ep_taddr = addr;
628 				epp->ep_tsize = size;
629 				if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) {
630 					epp->ep_daddr = addr;
631 					epp->ep_dsize = size;
632 				}
633 			} else {
634 				epp->ep_daddr = addr;
635 				epp->ep_dsize = size;
636 			}
637 			break;
638 
639 		case Elf_pt_shlib:
640 #ifndef COMPAT_IBCS2			/* SCO has these sections */
641 			error = ENOEXEC;
642 			goto bad;
643 #endif
644 
645 		case Elf_pt_interp:
646 			/* Already did this one */
647 		case Elf_pt_dynamic:
648 		case Elf_pt_note:
649 			break;
650 
651 		case Elf_pt_phdr:
652 			/* Note address of program headers (in text segment) */
653 			phdr = pp->p_vaddr;
654 			break;
655 
656 		default:
657 			/*
658 			 * Not fatal; we don't need to understand everything.
659 			 */
660 			break;
661 		}
662 	}
663 
664 	/* this breaks on, e.g., OpenBSD-compatible mips shared binaries. */
665 #ifndef ELF_INTERP_NON_RELOCATABLE
666 	/*
667 	 * If no position to load the interpreter was set by a probe
668 	 * function, pick the same address that a non-fixed mmap(0, ..)
669 	 * would (i.e. something safely out of the way).
670 	 */
671 	if (pos == ELFDEFNNAME(NO_ADDR))
672 		pos = round_page(epp->ep_daddr + MAXDSIZ);
673 #endif	/* !ELF_INTERP_NON_RELOCATABLE */
674 
675 	/*
676 	 * Check if we found a dynamically linked binary and arrange to load
677 	 * it's interpreter
678 	 */
679 	if (interp[0]) {
680 		struct elf_args *ap;
681 
682 		ap = (struct elf_args *)malloc(sizeof(struct elf_args),
683 		    M_TEMP, M_WAITOK);
684 		if ((error = ELFNAME(load_file)(p, epp, interp,
685 		    &epp->ep_vmcmds, &epp->ep_entry, ap, &pos)) != 0) {
686 			free((char *)ap, M_TEMP);
687 			goto bad;
688 		}
689 		pos += phsize;
690 		ap->arg_phaddr = phdr;
691 
692 		ap->arg_phentsize = eh->e_phentsize;
693 		ap->arg_phnum = eh->e_phnum;
694 		ap->arg_entry = eh->e_entry;
695 
696 		epp->ep_emul_arg = ap;
697 	} else
698 		epp->ep_entry = eh->e_entry;
699 
700 #ifdef ELF_MAP_PAGE_ZERO
701 	/* Dell SVR4 maps page zero, yeuch! */
702 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, NBPG, 0, epp->ep_vp, 0,
703 	    VM_PROT_READ);
704 #endif
705 	free((char *)ph, M_TEMP);
706 	epp->ep_vp->v_flag |= VTEXT;
707 	return exec_elf_setup_stack(p, epp);
708 
709 bad:
710 	free((char *)ph, M_TEMP);
711 	kill_vmcmds(&epp->ep_vmcmds);
712 	return ENOEXEC;
713 }
714 
715 static int
716 ELFNAME2(netbsd,signature)(p, epp, eh)
717 	struct proc *p;
718 	struct exec_package *epp;
719 	Elf_Ehdr *eh;
720 {
721 	Elf_Phdr *hph, *ph;
722 	Elf_Note *np = NULL;
723 	size_t phsize;
724 	int error;
725 
726 	phsize = eh->e_phnum * sizeof(Elf_Phdr);
727 	hph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
728 	if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff,
729 	    (caddr_t)hph, phsize)) != 0)
730 		goto out1;
731 
732 	for (ph = hph;  ph < &hph[eh->e_phnum]; ph++) {
733 		if (ph->p_type != Elf_pt_note ||
734 		    ph->p_filesz < sizeof(Elf_Note) + ELF_NOTE_NETBSD_NAMESZ)
735 			continue;
736 
737 		np = (Elf_Note *)malloc(ph->p_filesz, M_TEMP, M_WAITOK);
738 		if ((error = ELFNAME(read_from)(p, epp->ep_vp, ph->p_offset,
739 		    (caddr_t)np, ph->p_filesz)) != 0)
740 			goto out2;
741 
742 		if (np->type != ELF_NOTE_TYPE_OSVERSION) {
743 			free(np, M_TEMP);
744 			np = NULL;
745 			continue;
746 		}
747 
748 		/* Check the name and description sizes. */
749 		if (np->namesz != ELF_NOTE_NETBSD_NAMESZ ||
750 		    np->descsz != ELF_NOTE_NETBSD_DESCSZ)
751 			goto out3;
752 
753 		/* Is the name "NetBSD\0\0"? */
754 		if (memcmp((np + 1), ELF_NOTE_NETBSD_NAME,
755 		    ELF_NOTE_NETBSD_NAMESZ))
756 			goto out3;
757 
758 		/* XXX: We could check for the specific emulation here */
759 		/* All checks succeeded. */
760 		error = 0;
761 		goto out2;
762 	}
763 
764 out3:
765 	error = ENOEXEC;
766 out2:
767 	if (np)
768 		free(np, M_TEMP);
769 out1:
770 	free(hph, M_TEMP);
771 	return error;
772 }
773 
774 static int
775 ELFNAME2(netbsd,probe)(p, epp, eh, itp, pos)
776 	struct proc *p;
777 	struct exec_package *epp;
778 	Elf_Ehdr *eh;
779 	char *itp;
780 	Elf_Addr *pos;
781 {
782 	int error;
783 
784 	if ((error = ELFNAME2(netbsd,signature)(p, epp, eh)) != 0)
785 		return error;
786 
787 	epp->ep_emul = &ELFNAMEEND(emul_netbsd);
788 	*pos = ELFDEFNNAME(NO_ADDR);
789 	return 0;
790 }
791