imgact_elf.c revision 17974
1/*-
2 * Copyright (c) 1995-1996 S�ren Schmidt
3 * Copyright (c) 1996 Peter Wemm
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer
11 *    in this position and unchanged.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software withough specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 *	$Id: imgact_elf.c,v 1.7 1996/06/18 05:15:46 dyson Exp $
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/resourcevar.h>
35#include <sys/exec.h>
36#include <sys/mman.h>
37#include <sys/imgact.h>
38#include <sys/imgact_elf.h>
39#include <sys/kernel.h>
40#include <sys/sysent.h>
41#include <sys/file.h>
42#include <sys/malloc.h>
43#include <sys/mount.h>
44#include <sys/namei.h>
45#include <sys/proc.h>
46#include <sys/sysproto.h>
47#include <sys/syscall.h>
48#include <sys/signalvar.h>
49#include <sys/sysctl.h>
50#include <sys/vnode.h>
51
52#include <vm/vm.h>
53#include <vm/vm_kern.h>
54#include <vm/vm_param.h>
55#include <vm/pmap.h>
56#include <vm/lock.h>
57#include <vm/vm_map.h>
58#include <vm/vm_prot.h>
59#include <vm/vm_extern.h>
60
61#include <machine/md_var.h>
62#include <i386/linux/linux_syscall.h>
63#include <i386/linux/linux.h>
64
65#define MAX_PHDR	32	/* XXX enough ? */
66
67static int map_pages __P((struct vnode *vp, vm_offset_t offset, vm_offset_t *buf, vm_size_t size));
68static void unmap_pages __P((struct vnode *vp, vm_offset_t buf, vm_size_t size));
69static int elf_check_permissions __P((struct proc *p, struct vnode *vp));
70static int elf_check_header __P((const Elf32_Ehdr *hdr, int type));
71static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot));
72static int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry));
73static int elf_freebsd_fixup __P((int **stack_base, struct image_params *imgp));
74int exec_elf_imgact __P((struct image_params *imgp));
75
76int elf_trace = 0;
77SYSCTL_INT(_debug, 1, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
78#define UPRINTF if (elf_trace) uprintf
79
80static struct sysentvec elf_freebsd_sysvec = {
81        SYS_MAXSYSCALL,
82        sysent,
83        0,
84        0,
85        0,
86        0,
87        0,
88        elf_freebsd_fixup,
89        sendsig,
90        sigcode,
91        &szsigcode,
92        0,
93	"FreeBSD ELF"
94};
95
96static Elf32_Interp_info freebsd_interp = {
97						&elf_freebsd_sysvec,
98						"/usr/libexec/ld-elf.so.1",
99						""
100					  };
101static Elf32_Interp_info *interp_list[MAX_INTERP] = {
102							&freebsd_interp,
103							NULL, NULL, NULL,
104							NULL, NULL, NULL, NULL
105						    };
106
107int
108elf_insert_interp(Elf32_Interp_info *entry)
109{
110	int i;
111
112	for (i=1; i<MAX_INTERP; i++) {
113		if (interp_list[i] == NULL) {
114			interp_list[i] = entry;
115			break;
116		}
117	}
118	if (i == MAX_INTERP)
119		return -1;
120	return 0;
121}
122
123int
124elf_remove_interp(Elf32_Interp_info *entry)
125{
126	int i;
127
128	for (i=1; i<MAX_INTERP; i++) {
129		if (interp_list[i] == entry) {
130			interp_list[i] = NULL;
131			break;
132		}
133	}
134	if (i == MAX_INTERP)
135		return -1;
136	return 0;
137}
138
139static int
140map_pages(struct vnode *vp, vm_offset_t offset,
141	     vm_offset_t *buf, vm_size_t size)
142{
143	int error;
144	vm_offset_t kern_buf;
145	vm_size_t pageoff;
146
147	/*
148	 * The request may not be aligned, and may even cross several
149	 * page boundaries in the file...
150	 */
151	pageoff = (offset & PAGE_MASK);
152	offset -= pageoff;		/* start of first aligned page to map */
153	size += pageoff;
154	size = round_page(size);	/* size of aligned pages to map */
155
156	if (error = vm_mmap(kernel_map,
157			    &kern_buf,
158			    size,
159			    VM_PROT_READ,
160			    VM_PROT_READ,
161			    0,
162			    (caddr_t)vp,
163			    offset))
164		return error;
165
166	*buf = kern_buf + pageoff;
167
168	return 0;
169}
170
171static void
172unmap_pages(struct vnode *vp, vm_offset_t buf, vm_size_t size)
173{
174	vm_size_t pageoff;
175
176	pageoff = (buf & PAGE_MASK);
177	buf -= pageoff;		/* start of first aligned page to map */
178	size += pageoff;
179	size = round_page(size);/* size of aligned pages to map */
180
181      	vm_map_remove(kernel_map, buf, buf + size);
182}
183
184static int
185elf_check_permissions(struct proc *p, struct vnode *vp)
186{
187	struct vattr attr;
188	int error;
189
190	/*
191	 * Check number of open-for-writes on the file and deny execution
192	 *	if there are any.
193	 */
194	if (vp->v_writecount) {
195		return (ETXTBSY);
196	}
197
198	/* Get file attributes */
199	error = VOP_GETATTR(vp, &attr, p->p_ucred, p);
200	if (error)
201		return (error);
202
203	/*
204	 * 1) Check if file execution is disabled for the filesystem that this
205	 *	file resides on.
206	 * 2) Insure that at least one execute bit is on - otherwise root
207	 *	will always succeed, and we don't want to happen unless the
208	 *	file really is executable.
209	 * 3) Insure that the file is a regular file.
210	 */
211	if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
212	    ((attr.va_mode & 0111) == 0) ||
213	    (attr.va_type != VREG)) {
214		return (EACCES);
215	}
216
217	/*
218	 * Zero length files can't be exec'd
219	 */
220	if (attr.va_size == 0)
221		return (ENOEXEC);
222
223	/*
224	 *  Check for execute permission to file based on current credentials.
225	 *	Then call filesystem specific open routine (which does nothing
226	 *	in the general case).
227	 */
228	error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
229	if (error)
230		return (error);
231
232	error = VOP_OPEN(vp, FREAD, p->p_ucred, p);
233	if (error)
234		return (error);
235
236	return (0);
237}
238
239static int
240elf_check_header(const Elf32_Ehdr *hdr, int type)
241{
242	if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 &&
243	      hdr->e_ident[EI_MAG1] == ELFMAG1 &&
244	      hdr->e_ident[EI_MAG2] == ELFMAG2 &&
245	      hdr->e_ident[EI_MAG3] == ELFMAG3))
246		return ENOEXEC;
247
248	if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486)
249		return ENOEXEC;
250
251	if (hdr->e_type != type)
252		return ENOEXEC;
253
254	return 0;
255}
256
257static int
258elf_load_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
259{
260	size_t map_len;
261	vm_offset_t map_addr;
262	int error;
263	unsigned char *data_buf = 0;
264	size_t copy_len;
265
266	map_addr = trunc_page(vmaddr);
267
268	if (memsz > filsz)
269		map_len = trunc_page(offset+filsz) - trunc_page(offset);
270	else
271		map_len = round_page(offset+filsz) - trunc_page(offset);
272
273	if (error = vm_mmap (&vmspace->vm_map,
274			     &map_addr,
275			     map_len,
276			     prot,
277			     VM_PROT_ALL,
278			     MAP_PRIVATE | MAP_FIXED,
279			     (caddr_t)vp,
280			     trunc_page(offset)))
281		return error;
282
283	if (memsz == filsz)
284		return 0;
285
286	/*
287	 * We have to map the remaining bit of the file into the kernel's
288	 * memory map, allocate some anonymous memory, and copy that last
289	 * bit into it. The remaining space should be .bss...
290	 */
291	copy_len = (offset + filsz) - trunc_page(offset + filsz);
292	map_addr = trunc_page(vmaddr + filsz);
293	map_len = round_page(vmaddr + memsz) - map_addr;
294
295        if (map_len != 0) {
296		if (error = vm_map_find(&vmspace->vm_map, NULL, 0,
297					&map_addr, map_len, FALSE,
298					VM_PROT_ALL, VM_PROT_ALL,0))
299			return error;
300	}
301
302	if (error = vm_mmap(kernel_map,
303			    (vm_offset_t *)&data_buf,
304			    PAGE_SIZE,
305			    VM_PROT_READ,
306			    VM_PROT_READ,
307			    0,
308			    (caddr_t)vp,
309			    trunc_page(offset + filsz)))
310		return error;
311
312	error = copyout(data_buf, (caddr_t)map_addr, copy_len);
313
314        vm_map_remove(kernel_map, (vm_offset_t)data_buf,
315		      (vm_offset_t)data_buf + PAGE_SIZE);
316
317	/*
318	 * set it to the specified protection
319	 */
320	vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len,  prot,
321		       FALSE);
322
323	UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len);
324	return error;
325}
326
327static int
328elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
329{
330	Elf32_Ehdr *hdr = NULL;
331	Elf32_Phdr *phdr = NULL;
332	struct nameidata nd;
333	struct vmspace *vmspace = p->p_vmspace;
334	vm_prot_t prot = 0;
335	unsigned long text_size = 0, data_size = 0;
336	unsigned long text_addr = 0, data_addr = 0;
337	int header_size = 0;
338        int error, i;
339
340        NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
341
342	if (error = namei(&nd))
343                goto fail;
344
345	if (nd.ni_vp == NULL) {
346		error = ENOEXEC;
347		goto fail;
348	}
349
350	/*
351	 * Check permissions, modes, uid, etc on the file, and "open" it.
352	 */
353	error = elf_check_permissions(p, nd.ni_vp);
354
355	/*
356	 * No longer need this, and it prevents demand paging.
357	 */
358	VOP_UNLOCK(nd.ni_vp);
359
360	if (error)
361                goto fail;
362
363	/*
364	 * Map in the header
365	 */
366	if (error = map_pages(nd.ni_vp, 0, (vm_offset_t *)&hdr, sizeof(hdr)))
367                goto fail;
368
369	/*
370	 * Do we have a valid ELF header ?
371	 */
372	if (error = elf_check_header(hdr, ET_DYN))
373		goto fail;
374
375	/*
376	 * ouch, need to bounds check in case user gives us a corrupted
377	 * file with an insane header size
378	 */
379	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
380		error = ENOEXEC;
381		goto fail;
382	}
383
384	header_size = hdr->e_phentsize * hdr->e_phnum;
385
386	if (error = map_pages(nd.ni_vp, hdr->e_phoff, (vm_offset_t *)&phdr,
387			         header_size))
388        	goto fail;
389
390	for (i = 0; i < hdr->e_phnum; i++) {
391		switch(phdr[i].p_type) {
392
393	   	case PT_NULL:	/* NULL section */
394	    		UPRINTF ("ELF(file) PT_NULL section\n");
395			break;
396		case PT_LOAD:	/* Loadable segment */
397		{
398	    		UPRINTF ("ELF(file) PT_LOAD section ");
399			if (phdr[i].p_flags & PF_X)
400  				prot |= VM_PROT_EXECUTE;
401			if (phdr[i].p_flags & PF_W)
402  				prot |= VM_PROT_WRITE;
403			if (phdr[i].p_flags & PF_R)
404  				prot |= VM_PROT_READ;
405
406			if (error = elf_load_section(vmspace, nd.ni_vp,
407  						     phdr[i].p_offset,
408  						     (caddr_t)phdr[i].p_vaddr +
409							(*addr),
410  						     phdr[i].p_memsz,
411  						     phdr[i].p_filesz, prot))
412				goto fail;
413
414			/*
415			 * Is this .text or .data ??
416			 *
417			 * We only handle one each of those yet XXX
418			 */
419			if (hdr->e_entry >= phdr[i].p_vaddr &&
420			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
421  				text_addr = trunc_page(phdr[i].p_vaddr+(*addr));
422  				text_size = round_page(phdr[i].p_memsz +
423						       phdr[i].p_vaddr -
424						       trunc_page(phdr[i].p_vaddr));
425				*entry=(unsigned long)hdr->e_entry+(*addr);
426	    			UPRINTF(".text <%08x,%08x> entry=%08x\n",
427					text_addr, text_size, *entry);
428			} else {
429  				data_addr = trunc_page(phdr[i].p_vaddr+(*addr));
430  				data_size = round_page(phdr[i].p_memsz +
431						       phdr[i].p_vaddr -
432						       trunc_page(phdr[i].p_vaddr));
433	    			UPRINTF(".data <%08x,%08x>\n",
434					data_addr, data_size);
435			}
436		}
437		break;
438
439	   	case PT_DYNAMIC:/* Dynamic link information */
440	    		UPRINTF ("ELF(file) PT_DYNAMIC section\n");
441			break;
442	  	case PT_INTERP:	/* Path to interpreter */
443	    		UPRINTF ("ELF(file) PT_INTERP section\n");
444			break;
445	  	case PT_NOTE:	/* Note section */
446	    		UPRINTF ("ELF(file) PT_NOTE section\n");
447			break;
448	  	case PT_SHLIB:	/* Shared lib section  */
449	    		UPRINTF ("ELF(file) PT_SHLIB section\n");
450			break;
451		case PT_PHDR: 	/* Program header table info */
452	    		UPRINTF ("ELF(file) PT_PHDR section\n");
453			break;
454		default:
455	    		UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type );
456		}
457	}
458
459fail:
460	if (phdr)
461		unmap_pages(nd.ni_vp, (vm_offset_t)phdr, header_size);
462	if (hdr)
463		unmap_pages(nd.ni_vp, (vm_offset_t)hdr, sizeof(hdr));
464
465	return error;
466}
467
468int
469exec_elf_imgact(struct image_params *imgp)
470{
471	const Elf32_Ehdr *hdr = (const Elf32_Ehdr *) imgp->image_header;
472	const Elf32_Phdr *phdr, *mapped_phdr = NULL;
473	Elf32_Auxargs *elf_auxargs = NULL;
474	struct vmspace *vmspace = imgp->proc->p_vmspace;
475	vm_prot_t prot = 0;
476	u_long text_size = 0, data_size = 0;
477	u_long text_addr = 0, data_addr = 0;
478	u_long addr, entry = 0, proghdr = 0;
479	int error, i, header_size = 0, interp_len = 0;
480	char *interp = NULL;
481
482	/*
483	 * Do we have a valid ELF header ?
484	 */
485	if (elf_check_header(hdr, ET_EXEC))
486		return -1;
487
488	/*
489	 * From here on down, we return an errno, not -1, as we've
490	 * detected an ELF file.
491	 */
492
493	/*
494	 * ouch, need to bounds check in case user gives us a corrupted
495	 * file with an insane header size
496	 */
497	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
498		return ENOEXEC;
499	}
500
501	header_size = hdr->e_phentsize * hdr->e_phnum;
502
503	if ((hdr->e_phoff > PAGE_SIZE) ||
504	    (hdr->e_phoff + header_size) > PAGE_SIZE) {
505	  	/*
506		 * Ouch ! we only get one page full of header...
507		 * Try to map it in ourselves, and see how we go.
508	   	 */
509		if (error = map_pages(imgp->vp, hdr->e_phoff,
510				(vm_offset_t *)&mapped_phdr, header_size))
511			return (error);
512		/*
513		 * Save manual mapping for cleanup
514		 */
515		phdr = mapped_phdr;
516	} else {
517		phdr = (const Elf32_Phdr*)
518		       ((const char *)imgp->image_header + hdr->e_phoff);
519	}
520
521	/*
522	 * From this point on, we may have resources that need to be freed.
523	 */
524	if (error = exec_extract_strings(imgp))
525		goto fail;
526
527	exec_new_vmspace(imgp);
528
529	for (i = 0; i < hdr->e_phnum; i++) {
530		switch(phdr[i].p_type) {
531
532	   	case PT_NULL:	/* NULL section */
533	    		UPRINTF ("ELF PT_NULL section\n");
534			break;
535		case PT_LOAD:	/* Loadable segment */
536		{
537	    		UPRINTF ("ELF PT_LOAD section ");
538			if (phdr[i].p_flags & PF_X)
539  				prot |= VM_PROT_EXECUTE;
540			if (phdr[i].p_flags & PF_W)
541  				prot |= VM_PROT_WRITE;
542			if (phdr[i].p_flags & PF_R)
543  				prot |= VM_PROT_READ;
544
545			if (error = elf_load_section(vmspace, imgp->vp,
546  						     phdr[i].p_offset,
547  						     (caddr_t)phdr[i].p_vaddr,
548  						     phdr[i].p_memsz,
549  						     phdr[i].p_filesz, prot))
550  				goto fail;
551
552			/*
553			 * Is this .text or .data ??
554			 *
555			 * We only handle one each of those yet XXX
556			 */
557			if (hdr->e_entry >= phdr[i].p_vaddr &&
558			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
559  				text_addr = trunc_page(phdr[i].p_vaddr);
560  				text_size = round_page(phdr[i].p_memsz +
561						       phdr[i].p_vaddr -
562						       text_addr);
563				entry = (u_long)hdr->e_entry;
564	    			UPRINTF(".text <%08x,%08x> entry=%08x\n",
565					text_addr, text_size, entry);
566			} else {
567  				data_addr = trunc_page(phdr[i].p_vaddr);
568  				data_size = round_page(phdr[i].p_memsz +
569						       phdr[i].p_vaddr -
570						       data_addr);
571	    			UPRINTF(".data <%08x,%08x>\n",
572					data_addr, data_size);
573			}
574		}
575		break;
576
577	   	case PT_DYNAMIC:/* Dynamic link information */
578	    		UPRINTF ("ELF PT_DYNAMIC section ??\n");
579			break;
580	  	case PT_INTERP:	/* Path to interpreter */
581	    		UPRINTF ("ELF PT_INTERP section ");
582			if (phdr[i].p_filesz > MAXPATHLEN) {
583				error = ENOEXEC;
584				goto fail;
585			}
586			interp_len = MAXPATHLEN;
587			if (error = map_pages(imgp->vp, phdr[i].p_offset,
588					 (vm_offset_t *)&interp, interp_len))
589				goto fail;
590			UPRINTF("<%s>\n", interp);
591			break;
592	  	case PT_NOTE:	/* Note section */
593	    		UPRINTF ("ELF PT_NOTE section\n");
594			break;
595	  	case PT_SHLIB:	/* Shared lib section  */
596	    		UPRINTF ("ELF PT_SHLIB section\n");
597			break;
598		case PT_PHDR: 	/* Program header table info */
599	    		UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr);
600			proghdr = phdr[i].p_vaddr;
601			break;
602		default:
603	    		UPRINTF ("ELF %d section ??\n", phdr[i].p_type);
604		}
605	}
606
607	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
608	vmspace->vm_taddr = (caddr_t)text_addr;
609	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
610	vmspace->vm_daddr = (caddr_t)data_addr;
611
612	addr = 2*MAXDSIZ; /* May depend on OS type XXX */
613
614	if (interp) {
615		char path[MAXPATHLEN];
616		/*
617		 * So which kind of ELF binary do we have at hand
618		 * FreeBSD, SVR4 or Linux ??
619		 */
620		for (i=0; i<MAX_INTERP; i++) {
621			if (interp_list[i] != NULL) {
622				if (!strcmp(interp, interp_list[i]->path)) {
623					imgp->proc->p_sysent =
624						interp_list[i]->sysvec;
625					strcpy(path, interp_list[i]->emul_path);
626					strcat(path, interp_list[i]->path);
627					UPRINTF("interpreter=<%s> %s\n",
628						interp_list[i]->path,
629						interp_list[i]->emul_path);
630					break;
631				}
632			}
633		}
634		if (i == MAX_INTERP) {
635			uprintf("ELF interpreter %s not known\n", interp);
636			error = ENOEXEC;
637			goto fail;
638		}
639		if (error = elf_load_file(imgp->proc,
640					  path,
641				          &addr, 	/* XXX */
642				          &imgp->entry_addr)) {
643			uprintf("ELF interpreter %s not found\n", path);
644			goto fail;
645		}
646	}
647	else
648		imgp->entry_addr = entry;
649
650	/*
651	 * Construct auxargs table (used by the fixup routine)
652	 */
653	elf_auxargs = malloc(sizeof(Elf32_Auxargs), M_TEMP, M_WAITOK);
654	elf_auxargs->execfd = -1;
655	elf_auxargs->phdr = proghdr;
656	elf_auxargs->phent = hdr->e_phentsize;
657	elf_auxargs->phnum = hdr->e_phnum;
658	elf_auxargs->pagesz = PAGE_SIZE;
659	elf_auxargs->base = addr;
660	elf_auxargs->flags = 0;
661	elf_auxargs->entry = entry;
662	elf_auxargs->trace = elf_trace;
663
664	imgp->auxargs = elf_auxargs;
665	imgp->interpreted = 0;
666
667	/* don't allow modifying the file while we run it */
668	imgp->vp->v_flag |= VTEXT;
669
670fail:
671	if (mapped_phdr)
672		unmap_pages(imgp->vp, (vm_offset_t)mapped_phdr, header_size);
673	if (interp)
674		unmap_pages(imgp->vp, (vm_offset_t)interp, interp_len);
675
676	return error;
677}
678
679static int
680elf_freebsd_fixup(int **stack_base, struct image_params *imgp)
681{
682	Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
683	int *pos;
684
685	pos = *stack_base + (imgp->argc + imgp->envc + 2);
686
687	if (args->trace) {
688		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
689	}
690	if (args->execfd != -1) {
691		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
692	}
693	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
694	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
695	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
696	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
697	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
698	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
699	AUXARGS_ENTRY(pos, AT_BASE, args->base);
700	AUXARGS_ENTRY(pos, AT_NULL, 0);
701
702	free(imgp->auxargs, M_TEMP);
703	imgp->auxargs = NULL;
704
705	(*stack_base)--;
706	**stack_base = (int)imgp->argc;
707	return 0;
708}
709
710/*
711 * Tell kern_execve.c about it, with a little help from the linker.
712 * Since `const' objects end up in the text segment, TEXT_SET is the
713 * correct directive to use.
714 */
715const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
716TEXT_SET(execsw_set, elf_execsw);
717
718