exec_elf32.c revision 1.55
1/*	$NetBSD: exec_elf32.c,v 1.55 2000/11/08 05:47:56 chs 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#include "opt_compat_freebsd.h"
75#include "opt_compat_netbsd32.h"
76#include "opt_syscall_debug.h"
77
78#include <sys/param.h>
79#include <sys/proc.h>
80#include <sys/malloc.h>
81#include <sys/namei.h>
82#include <sys/vnode.h>
83#include <sys/exec.h>
84#include <sys/exec_elf.h>
85#include <sys/syscall.h>
86#include <sys/signalvar.h>
87#include <sys/mount.h>
88#include <sys/stat.h>
89
90#ifdef COMPAT_NETBSD32
91#include <compat/netbsd32/netbsd32_exec.h>
92#endif
93
94#ifdef COMPAT_LINUX
95#include <compat/linux/common/linux_exec.h>
96#endif
97
98#ifdef COMPAT_SVR4
99#include <compat/svr4/svr4_exec.h>
100#endif
101
102#ifdef COMPAT_IBCS2
103#include <compat/ibcs2/ibcs2_exec.h>
104#endif
105
106#ifdef COMPAT_FREEBSD
107#include <compat/freebsd/freebsd_exec.h>
108#endif
109
110int	ELFNAME(check_header)(Elf_Ehdr *, int);
111int	ELFNAME(load_file)(struct proc *, struct exec_package *, char *,
112	    struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *);
113void	ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *,
114	    const Elf_Phdr *, Elf_Addr *, u_long *, int *, int);
115
116int ELFNAME2(netbsd,signature)(struct proc *, struct exec_package *,
117    Elf_Ehdr *);
118static int ELFNAME2(netbsd,probe)(struct proc *, struct exec_package *,
119    Elf_Ehdr *, char *, Elf_Addr *);
120
121extern char sigcode[], esigcode[];
122#ifdef SYSCALL_DEBUG
123extern char *syscallnames[];
124#endif
125
126struct 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	howmany(ELF_AUX_ENTRIES * sizeof(AuxInfo), sizeof (Elf_Addr)),
139	ELFNAME(copyargs),
140	setregs,
141	sigcode,
142	esigcode,
143};
144
145int (*ELFNAME(probe_funcs)[])(struct proc *, struct exec_package *,
146    Elf_Ehdr *, char *, Elf_Addr *) = {
147#if defined(COMPAT_NETBSD32) && (ELFSIZE == 32)
148	    /* This one should go first so it matches instead of netbsd */
149	ELFNAME2(netbsd32,probe),
150#endif
151	ELFNAME2(netbsd,probe),
152#if defined(COMPAT_FREEBSD) && (ELFSIZE == 32)
153	ELFNAME2(freebsd,probe),		/* XXX not 64-bit safe */
154#endif
155#if defined(COMPAT_LINUX)
156	ELFNAME2(linux,probe),
157#endif
158#if defined(COMPAT_SVR4) && (ELFSIZE == 32)
159	ELFNAME2(svr4,probe),			/* XXX not 64-bit safe */
160#endif
161#if defined(COMPAT_IBCS2) && (ELFSIZE == 32)
162	ELFNAME2(ibcs2,probe),			/* XXX not 64-bit safe */
163#endif
164};
165
166/* round up and down to page boundaries. */
167#define	ELF_ROUND(a, b)		(((a) + (b) - 1) & ~((b) - 1))
168#define	ELF_TRUNC(a, b)		((a) & ~((b) - 1))
169
170/*
171 * Copy arguments onto the stack in the normal way, but add some
172 * extra information in case of dynamic binding.
173 */
174void *
175ELFNAME(copyargs)(struct exec_package *pack, struct ps_strings *arginfo,
176    void *stack, void *argp)
177{
178	size_t len;
179	AuxInfo ai[ELF_AUX_ENTRIES], *a;
180	struct elf_args *ap;
181
182	stack = copyargs(pack, arginfo, stack, argp);
183	if (!stack)
184		return NULL;
185
186	a = ai;
187
188	/*
189	 * Push extra arguments on the stack needed by dynamically
190	 * linked binaries
191	 */
192	if ((ap = (struct elf_args *)pack->ep_emul_arg)) {
193
194		a->a_type = AT_PHDR;
195		a->a_v = ap->arg_phaddr;
196		a++;
197
198		a->a_type = AT_PHENT;
199		a->a_v = ap->arg_phentsize;
200		a++;
201
202		a->a_type = AT_PHNUM;
203		a->a_v = ap->arg_phnum;
204		a++;
205
206		a->a_type = AT_PAGESZ;
207		a->a_v = NBPG;
208		a++;
209
210		a->a_type = AT_BASE;
211		a->a_v = ap->arg_interp;
212		a++;
213
214		a->a_type = AT_FLAGS;
215		a->a_v = 0;
216		a++;
217
218		a->a_type = AT_ENTRY;
219		a->a_v = ap->arg_entry;
220		a++;
221
222		free((char *)ap, M_TEMP);
223		pack->ep_emul_arg = NULL;
224	}
225
226	a->a_type = AT_NULL;
227	a->a_v = 0;
228	a++;
229
230	len = (a - ai) * sizeof(AuxInfo);
231	if (copyout(ai, stack, len))
232		return NULL;
233	stack = (caddr_t)stack + len;
234
235	return stack;
236}
237
238/*
239 * elf_check_header():
240 *
241 * Check header for validity; return 0 of ok ENOEXEC if error
242 */
243int
244ELFNAME(check_header)(Elf_Ehdr *eh, int type)
245{
246
247	if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0 ||
248	    eh->e_ident[EI_CLASS] != ELFCLASS)
249		return ENOEXEC;
250
251	switch (eh->e_machine) {
252
253	ELFDEFNNAME(MACHDEP_ID_CASES)
254
255	default:
256		return ENOEXEC;
257	}
258
259	if (eh->e_type != type)
260		return ENOEXEC;
261
262	return 0;
263}
264
265/*
266 * elf_load_psection():
267 *
268 * Load a psection at the appropriate address
269 */
270void
271ELFNAME(load_psection)(struct exec_vmcmd_set *vcset, struct vnode *vp,
272    const Elf_Phdr *ph, Elf_Addr *addr, u_long *size, int *prot, int flags)
273{
274	u_long uaddr, msize, psize, rm, rf;
275	long diff, offset;
276
277	/*
278	 * If the user specified an address, then we load there.
279	 */
280	if (*addr != ELFDEFNNAME(NO_ADDR)) {
281		if (ph->p_align > 1) {
282			*addr = ELF_TRUNC(*addr, ph->p_align);
283			uaddr = ELF_TRUNC(ph->p_vaddr, ph->p_align);
284		} else
285			uaddr = ph->p_vaddr;
286		diff = ph->p_vaddr - uaddr;
287	} else {
288		*addr = uaddr = ph->p_vaddr;
289		if (ph->p_align > 1)
290			*addr = ELF_TRUNC(uaddr, ph->p_align);
291		diff = uaddr - *addr;
292	}
293
294	*prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0;
295	*prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0;
296	*prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0;
297
298	offset = ph->p_offset - diff;
299	*size = ph->p_filesz + diff;
300	msize = ph->p_memsz + diff;
301	psize = round_page(*size);
302
303	if ((ph->p_flags & PF_W) != 0) {
304		/*
305		 * Because the pagedvn pager can't handle zero fill of the last
306		 * data page if it's not page aligned we map the last page
307		 * readvn.
308		 */
309		psize = trunc_page(*size);
310	}
311	if (psize > 0) {
312		NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, *addr, vp,
313		    offset, *prot, flags);
314	}
315	if (psize < *size) {
316		NEW_VMCMD2(vcset, vmcmd_map_readvn, *size - psize,
317		    *addr + psize, vp, offset + psize, *prot,
318		    psize > 0 ? flags & VMCMD_RELATIVE : flags);
319	}
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_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP,
329		    0, *prot, flags & VMCMD_RELATIVE);
330		*size = msize;
331	}
332}
333
334/*
335 * elf_read_from():
336 *
337 *	Read from vnode into buffer at offset.
338 */
339int
340ELFNAME(read_from)(struct proc *p, struct vnode *vp, u_long off,
341    caddr_t buf, int size)
342{
343	int error;
344	size_t resid;
345
346	if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE,
347	    0, p->p_ucred, &resid, p)) != 0)
348		return error;
349	/*
350	 * See if we got all of it
351	 */
352	if (resid != 0)
353		return ENOEXEC;
354	return 0;
355}
356
357/*
358 * elf_load_file():
359 *
360 * Load a file (interpreter/library) pointed to by path
361 * [stolen from coff_load_shlib()]. Made slightly generic
362 * so it might be used externally.
363 */
364int
365ELFNAME(load_file)(struct proc *p, struct exec_package *epp, char *path,
366    struct exec_vmcmd_set *vcset, u_long *entry, struct elf_args *ap,
367    Elf_Addr *last)
368{
369	int error, i;
370	struct nameidata nd;
371	struct vnode *vp;
372	struct vattr attr;
373	Elf_Ehdr eh;
374	Elf_Phdr *ph = NULL;
375	Elf_Phdr *base_ph = NULL;
376	u_long phsize;
377	char *bp = NULL;
378	Elf_Addr addr = *last;
379
380	bp = path;
381	/*
382	 * 1. open file
383	 * 2. read filehdr
384	 * 3. map text, data, and bss out of it using VM_*
385	 */
386	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
387	if ((error = namei(&nd)) != 0)
388		return error;
389	vp = nd.ni_vp;
390
391	/*
392	 * Similarly, if it's not marked as executable, or it's not a regular
393	 * file, we don't allow it to be used.
394	 */
395	if (vp->v_type != VREG) {
396		error = EACCES;
397		goto badunlock;
398	}
399	if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0)
400		goto badunlock;
401
402	/* get attributes */
403	if ((error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) != 0)
404		goto badunlock;
405
406	/*
407	 * Check mount point.  Though we're not trying to exec this binary,
408	 * we will be executing code from it, so if the mount point
409	 * disallows execution or set-id-ness, we punt or kill the set-id.
410	 */
411	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
412		error = EACCES;
413		goto badunlock;
414	}
415	if (vp->v_mount->mnt_flag & MNT_NOSUID)
416		epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
417
418#ifdef notyet /* XXX cgd 960926 */
419	XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?)
420#endif
421	VOP_UNLOCK(vp, 0);
422
423	if ((error = ELFNAME(read_from)(p, vp, 0, (caddr_t) &eh,
424	    sizeof(eh))) != 0)
425		goto bad;
426
427	if ((error = ELFNAME(check_header)(&eh, ET_DYN)) != 0)
428		goto bad;
429
430	phsize = eh.e_phnum * sizeof(Elf_Phdr);
431	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
432
433	if ((error = ELFNAME(read_from)(p, vp, eh.e_phoff,
434	    (caddr_t) ph, phsize)) != 0)
435		goto bad;
436
437	/*
438	 * Load all the necessary sections
439	 */
440	for (i = 0; i < eh.e_phnum; i++) {
441		u_long size = 0;
442		int prot = 0;
443		int flags;
444
445		switch (ph[i].p_type) {
446		case PT_LOAD:
447			if (base_ph == NULL) {
448				addr = *last;
449				flags = VMCMD_BASE;
450			} else {
451				addr = ph[i].p_vaddr - base_ph->p_vaddr;
452				flags = VMCMD_RELATIVE;
453			}
454			ELFNAME(load_psection)(vcset, vp, &ph[i], &addr,
455			    &size, &prot, flags);
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			if (base_ph == NULL)
467				base_ph = &ph[i];
468			addr += size;
469			break;
470
471		case PT_DYNAMIC:
472		case PT_PHDR:
473		case PT_NOTE:
474			break;
475
476		default:
477			break;
478		}
479	}
480
481	free((char *)ph, M_TEMP);
482	*last = addr;
483	vrele(vp);
484	return 0;
485
486badunlock:
487	VOP_UNLOCK(vp, 0);
488
489bad:
490	if (ph != NULL)
491		free((char *)ph, M_TEMP);
492#ifdef notyet /* XXX cgd 960926 */
493	(maybe) VOP_CLOSE it
494#endif
495	vrele(vp);
496	return error;
497}
498
499/*
500 * exec_elf_makecmds(): Prepare an Elf binary's exec package
501 *
502 * First, set of the various offsets/lengths in the exec package.
503 *
504 * Then, mark the text image busy (so it can be demand paged) or error
505 * out if this is not possible.  Finally, set up vmcmds for the
506 * text, data, bss, and stack segments.
507 */
508int
509ELFNAME2(exec,makecmds)(struct proc *p, 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	/*
522	 * XXX allow for executing shared objects. It seems silly
523	 * but other ELF-based systems allow it as well.
524	 */
525	if (ELFNAME(check_header)(eh, ET_EXEC) != 0 &&
526	    ELFNAME(check_header)(eh, ET_DYN) != 0)
527		return ENOEXEC;
528
529	/*
530	 * check if vnode is in open for writing, because we want to
531	 * demand-page out of it.  if it is, don't do it, for various
532	 * reasons
533	 */
534	if (epp->ep_vp->v_writecount != 0) {
535#ifdef DIAGNOSTIC
536		if (epp->ep_vp->v_flag & VTEXT)
537			panic("exec: a VTEXT vnode has writecount != 0\n");
538#endif
539		return ETXTBSY;
540	}
541	/*
542	 * Allocate space to hold all the program headers, and read them
543	 * from the file
544	 */
545	phsize = eh->e_phnum * sizeof(Elf_Phdr);
546	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
547
548	if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff,
549	    (caddr_t) ph, phsize)) != 0)
550		goto bad;
551
552	epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR);
553	epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR);
554
555	interp[0] = '\0';
556
557	for (i = 0; i < eh->e_phnum; i++) {
558		pp = &ph[i];
559		if (pp->p_type == PT_INTERP) {
560			if (pp->p_filesz >= sizeof(interp))
561				goto bad;
562			if ((error = ELFNAME(read_from)(p, epp->ep_vp,
563			    pp->p_offset, (caddr_t) interp,
564			    pp->p_filesz)) != 0)
565				goto bad;
566			break;
567		}
568	}
569
570	/*
571	 * Setup things for native emulation.
572	 */
573	epp->ep_emul = &ELFNAMEEND(emul_netbsd);
574	pos = ELFDEFNNAME(NO_ADDR);
575
576	/*
577	 * On the same architecture, we may be emulating different systems.
578	 * See which one will accept this executable. This currently only
579	 * applies to SVR4, and IBCS2 on the i386 and Linux on the i386
580	 * and the Alpha.
581	 *
582	 * Probe functions would normally see if the interpreter (if any)
583	 * exists. Emulation packages may possibly replace the interpreter in
584	 * interp[] with a changed path (/emul/xxx/<path>), and also
585	 * set the ep_emul field in the exec package structure.
586	 */
587	n = sizeof(ELFNAME(probe_funcs)) / sizeof(ELFNAME(probe_funcs)[0]);
588	if (n != 0) {
589		error = ENOEXEC;
590		for (i = 0; i < n && error; i++)
591			error = ELFNAME(probe_funcs)[i](p, epp, eh,
592			    interp, &pos);
593#ifdef notyet
594		/*
595		 * We should really use a signature in our native binaries
596		 * and have our own probe function for matching binaries,
597		 * before trying the emulations. For now, if the emulation
598		 * probes failed we default to native.
599		 */
600		if (error)
601			goto bad;
602#endif
603	}
604
605	/*
606	 * Load all the necessary sections
607	 */
608	for (i = nload = 0; i < eh->e_phnum; i++) {
609		Elf_Addr  addr = ELFDEFNNAME(NO_ADDR);
610		u_long size = 0;
611		int prot = 0;
612
613		pp = &ph[i];
614
615		switch (ph[i].p_type) {
616		case PT_LOAD:
617			/*
618			 * XXX
619			 * Can handle only 2 sections: text and data
620			 */
621			if (nload++ == 2)
622				goto bad;
623			ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp,
624			    &ph[i], &addr, &size, &prot, 0);
625
626			/*
627			 * Decide whether it's text or data by looking
628			 * at the entry point.
629			 */
630			if (eh->e_entry >= addr &&
631			    eh->e_entry < (addr + size)) {
632				epp->ep_taddr = addr;
633				epp->ep_tsize = size;
634				if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) {
635					epp->ep_daddr = addr;
636					epp->ep_dsize = size;
637				}
638			} else {
639				epp->ep_daddr = addr;
640				epp->ep_dsize = size;
641			}
642			break;
643
644		case PT_SHLIB:
645#ifndef COMPAT_IBCS2			/* SCO has these sections */
646			error = ENOEXEC;
647			goto bad;
648#endif
649
650		case PT_INTERP:
651			/* Already did this one */
652		case PT_DYNAMIC:
653		case PT_NOTE:
654			break;
655
656		case PT_PHDR:
657			/* Note address of program headers (in text segment) */
658			phdr = pp->p_vaddr;
659			break;
660
661		default:
662			/*
663			 * Not fatal; we don't need to understand everything.
664			 */
665			break;
666		}
667	}
668
669	/* this breaks on, e.g., OpenBSD-compatible mips shared binaries. */
670#ifndef ELF_INTERP_NON_RELOCATABLE
671	/*
672	 * If no position to load the interpreter was set by a probe
673	 * function, pick the same address that a non-fixed mmap(0, ..)
674	 * would (i.e. something safely out of the way).
675	 */
676	if (pos == ELFDEFNNAME(NO_ADDR))
677		pos = round_page(epp->ep_daddr + MAXDSIZ);
678#endif	/* !ELF_INTERP_NON_RELOCATABLE */
679
680	/*
681	 * Check if we found a dynamically linked binary and arrange to load
682	 * it's interpreter
683	 */
684	if (interp[0]) {
685		struct elf_args *ap;
686
687		ap = (struct elf_args *)malloc(sizeof(struct elf_args),
688		    M_TEMP, M_WAITOK);
689		if ((error = ELFNAME(load_file)(p, epp, interp,
690		    &epp->ep_vmcmds, &epp->ep_entry, ap, &pos)) != 0) {
691			free((char *)ap, M_TEMP);
692			goto bad;
693		}
694		pos += phsize;
695		ap->arg_phaddr = phdr;
696
697		ap->arg_phentsize = eh->e_phentsize;
698		ap->arg_phnum = eh->e_phnum;
699		ap->arg_entry = eh->e_entry;
700
701		epp->ep_emul_arg = ap;
702	} else
703		epp->ep_entry = eh->e_entry;
704
705#ifdef ELF_MAP_PAGE_ZERO
706	/* Dell SVR4 maps page zero, yeuch! */
707	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, NBPG, 0, epp->ep_vp, 0,
708	    VM_PROT_READ);
709#endif
710	free((char *)ph, M_TEMP);
711	vn_marktext(epp->ep_vp);
712	return exec_elf_setup_stack(p, epp);
713
714bad:
715	free((char *)ph, M_TEMP);
716	kill_vmcmds(&epp->ep_vmcmds);
717	return ENOEXEC;
718}
719
720int
721ELFNAME2(netbsd,signature)(struct proc *p, struct exec_package *epp,
722    Elf_Ehdr *eh)
723{
724	Elf_Phdr *hph, *ph;
725	Elf_Nhdr *np = NULL;
726	size_t phsize;
727	int error;
728
729	phsize = eh->e_phnum * sizeof(Elf_Phdr);
730	hph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
731	if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff,
732	    (caddr_t)hph, phsize)) != 0)
733		goto out1;
734
735	for (ph = hph;  ph < &hph[eh->e_phnum]; ph++) {
736		if (ph->p_type != PT_NOTE ||
737		    ph->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
738			continue;
739
740		np = (Elf_Nhdr *)malloc(ph->p_filesz, M_TEMP, M_WAITOK);
741		if ((error = ELFNAME(read_from)(p, epp->ep_vp, ph->p_offset,
742		    (caddr_t)np, ph->p_filesz)) != 0)
743			goto out2;
744
745		if (np->n_type != ELF_NOTE_TYPE_OSVERSION) {
746			free(np, M_TEMP);
747			np = NULL;
748			continue;
749		}
750
751		/* Check the name and description sizes. */
752		if (np->n_namesz != ELF_NOTE_NETBSD_NAMESZ ||
753		    np->n_descsz != ELF_NOTE_NETBSD_DESCSZ)
754			goto out3;
755
756		/* Is the name "NetBSD\0\0"? */
757		if (memcmp((np + 1), ELF_NOTE_NETBSD_NAME,
758		    ELF_NOTE_NETBSD_NAMESZ))
759			goto out3;
760
761		/* XXX: We could check for the specific emulation here */
762		/* All checks succeeded. */
763		error = 0;
764		goto out2;
765	}
766
767out3:
768	error = ENOEXEC;
769out2:
770	if (np)
771		free(np, M_TEMP);
772out1:
773	free(hph, M_TEMP);
774	return error;
775}
776
777static int
778ELFNAME2(netbsd,probe)(struct proc *p, struct exec_package *epp,
779    Elf_Ehdr *eh, char *itp, Elf_Addr *pos)
780{
781	int error;
782
783	if ((error = ELFNAME2(netbsd,signature)(p, epp, eh)) != 0)
784		return error;
785	epp->ep_emul = &ELFNAMEEND(emul_netbsd);
786	*pos = ELFDEFNNAME(NO_ADDR);
787	return 0;
788}
789