The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/exec_elf32.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: exec_elf32.c,v 1.97.2.2 2006/03/20 17:52:29 riz Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1994, 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Christos Zoulas.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Copyright (c) 1996 Christopher G. Demetriou
   41  * All rights reserved.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  * 3. The name of the author may not be used to endorse or promote products
   52  *    derived from this software without specific prior written permission
   53  *
   54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   55  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   56  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   57  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   58  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   59  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   60  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   61  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   63  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   64  */
   65 
   66 #include <sys/cdefs.h>
   67 __KERNEL_RCSID(1, "$NetBSD: exec_elf32.c,v 1.97.2.2 2006/03/20 17:52:29 riz Exp $");
   68 
   69 /* If not included by exec_elf64.c, ELFSIZE won't be defined. */
   70 #ifndef ELFSIZE
   71 #define ELFSIZE         32
   72 #endif
   73 
   74 #include <sys/param.h>
   75 #include <sys/proc.h>
   76 #include <sys/malloc.h>
   77 #include <sys/namei.h>
   78 #include <sys/vnode.h>
   79 #include <sys/exec.h>
   80 #include <sys/exec_elf.h>
   81 #include <sys/syscall.h>
   82 #include <sys/signalvar.h>
   83 #include <sys/mount.h>
   84 #include <sys/stat.h>
   85 
   86 #include <machine/cpu.h>
   87 #include <machine/reg.h>
   88 
   89 extern const struct emul emul_netbsd;
   90 
   91 int     ELFNAME(load_file)(struct proc *, struct exec_package *, char *,
   92             struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *);
   93 void    ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *,
   94             const Elf_Phdr *, Elf_Addr *, u_long *, int *, int);
   95 
   96 int ELFNAME2(netbsd,signature)(struct proc *, struct exec_package *,
   97     Elf_Ehdr *);
   98 int ELFNAME2(netbsd,probe)(struct proc *, struct exec_package *,
   99     void *, char *, vaddr_t *);
  100 
  101 /* round up and down to page boundaries. */
  102 #define ELF_ROUND(a, b)         (((a) + (b) - 1) & ~((b) - 1))
  103 #define ELF_TRUNC(a, b)         ((a) & ~((b) - 1))
  104 
  105 #define MAXPHNUM        50
  106 
  107 /*
  108  * Copy arguments onto the stack in the normal way, but add some
  109  * extra information in case of dynamic binding.
  110  */
  111 int
  112 ELFNAME(copyargs)(struct proc *p, struct exec_package *pack,
  113     struct ps_strings *arginfo, char **stackp, void *argp)
  114 {
  115         size_t len;
  116         AuxInfo ai[ELF_AUX_ENTRIES], *a;
  117         struct elf_args *ap;
  118         int error;
  119 
  120         if ((error = copyargs(p, pack, arginfo, stackp, argp)) != 0)
  121                 return error;
  122 
  123         a = ai;
  124 
  125         /*
  126          * Push extra arguments on the stack needed by dynamically
  127          * linked binaries
  128          */
  129         if ((ap = (struct elf_args *)pack->ep_emul_arg)) {
  130                 struct vattr *vap = pack->ep_vap;
  131 
  132                 a->a_type = AT_PHDR;
  133                 a->a_v = ap->arg_phaddr;
  134                 a++;
  135 
  136                 a->a_type = AT_PHENT;
  137                 a->a_v = ap->arg_phentsize;
  138                 a++;
  139 
  140                 a->a_type = AT_PHNUM;
  141                 a->a_v = ap->arg_phnum;
  142                 a++;
  143 
  144                 a->a_type = AT_PAGESZ;
  145                 a->a_v = PAGE_SIZE;
  146                 a++;
  147 
  148                 a->a_type = AT_BASE;
  149                 a->a_v = ap->arg_interp;
  150                 a++;
  151 
  152                 a->a_type = AT_FLAGS;
  153                 a->a_v = 0;
  154                 a++;
  155 
  156                 a->a_type = AT_ENTRY;
  157                 a->a_v = ap->arg_entry;
  158                 a++;
  159 
  160                 a->a_type = AT_EUID;
  161                 if (vap->va_mode & S_ISUID)
  162                         a->a_v = vap->va_uid;
  163                 else
  164                         a->a_v = p->p_ucred->cr_uid;
  165                 a++;
  166 
  167                 a->a_type = AT_RUID;
  168                 a->a_v = p->p_cred->p_ruid;
  169                 a++;
  170 
  171                 a->a_type = AT_EGID;
  172                 if (vap->va_mode & S_ISGID)
  173                         a->a_v = vap->va_gid;
  174                 else
  175                         a->a_v = p->p_ucred->cr_gid;
  176                 a++;
  177 
  178                 a->a_type = AT_RGID;
  179                 a->a_v = p->p_cred->p_rgid;
  180                 a++;
  181 
  182                 free(ap, M_TEMP);
  183                 pack->ep_emul_arg = NULL;
  184         }
  185 
  186         a->a_type = AT_NULL;
  187         a->a_v = 0;
  188         a++;
  189 
  190         len = (a - ai) * sizeof(AuxInfo);
  191         if ((error = copyout(ai, *stackp, len)) != 0)
  192                 return error;
  193         *stackp += len;
  194 
  195         return 0;
  196 }
  197 
  198 /*
  199  * elf_check_header():
  200  *
  201  * Check header for validity; return 0 of ok ENOEXEC if error
  202  */
  203 int
  204 ELFNAME(check_header)(Elf_Ehdr *eh, int type)
  205 {
  206 
  207         if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0 ||
  208             eh->e_ident[EI_CLASS] != ELFCLASS)
  209                 return (ENOEXEC);
  210 
  211         switch (eh->e_machine) {
  212 
  213         ELFDEFNNAME(MACHDEP_ID_CASES)
  214 
  215         default:
  216                 return (ENOEXEC);
  217         }
  218 
  219         if (ELF_EHDR_FLAGS_OK(eh) == 0)
  220                 return (ENOEXEC);
  221 
  222         if (eh->e_type != type)
  223                 return (ENOEXEC);
  224 
  225         if (eh->e_shnum > 1024 ||
  226             eh->e_phnum > 128)
  227                 return (ENOEXEC);
  228 
  229         return (0);
  230 }
  231 
  232 /*
  233  * elf_load_psection():
  234  *
  235  * Load a psection at the appropriate address
  236  */
  237 void
  238 ELFNAME(load_psection)(struct exec_vmcmd_set *vcset, struct vnode *vp,
  239     const Elf_Phdr *ph, Elf_Addr *addr, u_long *size, int *prot, int flags)
  240 {
  241         u_long msize, psize, rm, rf;
  242         long diff, offset;
  243 
  244         /*
  245          * If the user specified an address, then we load there.
  246          */
  247         if (*addr == ELFDEFNNAME(NO_ADDR))
  248                 *addr = ph->p_vaddr;
  249 
  250         if (ph->p_align > 1) {
  251                 /*
  252                  * Make sure we are virtually aligned as we are supposed to be.
  253                  */
  254                 diff = ph->p_vaddr - ELF_TRUNC(ph->p_vaddr, ph->p_align);
  255                 KASSERT(*addr - diff == ELF_TRUNC(*addr, ph->p_align));
  256                 /*
  257                  * But make sure to not map any pages before the start of the
  258                  * psection by limiting the difference to within a page.
  259                  */
  260                 diff &= PAGE_MASK;  
  261         } else
  262                 diff = 0;
  263 
  264         *prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0;
  265         *prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0;
  266         *prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0;
  267 
  268         /*
  269          * Adjust everything so it all starts on a page boundary.
  270          */
  271         *addr -= diff;
  272         offset = ph->p_offset - diff;
  273         *size = ph->p_filesz + diff;
  274         msize = ph->p_memsz + diff;
  275 
  276         if (ph->p_align >= PAGE_SIZE) {
  277                 if ((ph->p_flags & PF_W) != 0) {
  278                         /*
  279                          * Because the pagedvn pager can't handle zero fill
  280                          * of the last data page if it's not page aligned we
  281                          * map the last page readvn.
  282                          */
  283                         psize = trunc_page(*size);
  284                 } else {
  285                         psize = round_page(*size);
  286                 }
  287         } else {
  288                 psize = *size;
  289         }
  290 
  291         if (psize > 0) {
  292                 NEW_VMCMD2(vcset, ph->p_align < PAGE_SIZE ?
  293                     vmcmd_map_readvn : vmcmd_map_pagedvn, psize, *addr, vp,
  294                     offset, *prot, flags);
  295                 flags &= VMCMD_RELATIVE;
  296         }
  297         if (psize < *size) {
  298                 NEW_VMCMD2(vcset, vmcmd_map_readvn, *size - psize,
  299                     *addr + psize, vp, offset + psize, *prot, flags);
  300         }
  301 
  302         /*
  303          * Check if we need to extend the size of the segment (does
  304          * bss extend page the next page boundary)?
  305          */
  306         rm = round_page(*addr + msize);
  307         rf = round_page(*addr + *size);
  308 
  309         if (rm != rf) {
  310                 NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP,
  311                     0, *prot, flags & VMCMD_RELATIVE);
  312                 *size = msize;
  313         }
  314 }
  315 
  316 /*
  317  * elf_load_file():
  318  *
  319  * Load a file (interpreter/library) pointed to by path
  320  * [stolen from coff_load_shlib()]. Made slightly generic
  321  * so it might be used externally.
  322  */
  323 int
  324 ELFNAME(load_file)(struct proc *p, struct exec_package *epp, char *path,
  325     struct exec_vmcmd_set *vcset, u_long *entryoff, struct elf_args *ap,
  326     Elf_Addr *last)
  327 {
  328         int error, i;
  329         struct nameidata nd;
  330         struct vnode *vp;
  331         struct vattr attr;
  332         Elf_Ehdr eh;
  333         Elf_Phdr *ph = NULL;
  334         const Elf_Phdr *ph0;
  335         const Elf_Phdr *base_ph;
  336         const Elf_Phdr *last_ph;
  337         u_long phsize;
  338         Elf_Addr addr = *last;
  339 
  340         /*
  341          * 1. open file
  342          * 2. read filehdr
  343          * 3. map text, data, and bss out of it using VM_*
  344          */
  345         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
  346         if ((error = namei(&nd)) != 0)
  347                 return error;
  348         vp = nd.ni_vp;
  349 
  350         /*
  351          * Similarly, if it's not marked as executable, or it's not a regular
  352          * file, we don't allow it to be used.
  353          */
  354         if (vp->v_type != VREG) {
  355                 error = EACCES;
  356                 goto badunlock;
  357         }
  358         if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0)
  359                 goto badunlock;
  360 
  361         /* get attributes */
  362         if ((error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) != 0)
  363                 goto badunlock;
  364 
  365         /*
  366          * Check mount point.  Though we're not trying to exec this binary,
  367          * we will be executing code from it, so if the mount point
  368          * disallows execution or set-id-ness, we punt or kill the set-id.
  369          */
  370         if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
  371                 error = EACCES;
  372                 goto badunlock;
  373         }
  374         if (vp->v_mount->mnt_flag & MNT_NOSUID)
  375                 epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
  376 
  377 #ifdef notyet /* XXX cgd 960926 */
  378         XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?)
  379 #endif
  380 
  381         error = vn_marktext(vp);
  382         if (error)
  383                 goto badunlock;
  384 
  385         VOP_UNLOCK(vp, 0);
  386 
  387         if ((error = exec_read_from(p, vp, 0, &eh, sizeof(eh))) != 0)
  388                 goto bad;
  389 
  390         if ((error = ELFNAME(check_header)(&eh, ET_DYN)) != 0)
  391                 goto bad;
  392 
  393         if (eh.e_phnum > MAXPHNUM)
  394                 goto bad;
  395 
  396         phsize = eh.e_phnum * sizeof(Elf_Phdr);
  397         ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
  398 
  399         if ((error = exec_read_from(p, vp, eh.e_phoff, ph, phsize)) != 0)
  400                 goto bad;
  401 
  402         /*
  403          * If no position to load the interpreter was set by a probe
  404          * function, pick the same address that a non-fixed mmap(0, ..)
  405          * would (i.e. something safely out of the way).
  406          */
  407         if (*last == ELFDEFNNAME(NO_ADDR)) {
  408                 u_long limit = 0;
  409                 /*
  410                  * Find the start and ending addresses of the psections to
  411                  * be loaded.  This will give us the size.
  412                  */
  413                 for (i = 0, ph0 = ph, base_ph = NULL; i < eh.e_phnum;
  414                      i++, ph0++) {
  415                         if (ph0->p_type == PT_LOAD) {
  416                                 u_long psize = ph0->p_vaddr + ph0->p_memsz;
  417                                 if (base_ph == NULL)
  418                                         base_ph = ph0;
  419                                 if (psize > limit)
  420                                         limit = psize;
  421                         }
  422                 }
  423 
  424                 if (base_ph == NULL) {
  425                         error = ENOEXEC;
  426                         goto bad;
  427                 }
  428 
  429                 /*
  430                  * Now compute the size and load address.
  431                  */
  432                 addr = VM_DEFAULT_ADDRESS(epp->ep_daddr,
  433                     round_page(limit) - trunc_page(base_ph->p_vaddr));
  434         } else
  435                 addr = *last; /* may be ELF_LINK_ADDR */
  436 
  437         /*
  438          * Load all the necessary sections
  439          */
  440         for (i = 0, ph0 = ph, base_ph = NULL, last_ph = NULL;
  441              i < eh.e_phnum; i++, ph0++) {
  442                 switch (ph0->p_type) {
  443                 case PT_LOAD: {
  444                         u_long size;
  445                         int prot = 0;
  446                         int flags;
  447 
  448                         if (base_ph == NULL) {
  449                                 /*
  450                                  * First encountered psection is always the
  451                                  * base psection.  Make sure it's aligned
  452                                  * properly (align down for topdown and align
  453                                  * upwards for not topdown).
  454                                  */
  455                                 base_ph = ph0;
  456                                 flags = VMCMD_BASE;
  457                                 if (addr == ELF_LINK_ADDR)
  458                                         addr = ph0->p_vaddr;
  459                                 if (p->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN)
  460                                         addr = ELF_TRUNC(addr, ph0->p_align);
  461                                 else
  462                                         addr = ELF_ROUND(addr, ph0->p_align);
  463                         } else {
  464                                 u_long limit = round_page(last_ph->p_vaddr
  465                                     + last_ph->p_memsz);
  466                                 u_long base = trunc_page(ph0->p_vaddr);
  467 
  468                                 /*
  469                                  * If there is a gap in between the psections,
  470                                  * map it as inaccessible so nothing else
  471                                  * mmap'ed will be placed there.
  472                                  */
  473                                 if (limit != base) {
  474                                         NEW_VMCMD2(vcset, vmcmd_map_zero,
  475                                             base - limit,
  476                                             limit - base_ph->p_vaddr, NULLVP,
  477                                             0, VM_PROT_NONE, VMCMD_RELATIVE);
  478                                 }
  479 
  480                                 addr = ph0->p_vaddr - base_ph->p_vaddr;
  481                                 flags = VMCMD_RELATIVE;
  482                         }
  483                         last_ph = ph0;
  484                         ELFNAME(load_psection)(vcset, vp, &ph[i], &addr,
  485                             &size, &prot, flags);
  486                         /*
  487                          * If entry is within this psection then this
  488                          * must contain the .text section.  *entryoff is
  489                          * relative to the base psection.
  490                          */
  491                         if (eh.e_entry >= ph0->p_vaddr &&
  492                             eh.e_entry < (ph0->p_vaddr + size)) {
  493                                 *entryoff = eh.e_entry - base_ph->p_vaddr;
  494                         }
  495                         addr += size;
  496                         break;
  497                 }
  498 
  499                 case PT_DYNAMIC:
  500                 case PT_PHDR:
  501                 case PT_NOTE:
  502                         break;
  503 
  504                 default:
  505                         break;
  506                 }
  507         }
  508 
  509         free(ph, M_TEMP);
  510         /*
  511          * This value is ignored if TOPDOWN.
  512          */
  513         *last = addr;
  514         vrele(vp);
  515         return 0;
  516 
  517 badunlock:
  518         VOP_UNLOCK(vp, 0);
  519 
  520 bad:
  521         if (ph != NULL)
  522                 free(ph, M_TEMP);
  523 #ifdef notyet /* XXX cgd 960926 */
  524         (maybe) VOP_CLOSE it
  525 #endif
  526         vrele(vp);
  527         return error;
  528 }
  529 
  530 /*
  531  * exec_elf_makecmds(): Prepare an Elf binary's exec package
  532  *
  533  * First, set of the various offsets/lengths in the exec package.
  534  *
  535  * Then, mark the text image busy (so it can be demand paged) or error
  536  * out if this is not possible.  Finally, set up vmcmds for the
  537  * text, data, bss, and stack segments.
  538  */
  539 int
  540 ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp)
  541 {
  542         Elf_Ehdr *eh = epp->ep_hdr;
  543         Elf_Phdr *ph, *pp;
  544         Elf_Addr phdr = 0, pos = 0;
  545         int error, i, nload;
  546         char *interp = NULL;
  547         u_long phsize;
  548 
  549         if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
  550                 return ENOEXEC;
  551 
  552         /*
  553          * XXX allow for executing shared objects. It seems silly
  554          * but other ELF-based systems allow it as well.
  555          */
  556         if (ELFNAME(check_header)(eh, ET_EXEC) != 0 &&
  557             ELFNAME(check_header)(eh, ET_DYN) != 0)
  558                 return ENOEXEC;
  559 
  560         if (eh->e_phnum > MAXPHNUM)
  561                 return ENOEXEC;
  562 
  563         error = vn_marktext(epp->ep_vp);
  564         if (error)
  565                 return (error);
  566 
  567         /*
  568          * Allocate space to hold all the program headers, and read them
  569          * from the file
  570          */
  571         phsize = eh->e_phnum * sizeof(Elf_Phdr);
  572         ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
  573 
  574         if ((error = exec_read_from(p, epp->ep_vp, eh->e_phoff, ph, phsize)) !=
  575             0)
  576                 goto bad;
  577 
  578         epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR);
  579         epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR);
  580 
  581         for (i = 0; i < eh->e_phnum; i++) {
  582                 pp = &ph[i];
  583                 if (pp->p_type == PT_INTERP) {
  584                         if (pp->p_filesz >= MAXPATHLEN)
  585                                 goto bad;
  586                         MALLOC(interp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
  587                         interp[0] = '\0';
  588                         if ((error = exec_read_from(p, epp->ep_vp,
  589                             pp->p_offset, interp, pp->p_filesz)) != 0)
  590                                 goto bad;
  591                         break;
  592                 }
  593         }
  594 
  595         /*
  596          * On the same architecture, we may be emulating different systems.
  597          * See which one will accept this executable. This currently only
  598          * applies to SVR4, and IBCS2 on the i386 and Linux on the i386
  599          * and the Alpha.
  600          *
  601          * Probe functions would normally see if the interpreter (if any)
  602          * exists. Emulation packages may possibly replace the interpreter in
  603          * interp[] with a changed path (/emul/xxx/<path>).
  604          */
  605         pos = ELFDEFNNAME(NO_ADDR);
  606         if (epp->ep_esch->u.elf_probe_func) {
  607                 vaddr_t startp = (vaddr_t)pos;
  608 
  609                 error = (*epp->ep_esch->u.elf_probe_func)(p, epp, eh, interp,
  610                                                           &startp);
  611                 if (error)
  612                         goto bad;
  613                 pos = (Elf_Addr)startp;
  614         }
  615 
  616         /*
  617          * Load all the necessary sections
  618          */
  619         for (i = nload = 0; i < eh->e_phnum; i++) {
  620                 Elf_Addr  addr = ELFDEFNNAME(NO_ADDR);
  621                 u_long size = 0;
  622                 int prot = 0;
  623 
  624                 pp = &ph[i];
  625 
  626                 switch (ph[i].p_type) {
  627                 case PT_LOAD:
  628                         /*
  629                          * XXX
  630                          * Can handle only 2 sections: text and data
  631                          */
  632                         if (nload++ == 2)
  633                                 goto bad;
  634                         ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp,
  635                             &ph[i], &addr, &size, &prot, VMCMD_FIXED);
  636 
  637                         /*
  638                          * Decide whether it's text or data by looking
  639                          * at the entry point.
  640                          */
  641                         if (eh->e_entry >= addr &&
  642                             eh->e_entry < (addr + size)) {
  643                                 epp->ep_taddr = addr;
  644                                 epp->ep_tsize = size;
  645                                 if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) {
  646                                         epp->ep_daddr = addr;
  647                                         epp->ep_dsize = size;
  648                                 }
  649                         } else {
  650                                 epp->ep_daddr = addr;
  651                                 epp->ep_dsize = size;
  652                         }
  653                         break;
  654 
  655                 case PT_SHLIB:
  656                         /* SCO has these sections. */
  657                 case PT_INTERP:
  658                         /* Already did this one. */
  659                 case PT_DYNAMIC:
  660                 case PT_NOTE:
  661                         break;
  662 
  663                 case PT_PHDR:
  664                         /* Note address of program headers (in text segment) */
  665                         phdr = pp->p_vaddr;
  666                         break;
  667 
  668                 default:
  669                         /*
  670                          * Not fatal; we don't need to understand everything.
  671                          */
  672                         break;
  673                 }
  674         }
  675 
  676         /*
  677          * Check if we found a dynamically linked binary and arrange to load
  678          * its interpreter
  679          */
  680         if (interp) {
  681                 struct elf_args *ap;
  682                 int i = epp->ep_vmcmds.evs_used;
  683                 u_long interp_offset;
  684 
  685                 MALLOC(ap, struct elf_args *, sizeof(struct elf_args),
  686                     M_TEMP, M_WAITOK);
  687                 if ((error = ELFNAME(load_file)(p, epp, interp,
  688                     &epp->ep_vmcmds, &interp_offset, ap, &pos)) != 0) {
  689                         FREE(ap, M_TEMP);
  690                         goto bad;
  691                 }
  692                 ap->arg_interp = epp->ep_vmcmds.evs_cmds[i].ev_addr;
  693                 epp->ep_entry = ap->arg_interp + interp_offset;
  694                 ap->arg_phaddr = phdr;
  695 
  696                 ap->arg_phentsize = eh->e_phentsize;
  697                 ap->arg_phnum = eh->e_phnum;
  698                 ap->arg_entry = eh->e_entry;
  699 
  700                 epp->ep_emul_arg = ap;
  701 
  702                 FREE(interp, M_TEMP);
  703         } else
  704                 epp->ep_entry = eh->e_entry;
  705 
  706 #ifdef ELF_MAP_PAGE_ZERO
  707         /* Dell SVR4 maps page zero, yeuch! */
  708         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0,
  709             epp->ep_vp, 0, VM_PROT_READ);
  710 #endif
  711         free(ph, M_TEMP);
  712         return (*epp->ep_esch->es_setup_stack)(p, epp);
  713 
  714 bad:
  715         if (interp)
  716                 FREE(interp, M_TEMP);
  717         free(ph, M_TEMP);
  718         kill_vmcmds(&epp->ep_vmcmds);
  719         return ENOEXEC;
  720 }
  721 
  722 int
  723 ELFNAME2(netbsd,signature)(struct proc *p, struct exec_package *epp,
  724     Elf_Ehdr *eh)
  725 {
  726         size_t i;
  727         Elf_Phdr *ph;
  728         size_t phsize;
  729         int error;
  730 
  731         if (eh->e_phnum > MAXPHNUM)
  732                 return ENOEXEC;
  733 
  734         phsize = eh->e_phnum * sizeof(Elf_Phdr);
  735         ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
  736         error = exec_read_from(p, epp->ep_vp, eh->e_phoff, ph, phsize);
  737         if (error)
  738                 goto out;
  739 
  740         for (i = 0; i < eh->e_phnum; i++) {
  741                 Elf_Phdr *ephp = &ph[i];
  742                 Elf_Nhdr *np;
  743 
  744                 if (ephp->p_type != PT_NOTE ||
  745                     ephp->p_filesz > 1024 ||
  746                     ephp->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
  747                         continue;
  748 
  749                 np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK);
  750                 error = exec_read_from(p, epp->ep_vp, ephp->p_offset, np,
  751                     ephp->p_filesz);
  752                 if (error)
  753                         goto next;
  754 
  755                 if (np->n_type != ELF_NOTE_TYPE_NETBSD_TAG ||
  756                     np->n_namesz != ELF_NOTE_NETBSD_NAMESZ ||
  757                     np->n_descsz != ELF_NOTE_NETBSD_DESCSZ ||
  758                     memcmp((caddr_t)(np + 1), ELF_NOTE_NETBSD_NAME,
  759                     ELF_NOTE_NETBSD_NAMESZ))
  760                         goto next;
  761 
  762                 error = 0;
  763                 free(np, M_TEMP);
  764                 goto out;
  765 
  766         next:
  767                 free(np, M_TEMP);
  768                 continue;
  769         }
  770 
  771         error = ENOEXEC;
  772 out:
  773         free(ph, M_TEMP);
  774         return (error);
  775 }
  776 
  777 int
  778 ELFNAME2(netbsd,probe)(struct proc *p, struct exec_package *epp,
  779     void *eh, char *itp, vaddr_t *pos)
  780 {
  781         int error;
  782 
  783         if ((error = ELFNAME2(netbsd,signature)(p, epp, eh)) != 0)
  784                 return error;
  785 #ifdef ELF_INTERP_NON_RELOCATABLE
  786         *pos = ELF_LINK_ADDR;
  787 #endif
  788         return 0;
  789 }

Cache object: 5f4c4f21dac54525c41ce7b9c48e9b7a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.