imgact_elf.c revision 39154
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.29 1998/07/29 18:39:35 dfr Exp $
30 */
31
32#include "opt_rlimit.h"
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/exec.h>
37#include <sys/mman.h>
38#include <sys/imgact.h>
39#include <sys/imgact_elf.h>
40#include <sys/kernel.h>
41#include <sys/sysent.h>
42#include <sys/malloc.h>
43#include <sys/namei.h>
44#include <sys/proc.h>
45#include <sys/syscall.h>
46#include <sys/signalvar.h>
47#include <sys/sysctl.h>
48#include <sys/vnode.h>
49
50#include <vm/vm.h>
51#include <vm/vm_kern.h>
52#include <vm/vm_param.h>
53#include <vm/pmap.h>
54#include <sys/lock.h>
55#include <vm/vm_map.h>
56#include <vm/vm_prot.h>
57#include <vm/vm_extern.h>
58
59#include <machine/md_var.h>
60
61#define MAX_PHDR	32	/* XXX enough ? */
62
63#if ELF_TARG_CLASS == ELFCLASS32
64
65#define Elf_Ehdr	Elf32_Ehdr
66#define Elf_Phdr	Elf32_Phdr
67#define Elf_Auxargs	Elf32_Auxargs
68#define Elf_Brandinfo	Elf32_Brandinfo
69
70#else
71
72#define Elf_Ehdr	Elf64_Ehdr
73#define Elf_Phdr	Elf64_Phdr
74#define Elf_Auxargs	Elf64_Auxargs
75#define Elf_Brandinfo	Elf64_Brandinfo
76
77#endif
78
79
80static int elf_check_header __P((const Elf_Ehdr *hdr, int type));
81static 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));
82static int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry));
83static int elf_freebsd_fixup __P((long **stack_base, struct image_params *imgp));
84static int exec_elf_imgact __P((struct image_params *imgp));
85
86static int elf_trace = 0;
87SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
88#define UPRINTF if (elf_trace) uprintf
89
90static struct sysentvec elf_freebsd_sysvec = {
91        SYS_MAXSYSCALL,
92        sysent,
93        0,
94        0,
95        0,
96        0,
97        0,
98        0,
99        elf_freebsd_fixup,
100        sendsig,
101        sigcode,
102        &szsigcode,
103        0,
104	"FreeBSD ELF",
105	elf_coredump
106};
107
108static Elf_Brandinfo freebsd_brand_info = {
109						"FreeBSD",
110						"",
111						"/usr/libexec/ld-elf.so.1",
112						&elf_freebsd_sysvec
113					  };
114static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = {
115							&freebsd_brand_info,
116							NULL, NULL, NULL,
117							NULL, NULL, NULL, NULL
118						    };
119
120int
121elf_insert_brand_entry(Elf_Brandinfo *entry)
122{
123	int i;
124
125	for (i=1; i<MAX_BRANDS; i++) {
126		if (elf_brand_list[i] == NULL) {
127			elf_brand_list[i] = entry;
128			break;
129		}
130	}
131	if (i == MAX_BRANDS)
132		return -1;
133	return 0;
134}
135
136int
137elf_remove_brand_entry(Elf_Brandinfo *entry)
138{
139	int i;
140
141	for (i=1; i<MAX_BRANDS; i++) {
142		if (elf_brand_list[i] == entry) {
143			elf_brand_list[i] = NULL;
144			break;
145		}
146	}
147	if (i == MAX_BRANDS)
148		return -1;
149	return 0;
150}
151
152static int
153elf_check_header(const Elf_Ehdr *hdr, int type)
154{
155	if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 &&
156	      hdr->e_ident[EI_MAG1] == ELFMAG1 &&
157	      hdr->e_ident[EI_MAG2] == ELFMAG2 &&
158	      hdr->e_ident[EI_MAG3] == ELFMAG3))
159		return ENOEXEC;
160
161#ifdef __i386__
162	if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486)
163#endif
164#ifdef __alpha__
165	if (hdr->e_machine != EM_ALPHA)
166#endif
167		return ENOEXEC;
168
169
170	if (hdr->e_type != type)
171		return ENOEXEC;
172
173	return 0;
174}
175
176static int
177elf_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)
178{
179	size_t map_len;
180	vm_offset_t map_addr;
181	int error;
182	unsigned char *data_buf = 0;
183	size_t copy_len;
184
185	map_addr = trunc_page(vmaddr);
186
187	if (memsz > filsz)
188		map_len = trunc_page(offset+filsz) - trunc_page(offset);
189	else
190		map_len = round_page(offset+filsz) - trunc_page(offset);
191
192	if (error = vm_mmap (&vmspace->vm_map,
193			     &map_addr,
194			     map_len,
195			     prot,
196			     VM_PROT_ALL,
197			     MAP_PRIVATE | MAP_FIXED,
198			     (caddr_t)vp,
199			     trunc_page(offset)))
200		return error;
201
202	if (memsz == filsz)
203		return 0;
204
205	/*
206	 * We have to map the remaining bit of the file into the kernel's
207	 * memory map, allocate some anonymous memory, and copy that last
208	 * bit into it. The remaining space should be .bss...
209	 */
210	copy_len = (offset + filsz) - trunc_page(offset + filsz);
211	map_addr = trunc_page(vmaddr + filsz);
212	map_len = round_page(vmaddr + memsz) - map_addr;
213
214        if (map_len != 0) {
215		if (error = vm_map_find(&vmspace->vm_map, NULL, 0,
216					&map_addr, map_len, FALSE,
217					VM_PROT_ALL, VM_PROT_ALL,0))
218			return error;
219	}
220
221	if (error = vm_mmap(exec_map,
222			    (vm_offset_t *)&data_buf,
223			    PAGE_SIZE,
224			    VM_PROT_READ,
225			    VM_PROT_READ,
226			    0,
227			    (caddr_t)vp,
228			    trunc_page(offset + filsz)))
229		return error;
230
231	error = copyout(data_buf, (caddr_t)map_addr, copy_len);
232
233        vm_map_remove(exec_map, (vm_offset_t)data_buf,
234		      (vm_offset_t)data_buf + PAGE_SIZE);
235
236	/*
237	 * set it to the specified protection
238	 */
239	vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len,  prot,
240		       FALSE);
241
242	UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len);
243	return error;
244}
245
246static int
247elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
248{
249	Elf_Ehdr *hdr = NULL;
250	Elf_Phdr *phdr = NULL;
251	struct nameidata nd;
252	struct vmspace *vmspace = p->p_vmspace;
253	struct vattr attr;
254	struct image_params image_params, *imgp;
255	vm_prot_t prot = 0;
256	unsigned long text_size = 0, data_size = 0;
257	unsigned long text_addr = 0, data_addr = 0;
258	int header_size = 0;
259        int error, i;
260
261	imgp = &image_params;
262	/*
263	 * Initialize part of the common data
264	 */
265	imgp->proc = p;
266	imgp->uap = NULL;
267	imgp->attr = &attr;
268	imgp->firstpage = NULL;
269	imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE);
270
271	if (imgp->image_header == NULL) {
272		nd.ni_vp = NULL;
273		error = ENOMEM;
274		goto fail;
275	}
276
277        NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
278
279	if (error = namei(&nd)) {
280		nd.ni_vp = NULL;
281		goto fail;
282	}
283
284	imgp->vp = nd.ni_vp;
285
286	/*
287	 * Check permissions, modes, uid, etc on the file, and "open" it.
288	 */
289	error = exec_check_permissions(imgp);
290	if (error) {
291		VOP_UNLOCK(nd.ni_vp, 0, p);
292		goto fail;
293	}
294
295	error = exec_map_first_page(imgp);
296	VOP_UNLOCK(nd.ni_vp, 0, p);
297	if (error)
298                goto fail;
299
300	hdr = (Elf_Ehdr *)imgp->image_header;
301	if (error = elf_check_header(hdr, ET_DYN))
302		goto fail;
303
304	/*
305	 * ouch, need to bounds check in case user gives us a corrupted
306	 * file with an insane header size
307	 */
308	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
309		error = ENOEXEC;
310		goto fail;
311	}
312
313	header_size = hdr->e_phentsize * hdr->e_phnum;
314
315	/* Only support headers that fit within first page for now */
316	if (header_size + hdr->e_phoff > PAGE_SIZE) {
317		error = ENOEXEC;
318		goto fail;
319	}
320
321	phdr = (Elf_Phdr *)(imgp->image_header + hdr->e_phoff);
322
323	for (i = 0; i < hdr->e_phnum; i++) {
324		switch(phdr[i].p_type) {
325
326	   	case PT_NULL:	/* NULL section */
327	    		UPRINTF ("ELF(file) PT_NULL section\n");
328			break;
329		case PT_LOAD:	/* Loadable segment */
330		{
331	    		UPRINTF ("ELF(file) PT_LOAD section ");
332			if (phdr[i].p_flags & PF_X)
333  				prot |= VM_PROT_EXECUTE;
334			if (phdr[i].p_flags & PF_W)
335  				prot |= VM_PROT_WRITE;
336			if (phdr[i].p_flags & PF_R)
337  				prot |= VM_PROT_READ;
338
339			if (error = elf_load_section(vmspace, nd.ni_vp,
340  						     phdr[i].p_offset,
341  						     (caddr_t)phdr[i].p_vaddr +
342							(*addr),
343  						     phdr[i].p_memsz,
344  						     phdr[i].p_filesz, prot))
345				goto fail;
346
347			/*
348			 * Is this .text or .data ??
349			 *
350			 * We only handle one each of those yet XXX
351			 */
352			if (hdr->e_entry >= phdr[i].p_vaddr &&
353			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
354  				text_addr = trunc_page(phdr[i].p_vaddr+(*addr));
355  				text_size = round_page(phdr[i].p_memsz +
356						       phdr[i].p_vaddr -
357						       trunc_page(phdr[i].p_vaddr));
358				*entry=(unsigned long)hdr->e_entry+(*addr);
359	    			UPRINTF(".text <%08lx,%08lx> entry=%08lx\n",
360					text_addr, text_size, *entry);
361			} else {
362  				data_addr = trunc_page(phdr[i].p_vaddr+(*addr));
363  				data_size = round_page(phdr[i].p_memsz +
364						       phdr[i].p_vaddr -
365						       trunc_page(phdr[i].p_vaddr));
366	    			UPRINTF(".data <%08lx,%08lx>\n",
367					data_addr, data_size);
368			}
369		}
370		break;
371
372	   	case PT_DYNAMIC:/* Dynamic link information */
373	    		UPRINTF ("ELF(file) PT_DYNAMIC section\n");
374			break;
375	  	case PT_INTERP:	/* Path to interpreter */
376	    		UPRINTF ("ELF(file) PT_INTERP section\n");
377			break;
378	  	case PT_NOTE:	/* Note section */
379	    		UPRINTF ("ELF(file) PT_NOTE section\n");
380			break;
381	  	case PT_SHLIB:	/* Shared lib section  */
382	    		UPRINTF ("ELF(file) PT_SHLIB section\n");
383			break;
384		case PT_PHDR: 	/* Program header table info */
385	    		UPRINTF ("ELF(file) PT_PHDR section\n");
386			break;
387		default:
388	    		UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type );
389		}
390	}
391
392fail:
393	if (imgp->firstpage)
394		exec_unmap_first_page(imgp);
395	if (imgp->image_header)
396		kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header,
397			PAGE_SIZE);
398	if (nd.ni_vp)
399		vrele(nd.ni_vp);
400
401	return error;
402}
403
404static int
405exec_elf_imgact(struct image_params *imgp)
406{
407	const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header;
408	const Elf_Phdr *phdr, *mapped_phdr = NULL;
409	Elf_Auxargs *elf_auxargs = NULL;
410	struct vmspace *vmspace;
411	vm_prot_t prot = 0;
412	u_long text_size = 0, data_size = 0;
413	u_long text_addr = 0, data_addr = 0;
414	u_long addr, entry = 0, proghdr = 0;
415	int error, i, header_size = 0;
416	const char *interp = NULL;
417	char *brand = NULL;
418	char path[MAXPATHLEN];
419
420	/*
421	 * Do we have a valid ELF header ?
422	 */
423	if (elf_check_header(hdr, ET_EXEC))
424		return -1;
425
426	/*
427	 * From here on down, we return an errno, not -1, as we've
428	 * detected an ELF file.
429	 */
430
431	/*
432	 * ouch, need to bounds check in case user gives us a corrupted
433	 * file with an insane header size
434	 */
435	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
436		return ENOEXEC;
437	}
438
439	header_size = hdr->e_phentsize * hdr->e_phnum;
440
441	if ((hdr->e_phoff > PAGE_SIZE) ||
442	    (hdr->e_phoff + header_size) > PAGE_SIZE) {
443		/* Only support headers in first page for now */
444		return ENOEXEC;
445	} else {
446		phdr = (const Elf_Phdr*)
447		       ((const char *)imgp->image_header + hdr->e_phoff);
448	}
449
450	/*
451	 * From this point on, we may have resources that need to be freed.
452	 */
453	if (error = exec_extract_strings(imgp))
454		goto fail;
455
456	exec_new_vmspace(imgp);
457
458	vmspace = imgp->proc->p_vmspace;
459
460	for (i = 0; i < hdr->e_phnum; i++) {
461		switch(phdr[i].p_type) {
462
463	   	case PT_NULL:	/* NULL section */
464	    		UPRINTF ("ELF PT_NULL section\n");
465			break;
466		case PT_LOAD:	/* Loadable segment */
467		{
468	    		UPRINTF ("ELF PT_LOAD section ");
469			if (phdr[i].p_flags & PF_X)
470  				prot |= VM_PROT_EXECUTE;
471			if (phdr[i].p_flags & PF_W)
472  				prot |= VM_PROT_WRITE;
473			if (phdr[i].p_flags & PF_R)
474  				prot |= VM_PROT_READ;
475
476			if (error = elf_load_section(vmspace, imgp->vp,
477  						     phdr[i].p_offset,
478  						     (caddr_t)phdr[i].p_vaddr,
479  						     phdr[i].p_memsz,
480  						     phdr[i].p_filesz, prot))
481  				goto fail;
482
483			/*
484			 * Is this .text or .data ??
485			 *
486			 * We only handle one each of those yet XXX
487			 */
488			if (hdr->e_entry >= phdr[i].p_vaddr &&
489			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
490  				text_addr = trunc_page(phdr[i].p_vaddr);
491  				text_size = round_page(phdr[i].p_memsz +
492						       phdr[i].p_vaddr -
493						       text_addr);
494				entry = (u_long)hdr->e_entry;
495	    			UPRINTF(".text <%08lx,%08lx> entry=%08lx\n",
496					text_addr, text_size, entry);
497			} else {
498  				data_addr = trunc_page(phdr[i].p_vaddr);
499  				data_size = round_page(phdr[i].p_memsz +
500						       phdr[i].p_vaddr -
501						       data_addr);
502	    			UPRINTF(".data <%08lx,%08lx>\n",
503					data_addr, data_size);
504			}
505		}
506		break;
507
508	   	case PT_DYNAMIC:/* Dynamic link information */
509	    		UPRINTF ("ELF PT_DYNAMIC section ??\n");
510			break;
511	  	case PT_INTERP:	/* Path to interpreter */
512	    		UPRINTF ("ELF PT_INTERP section ");
513			if (phdr[i].p_filesz > MAXPATHLEN ||
514			    phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) {
515				error = ENOEXEC;
516				goto fail;
517			}
518			interp = imgp->image_header + phdr[i].p_offset;
519			UPRINTF("<%s>\n", interp);
520			break;
521	  	case PT_NOTE:	/* Note section */
522	    		UPRINTF ("ELF PT_NOTE section\n");
523			break;
524	  	case PT_SHLIB:	/* Shared lib section  */
525	    		UPRINTF ("ELF PT_SHLIB section\n");
526			break;
527		case PT_PHDR: 	/* Program header table info */
528	    		UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr);
529			proghdr = phdr[i].p_vaddr;
530			break;
531		default:
532	    		UPRINTF ("ELF %d section ??\n", phdr[i].p_type);
533		}
534	}
535
536	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
537	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
538	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
539	vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr;
540
541	addr = 2L*MAXDSIZ; /* May depend on OS type XXX */
542
543	imgp->entry_addr = entry;
544
545	/*
546	 * So which kind (brand) of ELF binary do we have at hand
547	 * FreeBSD, Linux, SVR4 or something else ??
548	 * If its has a interpreter section try that first
549	 */
550        if (interp) {
551                for (i=0; i<MAX_BRANDS; i++) {
552                        if (elf_brand_list[i] != NULL) {
553                                if (!strcmp(interp, elf_brand_list[i]->interp_path)) {
554                                        imgp->proc->p_sysent =
555                                                elf_brand_list[i]->sysvec;
556                                        strcpy(path, elf_brand_list[i]->emul_path);
557                                        strcat(path, elf_brand_list[i]->interp_path);
558                                        UPRINTF("interpreter=<%s> %s\n",
559                                                elf_brand_list[i]->interp_path,
560                                                elf_brand_list[i]->emul_path);
561                                        break;
562                                }
563                        }
564                }
565        }
566
567	/*
568	 * If there is no interpreter, or recognition of it
569	 * failed, se if the binary is branded.
570	 */
571	if (!interp || i == MAX_BRANDS) {
572		brand = (char *)&(hdr->e_ident[EI_BRAND]);
573		for (i=0; i<MAX_BRANDS; i++) {
574			if (elf_brand_list[i] != NULL) {
575				if (!strcmp(brand, elf_brand_list[i]->brand)) {
576					imgp->proc->p_sysent = elf_brand_list[i]->sysvec;
577					if (interp) {
578						strcpy(path, elf_brand_list[i]->emul_path);
579						strcat(path, elf_brand_list[i]->interp_path);
580						UPRINTF("interpreter=<%s> %s\n",
581						elf_brand_list[i]->interp_path,
582						elf_brand_list[i]->emul_path);
583					}
584					break;
585				}
586			}
587		}
588	}
589	if (i == MAX_BRANDS) {
590#ifndef __alpha__
591		uprintf("ELF binary type not known\n");
592		error = ENOEXEC;
593		goto fail;
594#else
595		i = 0;		/* assume freebsd */
596		imgp->proc->p_sysent = elf_brand_list[i]->sysvec;
597		if (interp) {
598			strcpy(path, elf_brand_list[i]->emul_path);
599			strcat(path, elf_brand_list[i]->interp_path);
600			UPRINTF("interpreter=<%s> %s\n",
601				elf_brand_list[i]->interp_path,
602				elf_brand_list[i]->emul_path);
603		}
604#endif
605	}
606	if (interp) {
607                if (error = elf_load_file(imgp->proc,
608                                          path,
609                                          &addr,        /* XXX */
610                                          &imgp->entry_addr)) {
611                        uprintf("ELF interpreter %s not found\n", path);
612                        goto fail;
613                }
614	}
615
616	UPRINTF("Executing %s binary\n", elf_brand_list[i]->brand);
617
618	/*
619	 * Construct auxargs table (used by the fixup routine)
620	 */
621	elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK);
622	elf_auxargs->execfd = -1;
623	elf_auxargs->phdr = proghdr;
624	elf_auxargs->phent = hdr->e_phentsize;
625	elf_auxargs->phnum = hdr->e_phnum;
626	elf_auxargs->pagesz = PAGE_SIZE;
627	elf_auxargs->base = addr;
628	elf_auxargs->flags = 0;
629	elf_auxargs->entry = entry;
630	elf_auxargs->trace = elf_trace;
631
632	imgp->auxargs = elf_auxargs;
633	imgp->interpreted = 0;
634
635	/* don't allow modifying the file while we run it */
636	imgp->vp->v_flag |= VTEXT;
637
638fail:
639	return error;
640}
641
642int
643elf_coredump (p)
644	register struct proc *p;
645{
646	/* Not implemented yet. */
647	return EFAULT;
648}
649
650static int
651elf_freebsd_fixup(long **stack_base, struct image_params *imgp)
652{
653	Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
654	long *pos;
655
656	pos = *stack_base + (imgp->argc + imgp->envc + 2);
657
658	if (args->trace) {
659		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
660	}
661	if (args->execfd != -1) {
662		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
663	}
664	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
665	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
666	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
667	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
668	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
669	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
670	AUXARGS_ENTRY(pos, AT_BASE, args->base);
671	AUXARGS_ENTRY(pos, AT_NULL, 0);
672
673	free(imgp->auxargs, M_TEMP);
674	imgp->auxargs = NULL;
675
676	(*stack_base)--;
677	**stack_base = (long)imgp->argc;
678	return 0;
679}
680
681/*
682 * Tell kern_execve.c about it, with a little help from the linker.
683 * Since `const' objects end up in the text segment, TEXT_SET is the
684 * correct directive to use.
685 */
686static const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
687TEXT_SET(execsw_set, elf_execsw);
688
689