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