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