imgact_elf.c revision 18959
159093Sdfr/*-
2121129Sdfr * Copyright (c) 1995-1996 S�ren Schmidt
359093Sdfr * Copyright (c) 1996 Peter Wemm
459093Sdfr * All rights reserved.
559093Sdfr *
659093Sdfr * Redistribution and use in source and binary forms, with or without
759093Sdfr * modification, are permitted provided that the following conditions
859093Sdfr * are met:
959093Sdfr * 1. Redistributions of source code must retain the above copyright
1059093Sdfr *    notice, this list of conditions and the following disclaimer
1159093Sdfr *    in this position and unchanged.
1259093Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1359093Sdfr *    notice, this list of conditions and the following disclaimer in the
1459093Sdfr *    documentation and/or other materials provided with the distribution.
1559093Sdfr * 3. The name of the author may not be used to endorse or promote products
1659093Sdfr *    derived from this software withough specific prior written permission
1759093Sdfr *
1859093Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1959093Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2059093Sdfr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2159093Sdfr * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2259093Sdfr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2359093Sdfr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2459093Sdfr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2559093Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2659093Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27116182Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28116182Sobrien *
29116182Sobrien *	$Id: imgact_elf.c,v 1.9 1996/10/03 06:14:48 peter Exp $
3059093Sdfr */
31121129Sdfr
32121129Sdfr#include <sys/param.h>
33121129Sdfr#include <sys/systm.h>
3459093Sdfr#include <sys/resourcevar.h>
35121129Sdfr#include <sys/exec.h>
36118921Scg#include <sys/mman.h>
3759093Sdfr#include <sys/imgact.h>
3859093Sdfr#include <sys/imgact_elf.h>
3959093Sdfr#include <sys/kernel.h>
4059093Sdfr#include <sys/sysent.h>
4159093Sdfr#include <sys/file.h>
4259093Sdfr#include <sys/malloc.h>
4359093Sdfr#include <sys/mount.h>
4459093Sdfr#include <sys/namei.h>
4559093Sdfr#include <sys/proc.h>
4659093Sdfr#include <sys/sysproto.h>
4759093Sdfr#include <sys/syscall.h>
4859093Sdfr#include <sys/signalvar.h>
4998105Skbyanc#include <sys/sysctl.h>
5098105Skbyanc#include <sys/vnode.h>
5159093Sdfr
5298105Skbyanc#include <vm/vm.h>
53118921Scg#include <vm/vm_kern.h>
5498105Skbyanc#include <vm/vm_param.h>
55118921Scg#include <vm/pmap.h>
5659093Sdfr#include <vm/lock.h>
5759093Sdfr#include <vm/vm_map.h>
5859093Sdfr#include <vm/vm_prot.h>
59121129Sdfr#include <vm/vm_extern.h>
60148811Sgrehan
6159093Sdfr#include <machine/md_var.h>
6259093Sdfr#include <i386/linux/linux_syscall.h>
63186347Snwhitehorn#include <i386/linux/linux.h>
64186347Snwhitehorn
65186347Snwhitehorn#define MAX_PHDR	32	/* XXX enough ? */
66186347Snwhitehorn
67186347Snwhitehornstatic int map_pages __P((struct vnode *vp, vm_offset_t offset, vm_offset_t *buf, vm_size_t size));
68186347Snwhitehornstatic void unmap_pages __P((vm_offset_t buf, vm_size_t size));
69186347Snwhitehornstatic int elf_check_permissions __P((struct proc *p, struct vnode *vp));
70186347Snwhitehornstatic int elf_check_header __P((const Elf32_Ehdr *hdr, int type));
71186347Snwhitehornstatic 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));
72186347Snwhitehornstatic int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry));
73186347Snwhitehornstatic int elf_freebsd_fixup __P((int **stack_base, struct image_params *imgp));
74186347Snwhitehornint exec_elf_imgact __P((struct image_params *imgp));
75186347Snwhitehorn
76217326Smdfint elf_trace = 0;
77118921ScgSYSCTL_INT(_debug, 1, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
78118921Scg#define UPRINTF if (elf_trace) uprintf
79121129Sdfr
80121129Sdfrstatic struct sysentvec elf_freebsd_sysvec = {
81121129Sdfr        SYS_MAXSYSCALL,
82148811Sgrehan        sysent,
83148811Sgrehan        0,
84148811Sgrehan        0,
85148811Sgrehan        0,
86121129Sdfr        0,
87121129Sdfr        0,
88121129Sdfr        elf_freebsd_fixup,
89121129Sdfr        sendsig,
90121129Sdfr        sigcode,
91121129Sdfr        &szsigcode,
92121129Sdfr        0,
93121129Sdfr	"FreeBSD ELF"
94121129Sdfr};
95121129Sdfr
96121129Sdfrstatic Elf32_Brandinfo freebsd_brand_info = {
97121129Sdfr						"FreeBSD",
98121129Sdfr						"",
99121129Sdfr						"/usr/libexec/ld-elf.so.1",
10059093Sdfr						&elf_freebsd_sysvec
10159093Sdfr					  };
102121129Sdfrstatic Elf32_Brandinfo *elf_brand_list[MAX_BRANDS] = {
10359093Sdfr							&freebsd_brand_info,
10459093Sdfr							NULL, NULL, NULL,
10559093Sdfr							NULL, NULL, NULL, NULL
10659093Sdfr						    };
10759093Sdfr
10859093Sdfrint
109186347Snwhitehornelf_insert_brand_entry(Elf32_Brandinfo *entry)
110121129Sdfr{
111118921Scg	int i;
11259093Sdfr
113118921Scg	for (i=1; i<MAX_BRANDS; i++) {
11459093Sdfr		if (elf_brand_list[i] == NULL) {
11559093Sdfr			elf_brand_list[i] = entry;
11659093Sdfr			break;
11759093Sdfr		}
11859093Sdfr	}
11959093Sdfr	if (i == MAX_BRANDS)
12059093Sdfr		return -1;
12165173Sdfr	return 0;
12265173Sdfr}
12359093Sdfr
12459093Sdfrint
12559093Sdfrelf_remove_brand_entry(Elf32_Brandinfo *entry)
12659093Sdfr{
127186347Snwhitehorn	int i;
128121129Sdfr
12959093Sdfr	for (i=1; i<MAX_BRANDS; i++) {
13059093Sdfr		if (elf_brand_list[i] == entry) {
13159093Sdfr			elf_brand_list[i] = NULL;
13259093Sdfr			break;
13359093Sdfr		}
13459093Sdfr	}
13559093Sdfr	if (i == MAX_BRANDS)
13659093Sdfr		return -1;
13759093Sdfr	return 0;
13859093Sdfr}
13959093Sdfr
14059093Sdfrstatic int
14159093Sdfrmap_pages(struct vnode *vp, vm_offset_t offset,
14265173Sdfr	     vm_offset_t *buf, vm_size_t size)
14359093Sdfr{
144121129Sdfr	int error;
145121129Sdfr	vm_offset_t kern_buf;
14659093Sdfr	vm_size_t pageoff;
14759093Sdfr
14859093Sdfr	/*
14959093Sdfr	 * The request may not be aligned, and may even cross several
15059093Sdfr	 * page boundaries in the file...
15165173Sdfr	 */
15265173Sdfr	pageoff = (offset & PAGE_MASK);
15365173Sdfr	offset -= pageoff;		/* start of first aligned page to map */
15465173Sdfr	size += pageoff;
155186347Snwhitehorn	size = round_page(size);	/* size of aligned pages to map */
156121129Sdfr
15765173Sdfr	if (error = vm_mmap(kernel_map,
15865173Sdfr			    &kern_buf,
15965173Sdfr			    size,
16065173Sdfr			    VM_PROT_READ,
16165173Sdfr			    VM_PROT_READ,
16265173Sdfr			    0,
163121129Sdfr			    (caddr_t)vp,
164186347Snwhitehorn			    offset))
165121129Sdfr		return error;
166121129Sdfr
167121129Sdfr	*buf = kern_buf + pageoff;
168121129Sdfr
169121129Sdfr	return 0;
170121129Sdfr}
171121129Sdfr
172186347Snwhitehornstatic void
173121129Sdfrunmap_pages(vm_offset_t buf, vm_size_t size)
174121129Sdfr{
175121129Sdfr	vm_size_t pageoff;
176121129Sdfr
17765173Sdfr	pageoff = (buf & PAGE_MASK);
178186347Snwhitehorn	buf -= pageoff;		/* start of first aligned page to map */
17965173Sdfr	size += pageoff;
18065173Sdfr	size = round_page(size);/* size of aligned pages to map */
18165173Sdfr
18265173Sdfr      	vm_map_remove(kernel_map, buf, buf + size);
18365173Sdfr}
184121129Sdfr
185186347Snwhitehornstatic int
186121129Sdfrelf_check_permissions(struct proc *p, struct vnode *vp)
18765173Sdfr{
18865173Sdfr	struct vattr attr;
18965173Sdfr	int error;
190186347Snwhitehorn
191186347Snwhitehorn	/*
19265173Sdfr	 * Check number of open-for-writes on the file and deny execution
19365173Sdfr	 *	if there are any.
194186347Snwhitehorn	 */
195186347Snwhitehorn	if (vp->v_writecount) {
19665173Sdfr		return (ETXTBSY);
19765173Sdfr	}
198121129Sdfr
199121129Sdfr	/* Get file attributes */
20059093Sdfr	error = VOP_GETATTR(vp, &attr, p->p_ucred, p);
201121129Sdfr	if (error)
202121129Sdfr		return (error);
203121129Sdfr
204121129Sdfr	/*
205121129Sdfr	 * 1) Check if file execution is disabled for the filesystem that this
206121129Sdfr	 *	file resides on.
20759093Sdfr	 * 2) Insure that at least one execute bit is on - otherwise root
20859093Sdfr	 *	will always succeed, and we don't want to happen unless the
209121129Sdfr	 *	file really is executable.
210188063Simp	 * 3) Insure that the file is a regular file.
21159093Sdfr	 */
21259093Sdfr	if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
213121129Sdfr	    ((attr.va_mode & 0111) == 0) ||
214121129Sdfr	    (attr.va_type != VREG)) {
215121129Sdfr		return (EACCES);
216121129Sdfr	}
217121129Sdfr
218121129Sdfr	/*
219121129Sdfr	 * Zero length files can't be exec'd
220121129Sdfr	 */
221121129Sdfr	if (attr.va_size == 0)
222121129Sdfr		return (ENOEXEC);
223121129Sdfr
224121129Sdfr	/*
225121129Sdfr	 *  Check for execute permission to file based on current credentials.
226121129Sdfr	 *	Then call filesystem specific open routine (which does nothing
227121129Sdfr	 *	in the general case).
228121129Sdfr	 */
229121129Sdfr	error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
230121129Sdfr	if (error)
231121129Sdfr		return (error);
232121129Sdfr
233188063Simp	error = VOP_OPEN(vp, FREAD, p->p_ucred, p);
234121129Sdfr	if (error)
235121129Sdfr		return (error);
236121129Sdfr
237121129Sdfr	return (0);
238121129Sdfr}
239121129Sdfr
240121129Sdfrstatic int
241121129Sdfrelf_check_header(const Elf32_Ehdr *hdr, int type)
242121129Sdfr{
243121129Sdfr	if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 &&
244121129Sdfr	      hdr->e_ident[EI_MAG1] == ELFMAG1 &&
245121129Sdfr	      hdr->e_ident[EI_MAG2] == ELFMAG2 &&
246121129Sdfr	      hdr->e_ident[EI_MAG3] == ELFMAG3))
247121129Sdfr		return ENOEXEC;
248121129Sdfr
249153844Sjhb	if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486)
250121129Sdfr		return ENOEXEC;
251121129Sdfr
252121129Sdfr	if (hdr->e_type != type)
253121129Sdfr		return ENOEXEC;
254121129Sdfr
255121129Sdfr	return 0;
256121129Sdfr}
257121129Sdfr
258121129Sdfrstatic int
25959093Sdfrelf_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)
26059093Sdfr{
26159093Sdfr	size_t map_len;
26259093Sdfr	vm_offset_t map_addr;
26359093Sdfr	int error;
264188063Simp	unsigned char *data_buf = 0;
26559093Sdfr	size_t copy_len;
266186347Snwhitehorn
267186347Snwhitehorn	map_addr = trunc_page(vmaddr);
268121129Sdfr
26959093Sdfr	if (memsz > filsz)
270121129Sdfr		map_len = trunc_page(offset+filsz) - trunc_page(offset);
271121129Sdfr	else
27259093Sdfr		map_len = round_page(offset+filsz) - trunc_page(offset);
273121129Sdfr
274121129Sdfr	if (error = vm_mmap (&vmspace->vm_map,
275121129Sdfr			     &map_addr,
276121129Sdfr			     map_len,
277121129Sdfr			     prot,
278121129Sdfr			     VM_PROT_ALL,
27959093Sdfr			     MAP_PRIVATE | MAP_FIXED,
280121129Sdfr			     (caddr_t)vp,
281121129Sdfr			     trunc_page(offset)))
282121129Sdfr		return error;
283121129Sdfr
284188063Simp	if (memsz == filsz)
285121129Sdfr		return 0;
286121129Sdfr
287186347Snwhitehorn	/*
288121129Sdfr	 * We have to map the remaining bit of the file into the kernel's
289121129Sdfr	 * memory map, allocate some anonymous memory, and copy that last
290121129Sdfr	 * bit into it. The remaining space should be .bss...
29159093Sdfr	 */
29259093Sdfr	copy_len = (offset + filsz) - trunc_page(offset + filsz);
29359093Sdfr	map_addr = trunc_page(vmaddr + filsz);
29459093Sdfr	map_len = round_page(vmaddr + memsz) - map_addr;
29559093Sdfr
29659093Sdfr        if (map_len != 0) {
29759093Sdfr		if (error = vm_map_find(&vmspace->vm_map, NULL, 0,
29859093Sdfr					&map_addr, map_len, FALSE,
29959093Sdfr					VM_PROT_ALL, VM_PROT_ALL,0))
30059093Sdfr			return error;
30159093Sdfr	}
30259093Sdfr
30369781Sdwmalone	if (error = vm_mmap(kernel_map,
30459093Sdfr			    (vm_offset_t *)&data_buf,
305188063Simp			    PAGE_SIZE,
30659093Sdfr			    VM_PROT_READ,
30759093Sdfr			    VM_PROT_READ,
30859093Sdfr			    0,
30959093Sdfr			    (caddr_t)vp,
31059093Sdfr			    trunc_page(offset + filsz)))
31159093Sdfr		return error;
31259093Sdfr
31359093Sdfr	error = copyout(data_buf, (caddr_t)map_addr, copy_len);
314186347Snwhitehorn
315121129Sdfr        vm_map_remove(kernel_map, (vm_offset_t)data_buf,
316186347Snwhitehorn		      (vm_offset_t)data_buf + PAGE_SIZE);
317121129Sdfr
31859093Sdfr	/*
31959093Sdfr	 * set it to the specified protection
32059093Sdfr	 */
321121129Sdfr	vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len,  prot,
322121129Sdfr		       FALSE);
323121129Sdfr
324121129Sdfr	UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len);
325121129Sdfr	return error;
326121129Sdfr}
327186347Snwhitehorn
32859093Sdfrstatic int
329121129Sdfrelf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
330121129Sdfr{
33159093Sdfr	Elf32_Ehdr *hdr = NULL;
33259093Sdfr	Elf32_Phdr *phdr = NULL;
33359820Sdfr	struct nameidata nd;
334121129Sdfr	struct vmspace *vmspace = p->p_vmspace;
335186347Snwhitehorn	vm_prot_t prot = 0;
33659093Sdfr	unsigned long text_size = 0, data_size = 0;
33759093Sdfr	unsigned long text_addr = 0, data_addr = 0;
33859093Sdfr	int header_size = 0;
33959093Sdfr        int error, i;
34059093Sdfr
34159093Sdfr        NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
342121129Sdfr
34359093Sdfr	if (error = namei(&nd))
34459093Sdfr                goto fail;
34559093Sdfr
34659093Sdfr	if (nd.ni_vp == NULL) {
34759093Sdfr		error = ENOEXEC;
34859093Sdfr		goto fail;
349186347Snwhitehorn	}
350186347Snwhitehorn
35159820Sdfr	/*
352121129Sdfr	 * Check permissions, modes, uid, etc on the file, and "open" it.
353186347Snwhitehorn	 */
354121129Sdfr	error = elf_check_permissions(p, nd.ni_vp);
355121129Sdfr
35659093Sdfr	/*
35759093Sdfr	 * No longer need this, and it prevents demand paging.
358188063Simp	 */
35959093Sdfr	VOP_UNLOCK(nd.ni_vp);
36059093Sdfr
36159093Sdfr	if (error)
362                goto fail;
363
364	/*
365	 * Map in the header
366	 */
367	if (error = map_pages(nd.ni_vp, 0, (vm_offset_t *)&hdr, sizeof(hdr)))
368                goto fail;
369
370	/*
371	 * Do we have a valid ELF header ?
372	 */
373	if (error = elf_check_header(hdr, ET_DYN))
374		goto fail;
375
376	/*
377	 * ouch, need to bounds check in case user gives us a corrupted
378	 * file with an insane header size
379	 */
380	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
381		error = ENOEXEC;
382		goto fail;
383	}
384
385	header_size = hdr->e_phentsize * hdr->e_phnum;
386
387	if (error = map_pages(nd.ni_vp, hdr->e_phoff, (vm_offset_t *)&phdr,
388			         header_size))
389        	goto fail;
390
391	for (i = 0; i < hdr->e_phnum; i++) {
392		switch(phdr[i].p_type) {
393
394	   	case PT_NULL:	/* NULL section */
395	    		UPRINTF ("ELF(file) PT_NULL section\n");
396			break;
397		case PT_LOAD:	/* Loadable segment */
398		{
399	    		UPRINTF ("ELF(file) PT_LOAD section ");
400			if (phdr[i].p_flags & PF_X)
401  				prot |= VM_PROT_EXECUTE;
402			if (phdr[i].p_flags & PF_W)
403  				prot |= VM_PROT_WRITE;
404			if (phdr[i].p_flags & PF_R)
405  				prot |= VM_PROT_READ;
406
407			if (error = elf_load_section(vmspace, nd.ni_vp,
408  						     phdr[i].p_offset,
409  						     (caddr_t)phdr[i].p_vaddr +
410							(*addr),
411  						     phdr[i].p_memsz,
412  						     phdr[i].p_filesz, prot))
413				goto fail;
414
415			/*
416			 * Is this .text or .data ??
417			 *
418			 * We only handle one each of those yet XXX
419			 */
420			if (hdr->e_entry >= phdr[i].p_vaddr &&
421			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
422  				text_addr = trunc_page(phdr[i].p_vaddr+(*addr));
423  				text_size = round_page(phdr[i].p_memsz +
424						       phdr[i].p_vaddr -
425						       trunc_page(phdr[i].p_vaddr));
426				*entry=(unsigned long)hdr->e_entry+(*addr);
427	    			UPRINTF(".text <%08x,%08x> entry=%08x\n",
428					text_addr, text_size, *entry);
429			} else {
430  				data_addr = trunc_page(phdr[i].p_vaddr+(*addr));
431  				data_size = round_page(phdr[i].p_memsz +
432						       phdr[i].p_vaddr -
433						       trunc_page(phdr[i].p_vaddr));
434	    			UPRINTF(".data <%08x,%08x>\n",
435					data_addr, data_size);
436			}
437		}
438		break;
439
440	   	case PT_DYNAMIC:/* Dynamic link information */
441	    		UPRINTF ("ELF(file) PT_DYNAMIC section\n");
442			break;
443	  	case PT_INTERP:	/* Path to interpreter */
444	    		UPRINTF ("ELF(file) PT_INTERP section\n");
445			break;
446	  	case PT_NOTE:	/* Note section */
447	    		UPRINTF ("ELF(file) PT_NOTE section\n");
448			break;
449	  	case PT_SHLIB:	/* Shared lib section  */
450	    		UPRINTF ("ELF(file) PT_SHLIB section\n");
451			break;
452		case PT_PHDR: 	/* Program header table info */
453	    		UPRINTF ("ELF(file) PT_PHDR section\n");
454			break;
455		default:
456	    		UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type );
457		}
458	}
459
460fail:
461	if (phdr)
462		unmap_pages((vm_offset_t)phdr, header_size);
463	if (hdr)
464		unmap_pages((vm_offset_t)hdr, sizeof(hdr));
465
466	return error;
467}
468
469int
470exec_elf_imgact(struct image_params *imgp)
471{
472	const Elf32_Ehdr *hdr = (const Elf32_Ehdr *) imgp->image_header;
473	const Elf32_Phdr *phdr, *mapped_phdr = NULL;
474	Elf32_Auxargs *elf_auxargs = NULL;
475	struct vmspace *vmspace = imgp->proc->p_vmspace;
476	vm_prot_t prot = 0;
477	u_long text_size = 0, data_size = 0;
478	u_long text_addr = 0, data_addr = 0;
479	u_long addr, entry = 0, proghdr = 0;
480	int error, i, header_size = 0, interp_len = 0;
481	char *interp = NULL;
482	char *brand = NULL;
483	char path[MAXPATHLEN];
484
485	/*
486	 * Do we have a valid ELF header ?
487	 */
488	if (elf_check_header(hdr, ET_EXEC))
489		return -1;
490
491	/*
492	 * From here on down, we return an errno, not -1, as we've
493	 * detected an ELF file.
494	 */
495
496	/*
497	 * ouch, need to bounds check in case user gives us a corrupted
498	 * file with an insane header size
499	 */
500	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
501		return ENOEXEC;
502	}
503
504	header_size = hdr->e_phentsize * hdr->e_phnum;
505
506	if ((hdr->e_phoff > PAGE_SIZE) ||
507	    (hdr->e_phoff + header_size) > PAGE_SIZE) {
508	  	/*
509		 * Ouch ! we only get one page full of header...
510		 * Try to map it in ourselves, and see how we go.
511	   	 */
512		if (error = map_pages(imgp->vp, hdr->e_phoff,
513				(vm_offset_t *)&mapped_phdr, header_size))
514			return (error);
515		/*
516		 * Save manual mapping for cleanup
517		 */
518		phdr = mapped_phdr;
519	} else {
520		phdr = (const Elf32_Phdr*)
521		       ((const char *)imgp->image_header + hdr->e_phoff);
522	}
523
524	/*
525	 * From this point on, we may have resources that need to be freed.
526	 */
527	if (error = exec_extract_strings(imgp))
528		goto fail;
529
530	exec_new_vmspace(imgp);
531
532	for (i = 0; i < hdr->e_phnum; i++) {
533		switch(phdr[i].p_type) {
534
535	   	case PT_NULL:	/* NULL section */
536	    		UPRINTF ("ELF PT_NULL section\n");
537			break;
538		case PT_LOAD:	/* Loadable segment */
539		{
540	    		UPRINTF ("ELF PT_LOAD section ");
541			if (phdr[i].p_flags & PF_X)
542  				prot |= VM_PROT_EXECUTE;
543			if (phdr[i].p_flags & PF_W)
544  				prot |= VM_PROT_WRITE;
545			if (phdr[i].p_flags & PF_R)
546  				prot |= VM_PROT_READ;
547
548			if (error = elf_load_section(vmspace, imgp->vp,
549  						     phdr[i].p_offset,
550  						     (caddr_t)phdr[i].p_vaddr,
551  						     phdr[i].p_memsz,
552  						     phdr[i].p_filesz, prot))
553  				goto fail;
554
555			/*
556			 * Is this .text or .data ??
557			 *
558			 * We only handle one each of those yet XXX
559			 */
560			if (hdr->e_entry >= phdr[i].p_vaddr &&
561			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
562  				text_addr = trunc_page(phdr[i].p_vaddr);
563  				text_size = round_page(phdr[i].p_memsz +
564						       phdr[i].p_vaddr -
565						       text_addr);
566				entry = (u_long)hdr->e_entry;
567	    			UPRINTF(".text <%08x,%08x> entry=%08x\n",
568					text_addr, text_size, entry);
569			} else {
570  				data_addr = trunc_page(phdr[i].p_vaddr);
571  				data_size = round_page(phdr[i].p_memsz +
572						       phdr[i].p_vaddr -
573						       data_addr);
574	    			UPRINTF(".data <%08x,%08x>\n",
575					data_addr, data_size);
576			}
577		}
578		break;
579
580	   	case PT_DYNAMIC:/* Dynamic link information */
581	    		UPRINTF ("ELF PT_DYNAMIC section ??\n");
582			break;
583	  	case PT_INTERP:	/* Path to interpreter */
584	    		UPRINTF ("ELF PT_INTERP section ");
585			if (phdr[i].p_filesz > MAXPATHLEN) {
586				error = ENOEXEC;
587				goto fail;
588			}
589			interp_len = MAXPATHLEN;
590			if (error = map_pages(imgp->vp, phdr[i].p_offset,
591					 (vm_offset_t *)&interp, interp_len))
592				goto fail;
593			UPRINTF("<%s>\n", interp);
594			break;
595	  	case PT_NOTE:	/* Note section */
596	    		UPRINTF ("ELF PT_NOTE section\n");
597			break;
598	  	case PT_SHLIB:	/* Shared lib section  */
599	    		UPRINTF ("ELF PT_SHLIB section\n");
600			break;
601		case PT_PHDR: 	/* Program header table info */
602	    		UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr);
603			proghdr = phdr[i].p_vaddr;
604			break;
605		default:
606	    		UPRINTF ("ELF %d section ??\n", phdr[i].p_type);
607		}
608	}
609
610	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
611	vmspace->vm_taddr = (caddr_t)text_addr;
612	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
613	vmspace->vm_daddr = (caddr_t)data_addr;
614
615	addr = 2*MAXDSIZ; /* May depend on OS type XXX */
616
617	imgp->entry_addr = entry;
618
619	/*
620	 * So which kind (brand) of ELF binary do we have at hand
621	 * FreeBSD, Linux, SVR4 or something else ??
622	 * If its has a interpreter section try that first
623	 */
624        if (interp) {
625                for (i=0; i<MAX_BRANDS; i++) {
626                        if (elf_brand_list[i] != NULL) {
627                                if (!strcmp(interp, elf_brand_list[i]->interp_path)) {
628                                        imgp->proc->p_sysent =
629                                                elf_brand_list[i]->sysvec;
630                                        strcpy(path, elf_brand_list[i]->emul_path);
631                                        strcat(path, elf_brand_list[i]->interp_path);
632                                        UPRINTF("interpreter=<%s> %s\n",
633                                                elf_brand_list[i]->interp_path,
634                                                elf_brand_list[i]->emul_path);
635                                        break;
636                                }
637                        }
638                }
639        }
640
641	/*
642	 * If there is no interpreter, or recognition of it
643	 * failed, se if the binary is branded.
644	 */
645	if (!interp || i == MAX_BRANDS) {
646		brand = (char *)&(hdr->e_ident[EI_BRAND]);
647		for (i=0; i<MAX_BRANDS; i++) {
648			if (elf_brand_list[i] != NULL) {
649				if (!strcmp(brand, elf_brand_list[i]->brand)) {
650					imgp->proc->p_sysent = elf_brand_list[i]->sysvec;
651					if (interp) {
652						strcpy(path, elf_brand_list[i]->emul_path);
653						strcat(path, elf_brand_list[i]->interp_path);
654						UPRINTF("interpreter=<%s> %s\n",
655						elf_brand_list[i]->interp_path,
656						elf_brand_list[i]->emul_path);
657					}
658				}
659			}
660		}
661	}
662	if (i == MAX_BRANDS) {
663		uprintf("ELF binary type not known\n");
664		error = ENOEXEC;
665		goto fail;
666	}
667	if (interp) {
668                if (error = elf_load_file(imgp->proc,
669                                          path,
670                                          &addr,        /* XXX */
671                                          &imgp->entry_addr)) {
672                        uprintf("ELF interpreter %s not found\n", path);
673                        goto fail;
674                }
675	}
676
677	uprintf("Executing %s binary\n", elf_brand_list[i]->brand);
678
679	/*
680	 * Construct auxargs table (used by the fixup routine)
681	 */
682	elf_auxargs = malloc(sizeof(Elf32_Auxargs), M_TEMP, M_WAITOK);
683	elf_auxargs->execfd = -1;
684	elf_auxargs->phdr = proghdr;
685	elf_auxargs->phent = hdr->e_phentsize;
686	elf_auxargs->phnum = hdr->e_phnum;
687	elf_auxargs->pagesz = PAGE_SIZE;
688	elf_auxargs->base = addr;
689	elf_auxargs->flags = 0;
690	elf_auxargs->entry = entry;
691	elf_auxargs->trace = elf_trace;
692
693	imgp->auxargs = elf_auxargs;
694	imgp->interpreted = 0;
695
696	/* don't allow modifying the file while we run it */
697	imgp->vp->v_flag |= VTEXT;
698
699fail:
700	if (mapped_phdr)
701		unmap_pages((vm_offset_t)mapped_phdr, header_size);
702	if (interp)
703		unmap_pages((vm_offset_t)interp, interp_len);
704
705	return error;
706}
707
708static int
709elf_freebsd_fixup(int **stack_base, struct image_params *imgp)
710{
711	Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
712	int *pos;
713
714	pos = *stack_base + (imgp->argc + imgp->envc + 2);
715
716	if (args->trace) {
717		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
718	}
719	if (args->execfd != -1) {
720		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
721	}
722	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
723	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
724	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
725	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
726	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
727	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
728	AUXARGS_ENTRY(pos, AT_BASE, args->base);
729	AUXARGS_ENTRY(pos, AT_NULL, 0);
730
731	free(imgp->auxargs, M_TEMP);
732	imgp->auxargs = NULL;
733
734	(*stack_base)--;
735	**stack_base = (int)imgp->argc;
736	return 0;
737}
738
739/*
740 * Tell kern_execve.c about it, with a little help from the linker.
741 * Since `const' objects end up in the text segment, TEXT_SET is the
742 * correct directive to use.
743 */
744const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
745TEXT_SET(execsw_set, elf_execsw);
746
747