imgact_elf.c revision 37957
11541Srgrimes/*-
21541Srgrimes * Copyright (c) 1995-1996 S�ren Schmidt
31541Srgrimes * Copyright (c) 1996 Peter Wemm
41541Srgrimes * All rights reserved.
51541Srgrimes *
61541Srgrimes * Redistribution and use in source and binary forms, with or without
71541Srgrimes * modification, are permitted provided that the following conditions
81541Srgrimes * are met:
91541Srgrimes * 1. Redistributions of source code must retain the above copyright
101541Srgrimes *    notice, this list of conditions and the following disclaimer
111541Srgrimes *    in this position and unchanged.
121541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
131541Srgrimes *    notice, this list of conditions and the following disclaimer in the
141541Srgrimes *    documentation and/or other materials provided with the distribution.
151541Srgrimes * 3. The name of the author may not be used to endorse or promote products
161541Srgrimes *    derived from this software withough specific prior written permission
171541Srgrimes *
181541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
191541Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
201541Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
211541Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
221541Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
231541Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
241541Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
251541Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
261541Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
271541Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
281541Srgrimes *
291541Srgrimes *	$Id: imgact_elf.c,v 1.28 1998/07/15 05:00:26 bde Exp $
301541Srgrimes */
311541Srgrimes
321541Srgrimes#include "opt_rlimit.h"
331541Srgrimes
341541Srgrimes#include <sys/param.h>
351541Srgrimes#include <sys/systm.h>
361541Srgrimes#include <sys/exec.h>
371541Srgrimes#include <sys/mman.h>
381541Srgrimes#include <sys/imgact.h>
3924453Speter#include <sys/imgact_elf.h>
401541Srgrimes#include <sys/kernel.h>
411541Srgrimes#include <sys/sysent.h>
421541Srgrimes#include <sys/malloc.h>
431541Srgrimes#include <sys/namei.h>
441541Srgrimes#include <sys/proc.h>
451541Srgrimes#include <sys/syscall.h>
461541Srgrimes#include <sys/signalvar.h>
471541Srgrimes#include <sys/sysctl.h>
481541Srgrimes#include <sys/vnode.h>
4912221Sbde
501541Srgrimes#include <vm/vm.h>
511541Srgrimes#include <vm/vm_kern.h>
521541Srgrimes#include <vm/vm_param.h>
531541Srgrimes#include <vm/pmap.h>
541541Srgrimes#include <sys/lock.h>
5518013Sbde#include <vm/vm_map.h>
561541Srgrimes#include <vm/vm_prot.h>
5712221Sbde#include <vm/vm_extern.h>
5811332Sswallace
591541Srgrimes#include <machine/md_var.h>
601541Srgrimes
6112221Sbde#define MAX_PHDR	32	/* XXX enough ? */
621541Srgrimes
631541Srgrimes#if ELF_TARG_CLASS == ELFCLASS32
641549Srgrimes
651541Srgrimes#define Elf_Ehdr	Elf32_Ehdr
661541Srgrimes#define Elf_Phdr	Elf32_Phdr
6711332Sswallace#define Elf_Auxargs	Elf32_Auxargs
681541Srgrimes#define Elf_Brandinfo	Elf32_Brandinfo
691541Srgrimes
701541Srgrimes#else
711541Srgrimes
721541Srgrimes#define Elf_Ehdr	Elf64_Ehdr
731541Srgrimes#define Elf_Phdr	Elf64_Phdr
741541Srgrimes#define Elf_Auxargs	Elf64_Auxargs
751541Srgrimes#define Elf_Brandinfo	Elf64_Brandinfo
761541Srgrimes
771541Srgrimes#endif
7812221Sbde
7911332Sswallace
8011332Sswallacestatic int elf_check_header __P((const Elf_Ehdr *hdr, int type));
8111332Sswallacestatic 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));
8212221Sbdestatic int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry));
831541Srgrimesstatic int elf_freebsd_fixup __P((long **stack_base, struct image_params *imgp));
841549Srgrimesstatic int exec_elf_imgact __P((struct image_params *imgp));
851541Srgrimes
861541Srgrimesstatic int elf_trace = 0;
8711332SswallaceSYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
881541Srgrimes#define UPRINTF if (elf_trace) uprintf
891541Srgrimes
901541Srgrimesstatic struct sysentvec elf_freebsd_sysvec = {
911541Srgrimes        SYS_MAXSYSCALL,
921541Srgrimes        sysent,
931541Srgrimes        0,
941541Srgrimes        0,
951541Srgrimes        0,
9612221Sbde        0,
9711332Sswallace        0,
9811332Sswallace        0,
9911332Sswallace        elf_freebsd_fixup,
10012221Sbde        sendsig,
10111332Sswallace        sigcode,
1021549Srgrimes        &szsigcode,
1031541Srgrimes        0,
1041541Srgrimes	"FreeBSD ELF"
10511332Sswallace};
1061541Srgrimes
1071541Srgrimesstatic Elf_Brandinfo freebsd_brand_info = {
1081541Srgrimes						"FreeBSD",
1091541Srgrimes						"",
1101541Srgrimes						"/usr/libexec/ld-elf.so.1",
1111541Srgrimes						&elf_freebsd_sysvec
1121541Srgrimes					  };
11312221Sbdestatic Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = {
11411332Sswallace							&freebsd_brand_info,
11511332Sswallace							NULL, NULL, NULL,
11611332Sswallace							NULL, NULL, NULL, NULL
11712221Sbde						    };
11811332Sswallace
1191541Srgrimesint
1201549Srgrimeself_insert_brand_entry(Elf_Brandinfo *entry)
1211541Srgrimes{
1221541Srgrimes	int i;
12311332Sswallace
1241541Srgrimes	for (i=1; i<MAX_BRANDS; i++) {
1251541Srgrimes		if (elf_brand_list[i] == NULL) {
1261541Srgrimes			elf_brand_list[i] = entry;
1271541Srgrimes			break;
1281541Srgrimes		}
1291541Srgrimes	}
1301541Srgrimes	if (i == MAX_BRANDS)
1311541Srgrimes		return -1;
1321541Srgrimes	return 0;
1331541Srgrimes}
13412221Sbde
13511332Sswallaceint
13611332Sswallaceelf_remove_brand_entry(Elf_Brandinfo *entry)
13711332Sswallace{
13812221Sbde	int i;
13911332Sswallace
1401541Srgrimes	for (i=1; i<MAX_BRANDS; i++) {
1411549Srgrimes		if (elf_brand_list[i] == entry) {
1421541Srgrimes			elf_brand_list[i] = NULL;
1431541Srgrimes			break;
14411332Sswallace		}
1451541Srgrimes	}
1461541Srgrimes	if (i == MAX_BRANDS)
1471541Srgrimes		return -1;
1481541Srgrimes	return 0;
1491541Srgrimes}
1501541Srgrimes
1511541Srgrimesstatic int
15212221Sbdeelf_check_header(const Elf_Ehdr *hdr, int type)
15311332Sswallace{
15411332Sswallace	if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 &&
15511332Sswallace	      hdr->e_ident[EI_MAG1] == ELFMAG1 &&
15612221Sbde	      hdr->e_ident[EI_MAG2] == ELFMAG2 &&
15711332Sswallace	      hdr->e_ident[EI_MAG3] == ELFMAG3))
1581541Srgrimes		return ENOEXEC;
1591549Srgrimes
1601541Srgrimes#ifdef __i386__
1611541Srgrimes	if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486)
16211332Sswallace#endif
1631541Srgrimes#ifdef __alpha__
1641541Srgrimes	if (hdr->e_machine != EM_ALPHA)
1651541Srgrimes#endif
1661541Srgrimes		return ENOEXEC;
1671541Srgrimes
1681541Srgrimes
1691541Srgrimes	if (hdr->e_type != type)
1701541Srgrimes		return ENOEXEC;
1711541Srgrimes
1721541Srgrimes	return 0;
1731541Srgrimes}
1741541Srgrimes
1751541Srgrimesstatic int
1761541Srgrimeself_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)
1771541Srgrimes{
17812221Sbde	size_t map_len;
17911332Sswallace	vm_offset_t map_addr;
18011332Sswallace	int error;
18111332Sswallace	unsigned char *data_buf = 0;
18212221Sbde	size_t copy_len;
18311332Sswallace
1841541Srgrimes	map_addr = trunc_page(vmaddr);
1851549Srgrimes
1861541Srgrimes	if (memsz > filsz)
1871541Srgrimes		map_len = trunc_page(offset+filsz) - trunc_page(offset);
18811332Sswallace	else
1891541Srgrimes		map_len = round_page(offset+filsz) - trunc_page(offset);
1901541Srgrimes
1911541Srgrimes	if (error = vm_mmap (&vmspace->vm_map,
1921541Srgrimes			     &map_addr,
1931541Srgrimes			     map_len,
1941541Srgrimes			     prot,
1951541Srgrimes			     VM_PROT_ALL,
19612221Sbde			     MAP_PRIVATE | MAP_FIXED,
1971541Srgrimes			     (caddr_t)vp,
1981541Srgrimes			     trunc_page(offset)))
1991541Srgrimes		return error;
2001541Srgrimes
20112221Sbde	if (memsz == filsz)
2021549Srgrimes		return 0;
2031541Srgrimes
2041541Srgrimes	/*
2051541Srgrimes	 * We have to map the remaining bit of the file into the kernel's
2061541Srgrimes	 * memory map, allocate some anonymous memory, and copy that last
2071541Srgrimes	 * bit into it. The remaining space should be .bss...
2081541Srgrimes	 */
2091541Srgrimes	copy_len = (offset + filsz) - trunc_page(offset + filsz);
2101541Srgrimes	map_addr = trunc_page(vmaddr + filsz);
2111541Srgrimes	map_len = round_page(vmaddr + memsz) - map_addr;
2121541Srgrimes
2131541Srgrimes        if (map_len != 0) {
2141541Srgrimes		if (error = vm_map_find(&vmspace->vm_map, NULL, 0,
2151541Srgrimes					&map_addr, map_len, FALSE,
2161541Srgrimes					VM_PROT_ALL, VM_PROT_ALL,0))
2171541Srgrimes			return error;
2181541Srgrimes	}
2193098Sphk
2203098Sphk	if (error = vm_mmap(exec_map,
2211541Srgrimes			    (vm_offset_t *)&data_buf,
2221541Srgrimes			    PAGE_SIZE,
2231541Srgrimes			    VM_PROT_READ,
2241541Srgrimes			    VM_PROT_READ,
2251541Srgrimes			    0,
22612221Sbde			    (caddr_t)vp,
22712207Sbde			    trunc_page(offset + filsz)))
22811332Sswallace		return error;
22911332Sswallace
23012221Sbde	error = copyout(data_buf, (caddr_t)map_addr, copy_len);
23111332Sswallace
2321541Srgrimes        vm_map_remove(exec_map, (vm_offset_t)data_buf,
2331549Srgrimes		      (vm_offset_t)data_buf + PAGE_SIZE);
2341541Srgrimes
2351541Srgrimes	/*
23612207Sbde	 * set it to the specified protection
2371541Srgrimes	 */
2381541Srgrimes	vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len,  prot,
2391541Srgrimes		       FALSE);
2401541Srgrimes
2411541Srgrimes	UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len);
2421541Srgrimes	return error;
2431541Srgrimes}
2441541Srgrimes
2451541Srgrimesstatic int
2461541Srgrimeself_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
2471541Srgrimes{
2481541Srgrimes	Elf_Ehdr *hdr = NULL;
2491541Srgrimes	Elf_Phdr *phdr = NULL;
2501541Srgrimes	struct nameidata nd;
2511541Srgrimes	struct vmspace *vmspace = p->p_vmspace;
2521541Srgrimes	struct vattr attr;
2531541Srgrimes	struct image_params image_params, *imgp;
2541541Srgrimes	vm_prot_t prot = 0;
2551541Srgrimes	unsigned long text_size = 0, data_size = 0;
2561541Srgrimes	unsigned long text_addr = 0, data_addr = 0;
2571541Srgrimes	int header_size = 0;
2581541Srgrimes        int error, i;
2591541Srgrimes
2601541Srgrimes	imgp = &image_params;
2611541Srgrimes	/*
26212221Sbde	 * Initialize part of the common data
2631541Srgrimes	 */
2641541Srgrimes	imgp->proc = p;
2651541Srgrimes	imgp->uap = NULL;
2661541Srgrimes	imgp->attr = &attr;
26712221Sbde	imgp->firstpage = NULL;
2681541Srgrimes	imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE);
2691549Srgrimes
2701541Srgrimes	if (imgp->image_header == NULL) {
2711541Srgrimes		nd.ni_vp = NULL;
2721541Srgrimes		error = ENOMEM;
2731541Srgrimes		goto fail;
2741541Srgrimes	}
2751541Srgrimes
2761541Srgrimes        NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
2771541Srgrimes
27820677Sbde	if (error = namei(&nd)) {
27920677Sbde		nd.ni_vp = NULL;
2801541Srgrimes		goto fail;
2811541Srgrimes	}
2821541Srgrimes
28315985Sdg	imgp->vp = nd.ni_vp;
2841541Srgrimes
2851541Srgrimes	/*
2861541Srgrimes	 * Check permissions, modes, uid, etc on the file, and "open" it.
2871541Srgrimes	 */
2881541Srgrimes	error = exec_check_permissions(imgp);
2891541Srgrimes	if (error) {
2901541Srgrimes		VOP_UNLOCK(nd.ni_vp, 0, p);
2911541Srgrimes		goto fail;
2921541Srgrimes	}
2931541Srgrimes
2941541Srgrimes	error = exec_map_first_page(imgp);
2951541Srgrimes	VOP_UNLOCK(nd.ni_vp, 0, p);
2961541Srgrimes	if (error)
2971541Srgrimes                goto fail;
2981541Srgrimes
2991541Srgrimes	hdr = (Elf_Ehdr *)imgp->image_header;
30024448Speter	if (error = elf_check_header(hdr, ET_DYN))
30124448Speter		goto fail;
30224448Speter
30324448Speter	/*
30424448Speter	 * ouch, need to bounds check in case user gives us a corrupted
30524448Speter	 * file with an insane header size
30624448Speter	 */
30724448Speter	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
30824448Speter		error = ENOEXEC;
30924448Speter		goto fail;
31024448Speter	}
31124448Speter
31212221Sbde	header_size = hdr->e_phentsize * hdr->e_phnum;
3131541Srgrimes
3141541Srgrimes	/* Only support headers that fit within first page for now */
3151541Srgrimes	if (header_size + hdr->e_phoff > PAGE_SIZE) {
31612221Sbde		error = ENOEXEC;
3171541Srgrimes		goto fail;
3181549Srgrimes	}
3191541Srgrimes
3201541Srgrimes	phdr = (Elf_Phdr *)(imgp->image_header + hdr->e_phoff);
3211541Srgrimes
3221541Srgrimes	for (i = 0; i < hdr->e_phnum; i++) {
3231541Srgrimes		switch(phdr[i].p_type) {
3241541Srgrimes
3251541Srgrimes	   	case PT_NULL:	/* NULL section */
3261541Srgrimes	    		UPRINTF ("ELF(file) PT_NULL section\n");
3271541Srgrimes			break;
32824448Speter		case PT_LOAD:	/* Loadable segment */
32924448Speter		{
33024448Speter	    		UPRINTF ("ELF(file) PT_LOAD section ");
33124448Speter			if (phdr[i].p_flags & PF_X)
33224448Speter  				prot |= VM_PROT_EXECUTE;
33324448Speter			if (phdr[i].p_flags & PF_W)
33424448Speter  				prot |= VM_PROT_WRITE;
33524448Speter			if (phdr[i].p_flags & PF_R)
33624448Speter  				prot |= VM_PROT_READ;
33724448Speter
33824448Speter			if (error = elf_load_section(vmspace, nd.ni_vp,
33924448Speter  						     phdr[i].p_offset,
34024448Speter  						     (caddr_t)phdr[i].p_vaddr +
34124448Speter							(*addr),
34224448Speter  						     phdr[i].p_memsz,
34324448Speter  						     phdr[i].p_filesz, prot))
34424448Speter				goto fail;
3451541Srgrimes
34624448Speter			/*
34717994Sache			 * Is this .text or .data ??
34824448Speter			 *
34917994Sache			 * We only handle one each of those yet XXX
35024448Speter			 */
35124448Speter			if (hdr->e_entry >= phdr[i].p_vaddr &&
35224448Speter			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
3538162Sache  				text_addr = trunc_page(phdr[i].p_vaddr+(*addr));
3541541Srgrimes  				text_size = round_page(phdr[i].p_memsz +
35524448Speter						       phdr[i].p_vaddr -
35624448Speter						       trunc_page(phdr[i].p_vaddr));
3571541Srgrimes				*entry=(unsigned long)hdr->e_entry+(*addr);
35824448Speter	    			UPRINTF(".text <%08lx,%08lx> entry=%08lx\n",
35924448Speter					text_addr, text_size, *entry);
3601541Srgrimes			} else {
36117994Sache  				data_addr = trunc_page(phdr[i].p_vaddr+(*addr));
36224448Speter  				data_size = round_page(phdr[i].p_memsz +
36324448Speter						       phdr[i].p_vaddr -
36417994Sache						       trunc_page(phdr[i].p_vaddr));
36524448Speter	    			UPRINTF(".data <%08lx,%08lx>\n",
36617994Sache					data_addr, data_size);
36724448Speter			}
36824448Speter		}
36924448Speter		break;
37024448Speter
37124448Speter	   	case PT_DYNAMIC:/* Dynamic link information */
37224448Speter	    		UPRINTF ("ELF(file) PT_DYNAMIC section\n");
37324448Speter			break;
37424448Speter	  	case PT_INTERP:	/* Path to interpreter */
37524448Speter	    		UPRINTF ("ELF(file) PT_INTERP section\n");
37624448Speter			break;
37724448Speter	  	case PT_NOTE:	/* Note section */
37824448Speter	    		UPRINTF ("ELF(file) PT_NOTE section\n");
37924448Speter			break;
38024448Speter	  	case PT_SHLIB:	/* Shared lib section  */
38124448Speter	    		UPRINTF ("ELF(file) PT_SHLIB section\n");
38224448Speter			break;
38324448Speter		case PT_PHDR: 	/* Program header table info */
38424448Speter	    		UPRINTF ("ELF(file) PT_PHDR section\n");
38524448Speter			break;
38624448Speter		default:
38724448Speter	    		UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type );
38824448Speter		}
38924448Speter	}
39024448Speter
39124448Speterfail:
39224448Speter	if (imgp->firstpage)
3938141Sache		exec_unmap_first_page(imgp);
39424448Speter	if (imgp->image_header)
39524448Speter		kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header,
39624448Speter			PAGE_SIZE);
39724448Speter	if (nd.ni_vp)
39824448Speter		vrele(nd.ni_vp);
39924448Speter
40024448Speter	return error;
40124448Speter}
40224448Speter
40324448Speterstatic int
4041541Srgrimesexec_elf_imgact(struct image_params *imgp)
4051541Srgrimes{
4061541Srgrimes	const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header;
40712221Sbde	const Elf_Phdr *phdr, *mapped_phdr = NULL;
4081541Srgrimes	Elf_Auxargs *elf_auxargs = NULL;
4091541Srgrimes	struct vmspace *vmspace;
4101541Srgrimes	vm_prot_t prot = 0;
41112221Sbde	u_long text_size = 0, data_size = 0;
4121541Srgrimes	u_long text_addr = 0, data_addr = 0;
4131549Srgrimes	u_long addr, entry = 0, proghdr = 0;
4141541Srgrimes	int error, i, header_size = 0;
4151541Srgrimes	const char *interp = NULL;
4161541Srgrimes	char *brand = NULL;
4171541Srgrimes	char path[MAXPATHLEN];
4181541Srgrimes
4191541Srgrimes	/*
4201541Srgrimes	 * Do we have a valid ELF header ?
4211541Srgrimes	 */
4221541Srgrimes	if (elf_check_header(hdr, ET_EXEC))
4231541Srgrimes		return -1;
42424449Speter
42524449Speter	/*
4261541Srgrimes	 * From here on down, we return an errno, not -1, as we've
4271541Srgrimes	 * detected an ELF file.
4281541Srgrimes	 */
4291541Srgrimes
4301541Srgrimes	/*
4311541Srgrimes	 * ouch, need to bounds check in case user gives us a corrupted
43224449Speter	 * file with an insane header size
43324449Speter	 */
43424449Speter	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
43524449Speter		return ENOEXEC;
43624449Speter	}
4371541Srgrimes
4381541Srgrimes	header_size = hdr->e_phentsize * hdr->e_phnum;
4391541Srgrimes
44012221Sbde	if ((hdr->e_phoff > PAGE_SIZE) ||
4411541Srgrimes	    (hdr->e_phoff + header_size) > PAGE_SIZE) {
4421541Srgrimes		/* Only support headers in first page for now */
4431541Srgrimes		return ENOEXEC;
44412221Sbde	} else {
4451541Srgrimes		phdr = (const Elf_Phdr*)
4461549Srgrimes		       ((const char *)imgp->image_header + hdr->e_phoff);
4471541Srgrimes	}
4481541Srgrimes
4491541Srgrimes	/*
4501541Srgrimes	 * From this point on, we may have resources that need to be freed.
4511541Srgrimes	 */
4521541Srgrimes	if (error = exec_extract_strings(imgp))
4531541Srgrimes		goto fail;
4541541Srgrimes
4551541Srgrimes	exec_new_vmspace(imgp);
45624448Speter
45724448Speter	vmspace = imgp->proc->p_vmspace;
45824448Speter
45924448Speter	for (i = 0; i < hdr->e_phnum; i++) {
46024448Speter		switch(phdr[i].p_type) {
46124448Speter
46224448Speter	   	case PT_NULL:	/* NULL section */
46324448Speter	    		UPRINTF ("ELF PT_NULL section\n");
46424448Speter			break;
46524448Speter		case PT_LOAD:	/* Loadable segment */
46624448Speter		{
4671541Srgrimes	    		UPRINTF ("ELF PT_LOAD section ");
46824448Speter			if (phdr[i].p_flags & PF_X)
46917994Sache  				prot |= VM_PROT_EXECUTE;
47024448Speter			if (phdr[i].p_flags & PF_W)
47117994Sache  				prot |= VM_PROT_WRITE;
47224448Speter			if (phdr[i].p_flags & PF_R)
47324448Speter  				prot |= VM_PROT_READ;
47424448Speter
4758162Sache			if (error = elf_load_section(vmspace, imgp->vp,
4761541Srgrimes  						     phdr[i].p_offset,
47724448Speter  						     (caddr_t)phdr[i].p_vaddr,
47817994Sache  						     phdr[i].p_memsz,
47924448Speter  						     phdr[i].p_filesz, prot))
48024448Speter  				goto fail;
48124448Speter
48224448Speter			/*
48324448Speter			 * Is this .text or .data ??
48424448Speter			 *
48524448Speter			 * We only handle one each of those yet XXX
48617994Sache			 */
48724448Speter			if (hdr->e_entry >= phdr[i].p_vaddr &&
48824448Speter			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
48924448Speter  				text_addr = trunc_page(phdr[i].p_vaddr);
49024448Speter  				text_size = round_page(phdr[i].p_memsz +
49124448Speter						       phdr[i].p_vaddr -
49224448Speter						       text_addr);
49324448Speter				entry = (u_long)hdr->e_entry;
49424448Speter	    			UPRINTF(".text <%08lx,%08lx> entry=%08lx\n",
49524448Speter					text_addr, text_size, entry);
49624448Speter			} else {
49724448Speter  				data_addr = trunc_page(phdr[i].p_vaddr);
49824448Speter  				data_size = round_page(phdr[i].p_memsz +
49924448Speter						       phdr[i].p_vaddr -
50024448Speter						       data_addr);
50124448Speter	    			UPRINTF(".data <%08lx,%08lx>\n",
50224448Speter					data_addr, data_size);
50324448Speter			}
50424448Speter		}
50524448Speter		break;
50624448Speter
50724448Speter	   	case PT_DYNAMIC:/* Dynamic link information */
5088141Sache	    		UPRINTF ("ELF PT_DYNAMIC section ??\n");
50924448Speter			break;
51024448Speter	  	case PT_INTERP:	/* Path to interpreter */
51124448Speter	    		UPRINTF ("ELF PT_INTERP section ");
51224448Speter			if (phdr[i].p_filesz > MAXPATHLEN ||
51324448Speter			    phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) {
51424448Speter				error = ENOEXEC;
51524448Speter				goto fail;
51624448Speter			}
51724448Speter			interp = imgp->image_header + phdr[i].p_offset;
5181541Srgrimes			UPRINTF("<%s>\n", interp);
5191541Srgrimes			break;
5201541Srgrimes	  	case PT_NOTE:	/* Note section */
52112221Sbde	    		UPRINTF ("ELF PT_NOTE section\n");
5221541Srgrimes			break;
5231541Srgrimes	  	case PT_SHLIB:	/* Shared lib section  */
5241541Srgrimes	    		UPRINTF ("ELF PT_SHLIB section\n");
52512221Sbde			break;
5261541Srgrimes		case PT_PHDR: 	/* Program header table info */
5271549Srgrimes	    		UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr);
5281541Srgrimes			proghdr = phdr[i].p_vaddr;
5291541Srgrimes			break;
5301541Srgrimes		default:
5311541Srgrimes	    		UPRINTF ("ELF %d section ??\n", phdr[i].p_type);
5321541Srgrimes		}
5331541Srgrimes	}
5341541Srgrimes
5351541Srgrimes	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
5361541Srgrimes	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
5371541Srgrimes	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
53824449Speter	vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr;
53924449Speter
5401541Srgrimes	addr = 2L*MAXDSIZ; /* May depend on OS type XXX */
5411541Srgrimes
54224449Speter	imgp->entry_addr = entry;
54324449Speter
54424449Speter	/*
54524449Speter	 * So which kind (brand) of ELF binary do we have at hand
54624449Speter	 * FreeBSD, Linux, SVR4 or something else ??
5471541Srgrimes	 * If its has a interpreter section try that first
5481541Srgrimes	 */
5491541Srgrimes        if (interp) {
55012221Sbde                for (i=0; i<MAX_BRANDS; i++) {
5511541Srgrimes                        if (elf_brand_list[i] != NULL) {
5521541Srgrimes                                if (!strcmp(interp, elf_brand_list[i]->interp_path)) {
5531541Srgrimes                                        imgp->proc->p_sysent =
5541541Srgrimes                                                elf_brand_list[i]->sysvec;
55512221Sbde                                        strcpy(path, elf_brand_list[i]->emul_path);
5561541Srgrimes                                        strcat(path, elf_brand_list[i]->interp_path);
5571549Srgrimes                                        UPRINTF("interpreter=<%s> %s\n",
5581541Srgrimes                                                elf_brand_list[i]->interp_path,
5591541Srgrimes                                                elf_brand_list[i]->emul_path);
5601541Srgrimes                                        break;
5611541Srgrimes                                }
5621541Srgrimes                        }
5631541Srgrimes                }
5641541Srgrimes        }
5651541Srgrimes
5661541Srgrimes	/*
5673098Sphk	 * If there is no interpreter, or recognition of it
5681541Srgrimes	 * failed, se if the binary is branded.
56912063Sdg	 */
57024447Speter	if (!interp || i == MAX_BRANDS) {
5711541Srgrimes		brand = (char *)&(hdr->e_ident[EI_BRAND]);
57224447Speter		for (i=0; i<MAX_BRANDS; i++) {
57324447Speter			if (elf_brand_list[i] != NULL) {
57424447Speter				if (!strcmp(brand, elf_brand_list[i]->brand)) {
57524447Speter					imgp->proc->p_sysent = elf_brand_list[i]->sysvec;
5761541Srgrimes					if (interp) {
57724447Speter						strcpy(path, elf_brand_list[i]->emul_path);
57824447Speter						strcat(path, elf_brand_list[i]->interp_path);
57924447Speter						UPRINTF("interpreter=<%s> %s\n",
58024447Speter						elf_brand_list[i]->interp_path,
58124447Speter						elf_brand_list[i]->emul_path);
58224447Speter					}
58324447Speter					break;
58424447Speter				}
58524447Speter			}
58624447Speter		}
58724447Speter	}
58824447Speter	if (i == MAX_BRANDS) {
58924447Speter#ifndef __alpha__
59024447Speter		uprintf("ELF binary type not known\n");
5911541Srgrimes		error = ENOEXEC;
5921541Srgrimes		goto fail;
5931541Srgrimes#else
5941541Srgrimes		i = 0;		/* assume freebsd */
59512221Sbde		imgp->proc->p_sysent = elf_brand_list[i]->sysvec;
5961541Srgrimes		if (interp) {
5979238Sache			strcpy(path, elf_brand_list[i]->emul_path);
5989238Sache			strcat(path, elf_brand_list[i]->interp_path);
5991541Srgrimes			UPRINTF("interpreter=<%s> %s\n",
60012221Sbde				elf_brand_list[i]->interp_path,
6011541Srgrimes				elf_brand_list[i]->emul_path);
6021549Srgrimes		}
6038019Sache#endif
6041541Srgrimes	}
6051541Srgrimes	if (interp) {
6061541Srgrimes                if (error = elf_load_file(imgp->proc,
6071541Srgrimes                                          path,
6081541Srgrimes                                          &addr,        /* XXX */
6099238Sache                                          &imgp->entry_addr)) {
6108135Sache                        uprintf("ELF interpreter %s not found\n", path);
6111541Srgrimes                        goto fail;
6129238Sache                }
6139238Sache	}
6149238Sache
6159238Sache	UPRINTF("Executing %s binary\n", elf_brand_list[i]->brand);
6168135Sache
6178135Sache	/*
6189238Sache	 * Construct auxargs table (used by the fixup routine)
61924450Speter	 */
62024450Speter	elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK);
6219238Sache	elf_auxargs->execfd = -1;
62224450Speter	elf_auxargs->phdr = proghdr;
62324450Speter	elf_auxargs->phent = hdr->e_phentsize;
62424450Speter	elf_auxargs->phnum = hdr->e_phnum;
6259238Sache	elf_auxargs->pagesz = PAGE_SIZE;
6269238Sache	elf_auxargs->base = addr;
6279238Sache	elf_auxargs->flags = 0;
62824450Speter	elf_auxargs->entry = entry;
6298135Sache	elf_auxargs->trace = elf_trace;
63024450Speter
6318111Sache	imgp->auxargs = elf_auxargs;
63224450Speter	imgp->interpreted = 0;
63324450Speter
6348135Sache	/* don't allow modifying the file while we run it */
6351541Srgrimes	imgp->vp->v_flag |= VTEXT;
6361541Srgrimes
63712221Sbdefail:
6381541Srgrimes	return error;
6399238Sache}
6409238Sache
6411541Srgrimesstatic int
64212221Sbdeelf_freebsd_fixup(long **stack_base, struct image_params *imgp)
6431541Srgrimes{
6441549Srgrimes	Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
6458019Sache	long *pos;
6461541Srgrimes
6471541Srgrimes	pos = *stack_base + (imgp->argc + imgp->envc + 2);
6481541Srgrimes
6491541Srgrimes	if (args->trace) {
6501541Srgrimes		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
6519238Sache	}
6528135Sache	if (args->execfd != -1) {
6531541Srgrimes		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
6549238Sache	}
6559238Sache	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
6569238Sache	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
6579238Sache	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
6588135Sache	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
6598135Sache	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
6609238Sache	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
66124450Speter	AUXARGS_ENTRY(pos, AT_BASE, args->base);
66224450Speter	AUXARGS_ENTRY(pos, AT_NULL, 0);
6639238Sache
66424450Speter	free(imgp->auxargs, M_TEMP);
66524450Speter	imgp->auxargs = NULL;
66624450Speter
6679238Sache	(*stack_base)--;
66824450Speter	**stack_base = (long)imgp->argc;
66924450Speter	return 0;
67024450Speter}
6718111Sache
67224450Speter/*
67324450Speter * Tell kern_execve.c about it, with a little help from the linker.
6748135Sache * Since `const' objects end up in the text segment, TEXT_SET is the
6751541Srgrimes * correct directive to use.
6761541Srgrimes */
67724453Speterstatic const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
67824453SpeterTEXT_SET(execsw_set, elf_execsw);
67924453Speter
68024453Speter