xref: /openbsd-src/sys/kern/exec_elf.c (revision a4afd6dad3fba28f80e70208181c06c482259988)
1 /*	$OpenBSD: exec_elf.c,v 1.18 1996/11/24 18:31:25 etheisen Exp $	*/
2 
3 /*
4  * Copyright (c) 1996 Per Fogelstrom
5  * All rights reserved.
6  *
7  * Copyright (c) 1994 Christos Zoulas
8  * All rights reserved.
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. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/proc.h>
38 #include <sys/malloc.h>
39 #include <sys/mount.h>
40 #include <sys/namei.h>
41 #include <sys/vnode.h>
42 #include <sys/exec.h>
43 #include <sys/exec_elf.h>
44 #include <sys/exec_olf.h>
45 #include <sys/file.h>
46 #include <sys/syscall.h>
47 #include <sys/signalvar.h>
48 #include <sys/stat.h>
49 
50 #if defined(COMPAT_LINUX) || defined(COMPAT_SVR4)	/*XXX should be */
51 #undef EXEC_ELF						/*XXX defined in */
52 #define EXEC_ELF					/*XXX machine/exec.h */
53 #endif							/*XXX instead ? */
54 
55 #if defined(NATIVE_EXEC_ELF) || defined(EXEC_ELF)
56 
57 #include <sys/mman.h>
58 #include <vm/vm.h>
59 #include <vm/vm_param.h>
60 #include <vm/vm_map.h>
61 
62 #include <machine/cpu.h>
63 #include <machine/reg.h>
64 #include <machine/exec.h>
65 
66 #ifdef COMPAT_LINUX
67 #include <compat/linux/linux_exec.h>
68 #endif
69 
70 #ifdef COMPAT_SVR4
71 #include <compat/svr4/svr4_exec.h>
72 #endif
73 
74 int (*elf_probe_funcs[]) __P((struct proc *, struct exec_package *,
75 			      char *, u_long *)) = {
76 #ifdef COMPAT_SVR4
77 	svr4_elf_probe,
78 #endif
79 #ifdef COMPAT_LINUX
80 	linux_elf_probe
81 #endif
82 };
83 
84 int elf_load_file __P((struct proc *, char *, struct exec_package *,
85 		       struct elf_args *, u_long *));
86 
87 int elf_check_header __P((Elf32_Ehdr *, int));
88 int olf_check_header __P((Elf32_Ehdr *, int));
89 int elf_read_from __P((struct proc *, struct vnode *, u_long, caddr_t, int));
90 void elf_load_psection __P((struct exec_vmcmd_set *,
91 	struct vnode *, Elf32_Phdr *, u_long *, u_long *, int *));
92 
93 int exec_elf_fixup __P((struct proc *, struct exec_package *));
94 
95 #define ELF_ALIGN(a, b) ((a) & ~((b) - 1))
96 
97 /*
98  * This is the basic elf emul. elf_probe_funcs may change to other emuls.
99  */
100 
101 extern char sigcode[], esigcode[];
102 #ifdef SYSCALL_DEBUG
103 extern char *syscallnames[];
104 #endif
105 
106 struct emul emul_elf = {
107 	"native",
108 	NULL,
109 	sendsig,
110 	SYS_syscall,
111 	SYS_MAXSYSCALL,
112 	sysent,
113 #ifdef SYSCALL_DEBUG
114 	syscallnames,
115 #else
116 	NULL,
117 #endif
118 	sizeof(AuxInfo) * ELF_AUX_ENTRIES,
119 	elf_copyargs,
120 	setregs,
121 	exec_elf_fixup,
122 	sigcode,
123 	esigcode,
124 };
125 
126 
127 /*
128  * Copy arguments onto the stack in the normal way, but add some
129  * space for extra information in case of dynamic binding.
130  */
131 void *
132 elf_copyargs(pack, arginfo, stack, argp)
133 	struct exec_package *pack;
134 	struct ps_strings *arginfo;
135 	void *stack;
136 	void *argp;
137 {
138 	stack = copyargs(pack, arginfo, stack, argp);
139 	if (!stack)
140 		return NULL;
141 
142 	/*
143 	 * Push space for extra arguments on the stack needed by
144 	 * dynamically linked binaries
145 	 */
146 	if (pack->ep_interp != NULL) {
147 		pack->ep_emul_argp = stack;
148 		stack += ELF_AUX_ENTRIES * sizeof (AuxInfo);
149 	}
150 	return stack;
151 }
152 
153 /*
154  * elf_check_header():
155  *
156  * Check header for validity; return 0 for ok, ENOEXEC if error
157  */
158 int
159 elf_check_header(ehdr, type)
160 	Elf32_Ehdr *ehdr;
161 	int type;
162 {
163         /*
164 	 * We need to check magic, class size, endianess, and version before
165 	 * we look at the rest of the Elf32_Ehdr structure. These few elements
166 	 * are represented in a machine independant fashion.
167 	 */
168 	if (!IS_ELF(*ehdr) ||
169 	    ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
170 	    ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
171 	    ehdr->e_ident[EI_VERSION] != ELF_TARG_VER)
172                 return ENOEXEC;
173 
174         /* Now check the machine dependant header */
175 	if (ehdr->e_machine != ELF_TARG_MACH ||
176 	    ehdr->e_version != ELF_TARG_VER)
177                 return ENOEXEC;
178 
179         /* Check the type */
180 	if (ehdr->e_type != type)
181 		return ENOEXEC;
182 
183 	return 0;
184 }
185 
186 /*
187  * olf_check_header():
188  *
189  * Check header for validity; return 0 for ok, ENOEXEC if error
190  */
191 int
192 olf_check_header(ehdr, type)
193 	Elf32_Ehdr *ehdr;
194 	int type;
195 {
196         /*
197 	 * We need to check magic, class size, endianess, version, and OS
198 	 * before we look at the rest of the Elf32_Ehdr structure. These few
199 	 * elements are represented in a machine independant fashion.
200 	 */
201 	if (!IS_OLF(*ehdr) ||
202 	    ehdr->e_ident[OI_CLASS] != ELF_TARG_CLASS ||
203 	    ehdr->e_ident[OI_DATA] != ELF_TARG_DATA ||
204 	    ehdr->e_ident[OI_VERSION] != ELF_TARG_VER ||
205 	    ehdr->e_ident[OI_OS] != OOS_OPENBSD)
206                 return ENOEXEC;
207 
208         /* Now check the machine dependant header */
209 	if (ehdr->e_machine != ELF_TARG_MACH ||
210 	    ehdr->e_version != ELF_TARG_VER)
211                 return ENOEXEC;
212 
213         /* Check the type */
214 	if (ehdr->e_type != type)
215 		return ENOEXEC;
216 
217 	return 0;
218 }
219 
220 /*
221  * elf_load_psection():
222  *
223  * Load a psection at the appropriate address
224  */
225 void
226 elf_load_psection(vcset, vp, ph, addr, size, prot)
227 	struct exec_vmcmd_set *vcset;
228 	struct vnode *vp;
229 	Elf32_Phdr *ph;
230 	u_long *addr;
231 	u_long *size;
232 	int *prot;
233 {
234 	u_long uaddr, msize, psize, rm, rf;
235 	long diff, offset;
236 
237 	/*
238 	 * If the user specified an address, then we load there.
239 	 */
240 	if (*addr != ELF32_NO_ADDR) {
241 		if (ph->p_align > 1) {
242 			*addr = ELF_ALIGN(*addr + ph->p_align, ph->p_align);
243 			uaddr = ELF_ALIGN(ph->p_vaddr, ph->p_align);
244 		} else
245 			uaddr = ph->p_vaddr;
246 		diff = ph->p_vaddr - uaddr;
247 	} else {
248 		*addr = uaddr = ph->p_vaddr;
249 		if (ph->p_align > 1)
250 			*addr = ELF_ALIGN(uaddr, ph->p_align);
251 		diff = uaddr - *addr;
252 	}
253 
254 	*prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0;
255 	*prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0;
256 	*prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0;
257 
258 	offset = ph->p_offset - diff;
259 	*size = ph->p_filesz + diff;
260 	msize = ph->p_memsz + diff;
261 	psize = round_page(*size);
262 
263 	/*
264 	 * Because the pagedvn pager can't handle zero fill of the last
265 	 * data page if it's not page aligned we map the las page readvn.
266 	 */
267 	if(ph->p_flags & PF_W) {
268 		psize = trunc_page(*size);
269 		NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp, offset, *prot);
270 		if(psize != *size) {
271 			NEW_VMCMD(vcset, vmcmd_map_readvn, *size - psize, *addr
272 + psize, vp, offset + psize, *prot);
273 		}
274 	}
275 	else {
276 		 NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp, offset, *prot);
277 	}
278 
279 	/*
280 	 * Check if we need to extend the size of the segment
281 	 */
282 	rm = round_page(*addr + msize);
283 	rf = round_page(*addr + *size);
284 
285 	if (rm != rf) {
286 		NEW_VMCMD(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0, *prot);
287 		*size = msize;
288 	}
289 }
290 
291 /*
292  * elf_read_from():
293  *
294  *	Read from vnode into buffer at offset.
295  */
296 int
297 elf_read_from(p, vp, off, buf, size)
298 	struct proc *p;
299 	struct vnode *vp;
300 	u_long off;
301 	caddr_t buf;
302 	int size;
303 {
304 	int error;
305 	int resid;
306 
307 	if ((error = vn_rdwr(UIO_READ, vp, buf, size,
308 			     off, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
309 			     &resid, p)) != 0)
310 		return error;
311 	/*
312 	 * See if we got all of it
313 	 */
314 	if (resid != 0)
315 		return ENOEXEC;
316 	return 0;
317 }
318 
319 /*
320  * elf_load_file():
321  *
322  * Load a file (interpreter/library) pointed to by path
323  * [stolen from coff_load_shlib()]. Made slightly generic
324  * so it might be used externally.
325  */
326 int
327 elf_load_file(p, path, epp, ap, last)
328 	struct proc *p;
329 	char *path;
330 	struct exec_package *epp;
331 	struct elf_args	*ap;
332 	u_long *last;
333 {
334 	int error, i;
335 	struct nameidata nd;
336 	Elf32_Ehdr eh;
337 	Elf32_Phdr *ph = NULL;
338 	u_long phsize;
339 	char *bp = NULL;
340 	u_long addr = *last;
341 	struct vnode *vp;
342 
343 	bp = path;
344 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
345 	if ((error = namei(&nd)) != 0) {
346 		return error;
347 	}
348 	vp = nd.ni_vp;
349 	if (vp->v_type != VREG) {
350 		error = EACCES;
351 		goto bad;
352 	}
353 	if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0)
354 		goto bad;
355 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
356 		error = EACCES;
357 		goto bad;
358 	}
359 	if ((error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) != 0)
360 		goto bad1;
361 	if ((error = elf_read_from(p, nd.ni_vp, 0,
362 				    (caddr_t) &eh, sizeof(eh))) != 0)
363 		goto bad1;
364 
365 	if (elf_check_header(&eh, ET_DYN) && olf_check_header(&eh, ET_DYN)) {
366 		error = ENOEXEC;
367 		goto bad1;
368 	}
369 
370 	phsize = eh.e_phnum * sizeof(Elf32_Phdr);
371 	ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
372 
373 	if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff,
374 				    (caddr_t) ph, phsize)) != 0)
375 		goto bad1;
376 
377 	/*
378 	 * Load all the necessary sections
379 	 */
380 	for (i = 0; i < eh.e_phnum; i++) {
381 		u_long size = 0;
382 		int prot = 0;
383 #ifdef mips
384 		if (*last == ELF32_NO_ADDR)
385 			addr = ELF32_NO_ADDR;	/* GRRRRR!!!!! */
386 #endif
387 
388 		switch (ph[i].p_type) {
389 		case PT_LOAD:
390 			elf_load_psection(&epp->ep_vmcmds, nd.ni_vp, &ph[i],
391 						&addr, &size, &prot);
392 			/* If entry is within this section it must be text */
393 			if (eh.e_entry >= ph[i].p_vaddr &&
394 			    eh.e_entry < (ph[i].p_vaddr + size)) {
395  				epp->ep_entry = addr + eh.e_entry -
396                                         ELF_ALIGN(ph[i].p_vaddr,ph[i].p_align);
397 				ap->arg_interp = addr;
398 			}
399 			addr += size;
400 			break;
401 
402 		case PT_DYNAMIC:
403 		case PT_PHDR:
404 		case PT_NOTE:
405 			break;
406 
407 		default:
408 			break;
409 		}
410 	}
411 
412 bad1:
413 	VOP_CLOSE(nd.ni_vp, FREAD, p->p_ucred, p);
414 bad:
415 	if (ph != NULL)
416 		free((char *) ph, M_TEMP);
417 
418 	*last = addr;
419 	vput(nd.ni_vp);
420 	return error;
421 }
422 
423 /*
424  * exec_elf_makecmds(): Prepare an Elf binary's exec package
425  *
426  * First, set of the various offsets/lengths in the exec package.
427  *
428  * Then, mark the text image busy (so it can be demand paged) or error
429  * out if this is not possible.  Finally, set up vmcmds for the
430  * text, data, bss, and stack segments.
431  *
432  */
433 int
434 exec_elf_makecmds(p, epp)
435 	struct proc *p;
436 	struct exec_package *epp;
437 {
438 	Elf32_Ehdr *eh = epp->ep_hdr;
439 	Elf32_Phdr *ph, *pp;
440 	Elf32_Addr phdr = 0;
441 	int error, i, n, nload;
442 	char interp[MAXPATHLEN];
443 	u_long pos = 0, phsize;
444 
445 	if (epp->ep_hdrvalid < sizeof(Elf32_Ehdr))
446 		return ENOEXEC;
447 
448 	if (elf_check_header(eh, ET_EXEC) && olf_check_header(eh, ET_EXEC))
449 		return ENOEXEC;
450 
451 	/*
452 	 * check if vnode is in open for writing, because we want to
453 	 * demand-page out of it.  if it is, don't do it, for various
454 	 * reasons
455 	 */
456 	if (epp->ep_vp->v_writecount != 0) {
457 #ifdef DIAGNOSTIC
458 		if (epp->ep_vp->v_flag & VTEXT)
459 			panic("exec: a VTEXT vnode has writecount != 0\n");
460 #endif
461 		return ETXTBSY;
462 	}
463 	/*
464 	 * Allocate space to hold all the program headers, and read them
465 	 * from the file
466 	 */
467 	phsize = eh->e_phnum * sizeof(Elf32_Phdr);
468 	ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
469 
470 	if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff,
471 				    (caddr_t) ph, phsize)) != 0)
472 		goto bad;
473 
474 	epp->ep_tsize = ELF32_NO_ADDR;
475 	epp->ep_dsize = ELF32_NO_ADDR;
476 
477 	interp[0] = '\0';
478 
479 	for (i = 0; i < eh->e_phnum; i++) {
480 		pp = &ph[i];
481 		if (pp->p_type == PT_INTERP) {
482 			if (pp->p_filesz >= sizeof(interp))
483 				goto bad;
484 			if ((error = elf_read_from(p, epp->ep_vp, pp->p_offset,
485 			    (caddr_t) interp, pp->p_filesz)) != 0)
486 				goto bad;
487 			break;
488 		}
489 	}
490 
491 	/*
492 	 * OK, we want a slightly different twist of the
493 	 * standard emulation package for "real" elf.
494 	 */
495 	epp->ep_emul = &emul_elf;
496 	pos = ELF32_NO_ADDR;
497 
498 	/*
499 	 * On the same architecture, we may be emulating different systems.
500 	 * See which one will accept this executable. This currently only
501 	 * applies to Linux and SVR4 on the i386.
502 	 *
503 	 * Probe functions would normally see if the interpreter (if any)
504 	 * exists. Emulation packages may possibly replace the interpreter in
505 	 * interp[] with a changed path (/emul/xxx/<path>), and also
506 	 * set the ep_emul field in the exec package structure.
507 	 */
508 	if ((n = sizeof elf_probe_funcs / sizeof elf_probe_funcs[0])) {
509 		error = ENOEXEC;
510 		for (i = 0; i < n && error; i++)
511 			error = elf_probe_funcs[i](p, epp, interp, &pos);
512 
513 		if (error)
514 			goto bad;
515 	}
516 
517 	/*
518 	 * Load all the necessary sections
519 	 */
520 	for (i = nload = 0; i < eh->e_phnum; i++) {
521 		u_long  addr = ELF32_NO_ADDR, size = 0;
522 		int prot = 0;
523 
524 		pp = &ph[i];
525 
526 		switch (ph[i].p_type) {
527 		case PT_LOAD:
528 			/*
529 			 * XXX
530 			 * Can handle only 2 sections: text and data
531 			 */
532 			if (nload++ == 2)
533 				goto bad;
534 			elf_load_psection(&epp->ep_vmcmds, epp->ep_vp,
535 				&ph[i], &addr, &size, &prot);
536 			/*
537 			 * Decide whether it's text or data by looking
538 			 * at the entry point.
539 			 */
540 			if (eh->e_entry >= addr && eh->e_entry < (addr + size)){
541 				epp->ep_taddr = addr;
542 				epp->ep_tsize = size;
543 			} else {
544 				epp->ep_daddr = addr;
545 				epp->ep_dsize = size;
546 			}
547 			break;
548 
549 		case PT_SHLIB:
550 			error = ENOEXEC;
551 			goto bad;
552 
553 		case PT_INTERP:
554 			/* Already did this one */
555 		case PT_DYNAMIC:
556 		case PT_NOTE:
557 			break;
558 
559 		case PT_PHDR:
560 			/* Note address of program headers (in text segment) */
561 			phdr = pp->p_vaddr;
562 			break;
563 
564 		default:
565 			/*
566 			 * Not fatal, we don't need to understand everything :-)
567 			 */
568 			break;
569 		}
570 	}
571 
572 #if !defined(mips)
573 	/*
574 	 * If no position to load the interpreter was set by a probe
575 	 * function, pick the same address that a non-fixed mmap(0, ..)
576 	 * would (i.e. something safely out of the way).
577 	 */
578 	if (pos == ELF32_NO_ADDR)
579 		pos = round_page(epp->ep_daddr + MAXDSIZ);
580 #endif
581 
582 	/*
583 	 * Check if we found a dynamically linked binary and arrange to load
584 	 * it's interpreter when the exec file is released.
585 	 */
586 	if (interp[0]) {
587 		char *ip;
588 		struct elf_args *ap;
589 
590 		ip = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
591 		ap = (struct elf_args *) malloc(sizeof(struct elf_args),
592 						 M_TEMP, M_WAITOK);
593 
594 		bcopy(interp, ip, MAXPATHLEN);
595 		epp->ep_interp = ip;
596 		epp->ep_interp_pos = pos;
597 
598 		ap->arg_phaddr = phdr;
599 		ap->arg_phentsize = eh->e_phentsize;
600 		ap->arg_phnum = eh->e_phnum;
601 		ap->arg_entry = eh->e_entry;
602 
603 		epp->ep_emul_arg = ap;
604 		epp->ep_entry = eh->e_entry; /* keep check_exec() happy */
605 	}
606 	else {
607 		epp->ep_interp = NULL;
608 		epp->ep_entry = eh->e_entry;
609 	}
610 
611 #ifdef ELF_MAP_PAGE_ZERO
612 	/* Dell SVR4 maps page zero, yeuch! */
613 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, NBPG, 0, epp->ep_vp, 0,
614 	    VM_PROT_READ);
615 #endif
616 
617 	free((char *) ph, M_TEMP);
618 	epp->ep_vp->v_flag |= VTEXT;
619 	return exec_aout_setup_stack(p, epp);
620 
621 bad:
622 	free((char *) ph, M_TEMP);
623 	kill_vmcmds(&epp->ep_vmcmds);
624 	return ENOEXEC;
625 }
626 
627 /*
628  * Phase II of load. It is now safe to load the interpreter. Info collected
629  * when loading the program is available for setup of the interpreter.
630  */
631 int
632 exec_elf_fixup(p, epp)
633 	struct proc *p;
634 	struct exec_package *epp;
635 {
636 	char	*interp;
637 	int	error, i;
638 	struct	elf_args *ap;
639 	AuxInfo ai[ELF_AUX_ENTRIES], *a;
640 	u_long	pos = epp->ep_interp_pos;
641 
642 	if(epp->ep_interp == 0) {
643 		return 0;
644 	}
645 
646 	interp = (char *)epp->ep_interp;
647 	ap = (struct elf_args *) epp->ep_emul_arg;
648 
649 	if ((error = elf_load_file(p, interp, epp, ap, &pos)) != 0) {
650 		free((char *) ap, M_TEMP);
651 		free((char *) interp, M_TEMP);
652 		kill_vmcmds(&epp->ep_vmcmds);
653 		return error;
654 	}
655 	/*
656 	 * We have to do this ourselfs...
657 	 */
658 	for (i = 0; i < epp->ep_vmcmds.evs_used && !error; i++) {
659 		struct exec_vmcmd *vcp;
660 
661 		vcp = &epp->ep_vmcmds.evs_cmds[i];
662 		error = (*vcp->ev_proc)(p, vcp);
663 	}
664 	kill_vmcmds(&epp->ep_vmcmds);
665 
666 	/*
667 	 * Push extra arguments on the stack needed by dynamically
668 	 * linked binaries
669 	 */
670 	if(error == 0) {
671 		a = ai;
672 
673 		a->au_id = AUX_phdr;
674 		a->au_v = ap->arg_phaddr;
675 		a++;
676 
677 		a->au_id = AUX_phent;
678 		a->au_v = ap->arg_phentsize;
679 		a++;
680 
681 		a->au_id = AUX_phnum;
682 		a->au_v = ap->arg_phnum;
683 		a++;
684 
685 		a->au_id = AUX_pagesz;
686 		a->au_v = NBPG;
687 		a++;
688 
689 		a->au_id = AUX_base;
690 		a->au_v = ap->arg_interp;
691 		a++;
692 
693 		a->au_id = AUX_flags;
694 		a->au_v = 0;
695 		a++;
696 
697 		a->au_id = AUX_entry;
698 		a->au_v = ap->arg_entry;
699 		a++;
700 
701 		a->au_id = AUX_null;
702 		a->au_v = 0;
703 		a++;
704 
705 		error = copyout(ai, epp->ep_emul_argp, sizeof ai);
706 	}
707 	free((char *) ap, M_TEMP);
708 	free((char *) interp, M_TEMP);
709 	return error;
710 }
711 #endif /* NATIVE_EXEC_ELF || EXEC_ELF */
712