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/link_elf_obj.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 /*-
    2  * Copyright (c) 1998 Doug Rabson
    3  * Copyright (c) 2004 Peter Wemm
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD: src/sys/kern/link_elf.c,v 1.24 1999/12/24 15:33:36 bde Exp $
   28  */
   29 
   30 #include <sys/param.h>
   31 #include <sys/kernel.h>
   32 #include <sys/systm.h>
   33 #include <sys/malloc.h>
   34 #include <sys/proc.h>
   35 #include <sys/nlookup.h>
   36 #include <sys/fcntl.h>
   37 #include <sys/vnode.h>
   38 #include <sys/linker.h>
   39 #include <machine/elf.h>
   40 
   41 #include <vm/vm.h>
   42 #include <vm/vm_param.h>
   43 #include <vm/vm_zone.h>
   44 #include <vm/vm_object.h>
   45 #include <vm/vm_kern.h>
   46 #include <vm/vm_extern.h>
   47 #include <sys/lock.h>
   48 #include <vm/pmap.h>
   49 #include <vm/vm_map.h>
   50 
   51 static int      link_elf_obj_preload_file(const char *, linker_file_t *);
   52 static int      link_elf_obj_preload_finish(linker_file_t);
   53 static int      link_elf_obj_load_file(const char *, linker_file_t *);
   54 static int
   55 link_elf_obj_lookup_symbol(linker_file_t, const char *,
   56                        c_linker_sym_t *);
   57 static int      link_elf_obj_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t *);
   58 static int
   59 link_elf_obj_search_symbol(linker_file_t, caddr_t value,
   60                        c_linker_sym_t * sym, long *diffp);
   61 
   62 static void     link_elf_obj_unload_file(linker_file_t);
   63 static int
   64 link_elf_obj_lookup_set(linker_file_t, const char *,
   65                     void ***, void ***, int *);
   66 static void     link_elf_obj_reloc_local(linker_file_t lf);
   67 static int elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps, Elf_Addr *);
   68 
   69 static struct linker_class_ops link_elf_obj_class_ops = {
   70         link_elf_obj_load_file,
   71         link_elf_obj_preload_file,
   72 };
   73 
   74 static struct linker_file_ops link_elf_obj_file_ops = {
   75         .lookup_symbol = link_elf_obj_lookup_symbol,
   76         .symbol_values = link_elf_obj_symbol_values,
   77         .search_symbol = link_elf_obj_search_symbol,
   78         .preload_finish = link_elf_obj_preload_finish,
   79         .unload = link_elf_obj_unload_file,
   80         .lookup_set = link_elf_obj_lookup_set,
   81 };
   82 
   83 typedef struct {
   84         void           *addr;
   85         Elf_Off         size;
   86         int             flags;
   87         int             sec;            /* Original section */
   88         char           *name;
   89 }               Elf_progent;
   90 
   91 typedef struct {
   92         Elf_Rel        *rel;
   93         int             nrel;
   94         int             sec;
   95 }               Elf_relent;
   96 
   97 typedef struct {
   98         Elf_Rela       *rela;
   99         int             nrela;
  100         int             sec;
  101 }               Elf_relaent;
  102 
  103 
  104 typedef struct elf_file {
  105         int             preloaded;
  106 
  107         caddr_t         address;        /* Relocation address */
  108         size_t          bytes;          /* Chunk size in bytes */
  109         vm_object_t     object;         /* VM object to hold file pages */
  110         Elf_Shdr       *e_shdr;
  111 
  112         Elf_progent    *progtab;
  113         int             nprogtab;
  114 
  115         Elf_relaent    *relatab;
  116         int             nrelatab;
  117 
  118         Elf_relent     *reltab;
  119         int             nreltab;
  120 
  121         Elf_Sym        *ddbsymtab;      /* The symbol table we are using */
  122         long            ddbsymcnt;      /* Number of symbols */
  123         caddr_t         ddbstrtab;      /* String table */
  124         long            ddbstrcnt;      /* number of bytes in string table */
  125 
  126         caddr_t         shstrtab;       /* Section name string table */
  127         long            shstrcnt;       /* number of bytes in string table */
  128 
  129         caddr_t         ctftab;         /* CTF table */
  130         long            ctfcnt;         /* number of bytes in CTF table */
  131         caddr_t         ctfoff;         /* CTF offset table */
  132         caddr_t         typoff;         /* Type offset table */
  133         long            typlen;         /* Number of type entries. */
  134 
  135 }              *elf_file_t;
  136 
  137 static int      relocate_file(linker_file_t lf);
  138 
  139 /*
  140  * The kernel symbol table starts here.
  141  */
  142 extern struct _dynamic _DYNAMIC;
  143 
  144 static void
  145 link_elf_obj_init(void *arg)
  146 {
  147 #if ELF_TARG_CLASS == ELFCLASS32
  148         linker_add_class("elf32", NULL, &link_elf_obj_class_ops);
  149 #else
  150         linker_add_class("elf64", NULL, &link_elf_obj_class_ops);
  151 #endif
  152 }
  153 
  154 SYSINIT(link_elf, SI_BOOT2_KLD, SI_ORDER_SECOND, link_elf_obj_init, 0);
  155 
  156 static void
  157 link_elf_obj_error(const char *file, const char *s)
  158 {
  159         kprintf("kldload: %s: %s\n", file, s);
  160 }
  161 
  162 static int
  163 link_elf_obj_preload_file(const char *filename, linker_file_t *result)
  164 {
  165         Elf_Ehdr       *hdr;
  166         Elf_Shdr       *shdr;
  167         Elf_Sym *es;
  168         caddr_t         modptr, baseptr, sizeptr;
  169         char           *type;
  170         elf_file_t      ef;
  171         linker_file_t   lf;
  172         Elf_Addr        off;
  173         int             error, i, j, pb, ra, rl, shstrindex, symstrindex, symtabindex;
  174 
  175         /*
  176          * Look to see if we have the module preloaded.
  177          */
  178         modptr = preload_search_by_name(filename);
  179         if (modptr == NULL)
  180                 return ENOENT;
  181 
  182         /* It's preloaded, check we can handle it and collect information */
  183         type = (char *)preload_search_info(modptr, MODINFO_TYPE);
  184         baseptr = preload_search_info(modptr, MODINFO_ADDR);
  185         sizeptr = preload_search_info(modptr, MODINFO_SIZE);
  186         hdr = (Elf_Ehdr *) preload_search_info(modptr, MODINFO_METADATA |
  187                                                MODINFOMD_ELFHDR);
  188         shdr = (Elf_Shdr *) preload_search_info(modptr, MODINFO_METADATA |
  189                                                 MODINFOMD_SHDR);
  190         if (type == NULL ||
  191             (strcmp(type, "elf" __XSTRING(__ELF_WORD_SIZE) " obj module") != 0 &&
  192              strcmp(type, "elf obj module") != 0)) {
  193                 return (EFTYPE);
  194         }
  195         if (baseptr == NULL || sizeptr == NULL || hdr == NULL || shdr == NULL)
  196                 return (EINVAL);
  197 
  198         ef = kmalloc(sizeof(struct elf_file), M_LINKER, M_WAITOK | M_ZERO);
  199         ef->preloaded = 1;
  200         ef->address = *(caddr_t *) baseptr;
  201         ef->bytes = 0;
  202         lf = linker_make_file(filename, ef, &link_elf_obj_file_ops);
  203         if (lf == NULL) {
  204                 kfree(ef, M_LINKER);
  205                 return ENOMEM;
  206         }
  207         lf->address = ef->address;
  208         lf->size = *(size_t *) sizeptr;
  209 
  210         if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
  211             hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
  212             hdr->e_ident[EI_VERSION] != EV_CURRENT ||
  213             hdr->e_version != EV_CURRENT ||
  214             hdr->e_type != ET_REL ||
  215             hdr->e_machine != ELF_TARG_MACH) {
  216                 error = EFTYPE;
  217                 goto out;
  218         }
  219         ef->e_shdr = shdr;
  220 
  221         /* Scan the section header for information and table sizing. */
  222         symtabindex = -1;
  223         symstrindex = -1;
  224         for (i = 0; i < hdr->e_shnum; i++) {
  225                 switch (shdr[i].sh_type) {
  226                 case SHT_PROGBITS:
  227                 case SHT_NOBITS:
  228                         ef->nprogtab++;
  229                         break;
  230                 case SHT_SYMTAB:
  231                         symtabindex = i;
  232                         symstrindex = shdr[i].sh_link;
  233                         break;
  234                 case SHT_REL:
  235                         ef->nreltab++;
  236                         break;
  237                 case SHT_RELA:
  238                         ef->nrelatab++;
  239                         break;
  240                 }
  241         }
  242 
  243         shstrindex = hdr->e_shstrndx;
  244         if (ef->nprogtab == 0 || symstrindex < 0 ||
  245             symstrindex >= hdr->e_shnum ||
  246             shdr[symstrindex].sh_type != SHT_STRTAB || shstrindex == 0 ||
  247             shstrindex >= hdr->e_shnum ||
  248             shdr[shstrindex].sh_type != SHT_STRTAB) {
  249                 error = ENOEXEC;
  250                 goto out;
  251         }
  252         /* Allocate space for tracking the load chunks */
  253         if (ef->nprogtab != 0)
  254                 ef->progtab = kmalloc(ef->nprogtab * sizeof(*ef->progtab),
  255                                      M_LINKER, M_WAITOK | M_ZERO);
  256         if (ef->nreltab != 0)
  257                 ef->reltab = kmalloc(ef->nreltab * sizeof(*ef->reltab),
  258                                     M_LINKER, M_WAITOK | M_ZERO);
  259         if (ef->nrelatab != 0)
  260                 ef->relatab = kmalloc(ef->nrelatab * sizeof(*ef->relatab),
  261                                      M_LINKER, M_WAITOK | M_ZERO);
  262         if ((ef->nprogtab != 0 && ef->progtab == NULL) ||
  263             (ef->nreltab != 0 && ef->reltab == NULL) ||
  264             (ef->nrelatab != 0 && ef->relatab == NULL)) {
  265                 error = ENOMEM;
  266                 goto out;
  267         }
  268         /* XXX, relocate the sh_addr fields saved by the loader. */
  269         off = 0;
  270         for (i = 0; i < hdr->e_shnum; i++) {
  271                 if (shdr[i].sh_addr != 0 && (off == 0 || shdr[i].sh_addr < off))
  272                         off = shdr[i].sh_addr;
  273         }
  274         for (i = 0; i < hdr->e_shnum; i++) {
  275                 if (shdr[i].sh_addr != 0)
  276                         shdr[i].sh_addr = shdr[i].sh_addr - off +
  277                                 (Elf_Addr) ef->address;
  278         }
  279 
  280         ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
  281         ef->ddbsymtab = (Elf_Sym *) shdr[symtabindex].sh_addr;
  282         ef->ddbstrcnt = shdr[symstrindex].sh_size;
  283         ef->ddbstrtab = (char *)shdr[symstrindex].sh_addr;
  284         ef->shstrcnt = shdr[shstrindex].sh_size;
  285         ef->shstrtab = (char *)shdr[shstrindex].sh_addr;
  286 
  287         /* Now fill out progtab and the relocation tables. */
  288         pb = 0;
  289         rl = 0;
  290         ra = 0;
  291         for (i = 0; i < hdr->e_shnum; i++) {
  292                 switch (shdr[i].sh_type) {
  293                 case SHT_PROGBITS:
  294                 case SHT_NOBITS:
  295                         ef->progtab[pb].addr = (void *)shdr[i].sh_addr;
  296                         if (shdr[i].sh_type == SHT_PROGBITS)
  297                                 ef->progtab[pb].name = "<<PROGBITS>>";
  298                         else
  299                                 ef->progtab[pb].name = "<<NOBITS>>";
  300                         ef->progtab[pb].size = shdr[i].sh_size;
  301                         ef->progtab[pb].sec = i;
  302                         if (ef->shstrtab && shdr[i].sh_name != 0)
  303                                 ef->progtab[pb].name =
  304                                         ef->shstrtab + shdr[i].sh_name;
  305 #if 0
  306                         if (ef->progtab[pb].name != NULL &&
  307                             !strcmp(ef->progtab[pb].name, "set_pcpu")) {
  308                                 void           *dpcpu;
  309 
  310                                 dpcpu = dpcpu_alloc(shdr[i].sh_size);
  311                                 if (dpcpu == NULL) {
  312                                         error = ENOSPC;
  313                                         goto out;
  314                                 }
  315                                 memcpy(dpcpu, ef->progtab[pb].addr,
  316                                        ef->progtab[pb].size);
  317                                 dpcpu_copy(dpcpu, shdr[i].sh_size);
  318                                 ef->progtab[pb].addr = dpcpu;
  319 #ifdef VIMAGE
  320                         } else if (ef->progtab[pb].name != NULL &&
  321                                    !strcmp(ef->progtab[pb].name, VNET_SETNAME)) {
  322                                 void           *vnet_data;
  323 
  324                                 vnet_data = vnet_data_alloc(shdr[i].sh_size);
  325                                 if (vnet_data == NULL) {
  326                                         error = ENOSPC;
  327                                         goto out;
  328                                 }
  329                                 memcpy(vnet_data, ef->progtab[pb].addr,
  330                                        ef->progtab[pb].size);
  331                                 vnet_data_copy(vnet_data, shdr[i].sh_size);
  332                                 ef->progtab[pb].addr = vnet_data;
  333 #endif
  334                         }
  335 #endif
  336                         /* Update all symbol values with the offset. */
  337                         for (j = 0; j < ef->ddbsymcnt; j++) {
  338                                 es = &ef->ddbsymtab[j];
  339                                 if (es->st_shndx != i)
  340                                         continue;
  341                                 es->st_value += (Elf_Addr) ef->progtab[pb].addr;
  342                         }
  343                         pb++;
  344                         break;
  345                 case SHT_REL:
  346                         ef->reltab[rl].rel = (Elf_Rel *) shdr[i].sh_addr;
  347                         ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
  348                         ef->reltab[rl].sec = shdr[i].sh_info;
  349                         rl++;
  350                         break;
  351                 case SHT_RELA:
  352                         ef->relatab[ra].rela = (Elf_Rela *) shdr[i].sh_addr;
  353                         ef->relatab[ra].nrela =
  354                                 shdr[i].sh_size / sizeof(Elf_Rela);
  355                         ef->relatab[ra].sec = shdr[i].sh_info;
  356                         ra++;
  357                         break;
  358                 }
  359         }
  360         if (pb != ef->nprogtab)
  361                 panic("lost progbits");
  362         if (rl != ef->nreltab)
  363                 panic("lost reltab");
  364         if (ra != ef->nrelatab)
  365                 panic("lost relatab");
  366 
  367         /* Local intra-module relocations */
  368         link_elf_obj_reloc_local(lf);
  369 
  370         *result = lf;
  371         return (0);
  372 
  373 out:
  374         /* preload not done this way */
  375         linker_file_unload(lf /* , LINKER_UNLOAD_FORCE */ );
  376         return (error);
  377 }
  378 
  379 static int
  380 link_elf_obj_preload_finish(linker_file_t lf)
  381 {
  382         int error;
  383 
  384         error = relocate_file(lf);
  385 
  386         return (error);
  387 }
  388 
  389 static int
  390 link_elf_obj_load_file(const char *filename, linker_file_t * result)
  391 {
  392         struct nlookupdata nd;
  393         struct thread  *td = curthread; /* XXX */
  394         struct proc    *p = td->td_proc;
  395         char           *pathname;
  396         struct vnode   *vp;
  397         Elf_Ehdr       *hdr;
  398         Elf_Shdr       *shdr;
  399         Elf_Sym        *es;
  400         int             nbytes, i, j;
  401         vm_offset_t     mapbase;
  402         size_t          mapsize;
  403         int             error = 0;
  404         int             resid;
  405         elf_file_t      ef;
  406         linker_file_t   lf;
  407         int             symtabindex;
  408         int             symstrindex;
  409         int             shstrindex;
  410         int             nsym;
  411         int             pb, rl, ra;
  412         int             alignmask;
  413 
  414         /* XXX Hack for firmware loading where p == NULL */
  415         if (p == NULL) {
  416                 p = &proc0;
  417         }
  418 
  419         KKASSERT(p != NULL);
  420         if (p->p_ucred == NULL) {
  421                 kprintf("link_elf_obj_load_file: cannot load '%s' from filesystem"
  422                         " this early\n", filename);
  423                 return ENOENT;
  424         }
  425         shdr = NULL;
  426         lf = NULL;
  427         mapsize = 0;
  428         hdr = NULL;
  429         pathname = linker_search_path(filename);
  430         if (pathname == NULL)
  431                 return ENOENT;
  432 
  433         error = nlookup_init(&nd, pathname, UIO_SYSSPACE, NLC_FOLLOW | NLC_LOCKVP);
  434         if (error == 0)
  435                 error = vn_open(&nd, NULL, FREAD, 0);
  436         kfree(pathname, M_LINKER);
  437         if (error) {
  438                 nlookup_done(&nd);
  439                 return error;
  440         }
  441         vp = nd.nl_open_vp;
  442         nd.nl_open_vp = NULL;
  443         nlookup_done(&nd);
  444 
  445         /*
  446          * Read the elf header from the file.
  447          */
  448         hdr = kmalloc(sizeof(*hdr), M_LINKER, M_WAITOK);
  449         error = vn_rdwr(UIO_READ, vp, (void *)hdr, sizeof(*hdr), 0,
  450                         UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
  451         if (error)
  452                 goto out;
  453         if (resid != 0) {
  454                 error = ENOEXEC;
  455                 goto out;
  456         }
  457         if (!IS_ELF(*hdr)) {
  458                 error = ENOEXEC;
  459                 goto out;
  460         }
  461 
  462         if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
  463             || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
  464                 link_elf_obj_error(filename, "Unsupported file layout");
  465                 error = ENOEXEC;
  466                 goto out;
  467         }
  468         if (hdr->e_ident[EI_VERSION] != EV_CURRENT
  469             || hdr->e_version != EV_CURRENT) {
  470                 link_elf_obj_error(filename, "Unsupported file version");
  471                 error = ENOEXEC;
  472                 goto out;
  473         }
  474         if (hdr->e_type != ET_REL) {
  475                 error = ENOSYS;
  476                 goto out;
  477         }
  478         if (hdr->e_machine != ELF_TARG_MACH) {
  479                 link_elf_obj_error(filename, "Unsupported machine");
  480                 error = ENOEXEC;
  481                 goto out;
  482         }
  483 
  484         ef = kmalloc(sizeof(struct elf_file), M_LINKER, M_WAITOK | M_ZERO);
  485         lf = linker_make_file(filename, ef, &link_elf_obj_file_ops);
  486         if (lf == NULL) {
  487                 kfree(ef, M_LINKER);
  488                 error = ENOMEM;
  489                 goto out;
  490         }
  491         ef->nprogtab = 0;
  492         ef->e_shdr = NULL;
  493         ef->nreltab = 0;
  494         ef->nrelatab = 0;
  495 
  496         /* Allocate and read in the section header */
  497         nbytes = hdr->e_shnum * hdr->e_shentsize;
  498         if (nbytes == 0 || hdr->e_shoff == 0 ||
  499             hdr->e_shentsize != sizeof(Elf_Shdr)) {
  500                 error = ENOEXEC;
  501                 goto out;
  502         }
  503         shdr = kmalloc(nbytes, M_LINKER, M_WAITOK);
  504         ef->e_shdr = shdr;
  505         error = vn_rdwr(UIO_READ, vp, (caddr_t) shdr, nbytes, hdr->e_shoff,
  506                         UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
  507         if (error)
  508                 goto out;
  509         if (resid) {
  510                 error = ENOEXEC;
  511                 goto out;
  512         }
  513         /* Scan the section header for information and table sizing. */
  514         nsym = 0;
  515         symtabindex = -1;
  516         symstrindex = -1;
  517         for (i = 0; i < hdr->e_shnum; i++) {
  518                 switch (shdr[i].sh_type) {
  519                 case SHT_PROGBITS:
  520                 case SHT_NOBITS:
  521                         ef->nprogtab++;
  522                         break;
  523                 case SHT_SYMTAB:
  524                         nsym++;
  525                         symtabindex = i;
  526                         symstrindex = shdr[i].sh_link;
  527                         break;
  528                 case SHT_REL:
  529                         ef->nreltab++;
  530                         break;
  531                 case SHT_RELA:
  532                         ef->nrelatab++;
  533                         break;
  534                 case SHT_STRTAB:
  535                         break;
  536                 }
  537         }
  538         if (ef->nprogtab == 0) {
  539                 link_elf_obj_error(filename, "file has no contents");
  540                 error = ENOEXEC;
  541                 goto out;
  542         }
  543         if (nsym != 1) {
  544                 /* Only allow one symbol table for now */
  545                 link_elf_obj_error(filename, "file has no valid symbol table");
  546                 error = ENOEXEC;
  547                 goto out;
  548         }
  549         if (symstrindex < 0 || symstrindex > hdr->e_shnum ||
  550             shdr[symstrindex].sh_type != SHT_STRTAB) {
  551                 link_elf_obj_error(filename, "file has invalid symbol strings");
  552                 error = ENOEXEC;
  553                 goto out;
  554         }
  555         /* Allocate space for tracking the load chunks */
  556         if (ef->nprogtab != 0)
  557                 ef->progtab = kmalloc(ef->nprogtab * sizeof(*ef->progtab),
  558                                       M_LINKER, M_WAITOK | M_ZERO);
  559         if (ef->nreltab != 0)
  560                 ef->reltab = kmalloc(ef->nreltab * sizeof(*ef->reltab),
  561                                      M_LINKER, M_WAITOK | M_ZERO);
  562         if (ef->nrelatab != 0)
  563                 ef->relatab = kmalloc(ef->nrelatab * sizeof(*ef->relatab),
  564                                       M_LINKER, M_WAITOK | M_ZERO);
  565         if ((ef->nprogtab != 0 && ef->progtab == NULL) ||
  566             (ef->nreltab != 0 && ef->reltab == NULL) ||
  567             (ef->nrelatab != 0 && ef->relatab == NULL)) {
  568                 error = ENOMEM;
  569                 goto out;
  570         }
  571         if (symtabindex == -1)
  572                 panic("lost symbol table index");
  573         /* Allocate space for and load the symbol table */
  574         ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
  575         ef->ddbsymtab = kmalloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK);
  576         error = vn_rdwr(UIO_READ, vp, (void *)ef->ddbsymtab,
  577                         shdr[symtabindex].sh_size, shdr[symtabindex].sh_offset,
  578                         UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
  579         if (error)
  580                 goto out;
  581         if (resid != 0) {
  582                 error = EINVAL;
  583                 goto out;
  584         }
  585         if (symstrindex == -1)
  586                 panic("lost symbol string index");
  587         /* Allocate space for and load the symbol strings */
  588         ef->ddbstrcnt = shdr[symstrindex].sh_size;
  589         ef->ddbstrtab = kmalloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK);
  590         error = vn_rdwr(UIO_READ, vp, ef->ddbstrtab,
  591                         shdr[symstrindex].sh_size, shdr[symstrindex].sh_offset,
  592                         UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
  593         if (error)
  594                 goto out;
  595         if (resid != 0) {
  596                 error = EINVAL;
  597                 goto out;
  598         }
  599         /* Do we have a string table for the section names?  */
  600         shstrindex = -1;
  601         if (hdr->e_shstrndx != 0 &&
  602             shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
  603                 shstrindex = hdr->e_shstrndx;
  604                 ef->shstrcnt = shdr[shstrindex].sh_size;
  605                 ef->shstrtab = kmalloc(shdr[shstrindex].sh_size, M_LINKER,
  606                                        M_WAITOK);
  607                 error = vn_rdwr(UIO_READ, vp, ef->shstrtab,
  608                                 shdr[shstrindex].sh_size, shdr[shstrindex].sh_offset,
  609                                 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
  610                 if (error)
  611                         goto out;
  612                 if (resid != 0) {
  613                         error = EINVAL;
  614                         goto out;
  615                 }
  616         }
  617         /* Size up code/data(progbits) and bss(nobits). */
  618         alignmask = 0;
  619         for (i = 0; i < hdr->e_shnum; i++) {
  620                 switch (shdr[i].sh_type) {
  621                 case SHT_PROGBITS:
  622                 case SHT_NOBITS:
  623                         alignmask = shdr[i].sh_addralign - 1;
  624                         mapsize += alignmask;
  625                         mapsize &= ~alignmask;
  626                         mapsize += shdr[i].sh_size;
  627                         break;
  628                 }
  629         }
  630 
  631         /*
  632          * We know how much space we need for the text/data/bss/etc. This
  633          * stuff needs to be in a single chunk so that profiling etc can get
  634          * the bounds and gdb can associate offsets with modules
  635          */
  636         ef->object = vm_object_allocate(OBJT_DEFAULT,
  637                                         round_page(mapsize) >> PAGE_SHIFT);
  638         if (ef->object == NULL) {
  639                 error = ENOMEM;
  640                 goto out;
  641         }
  642         vm_object_hold(ef->object);
  643         vm_object_reference_locked(ef->object);
  644         ef->address = (caddr_t) vm_map_min(&kernel_map);
  645         ef->bytes = 0;
  646 
  647         /*
  648          * In order to satisfy x86_64's architectural requirements on the
  649          * location of code and data in the kernel's address space, request a
  650          * mapping that is above the kernel.
  651          *
  652          * vkernel64's text+data is outside the managed VM space entirely.
  653          */
  654 #if defined(__x86_64__) && defined(_KERNEL_VIRTUAL)
  655         error = vkernel_module_memory_alloc(&mapbase, round_page(mapsize));
  656         vm_object_drop(ef->object);
  657 #else
  658         mapbase = KERNBASE;
  659         error = vm_map_find(&kernel_map, ef->object, 0, &mapbase,
  660                             round_page(mapsize), PAGE_SIZE,
  661                             TRUE, VM_MAPTYPE_NORMAL,
  662                             VM_PROT_ALL, VM_PROT_ALL, FALSE);
  663         vm_object_drop(ef->object);
  664         if (error) {
  665                 vm_object_deallocate(ef->object);
  666                 ef->object = NULL;
  667                 goto out;
  668         }
  669         /* Wire the pages */
  670         error = vm_map_wire(&kernel_map, mapbase,
  671                             mapbase + round_page(mapsize), 0);
  672 #endif
  673         if (error != KERN_SUCCESS) {
  674                 error = ENOMEM;
  675                 goto out;
  676         }
  677         /* Inform the kld system about the situation */
  678         lf->address = ef->address = (caddr_t) mapbase;
  679         lf->size = round_page(mapsize);
  680         ef->bytes = mapsize;
  681 
  682         /*
  683          * Now load code/data(progbits), zero bss(nobits), allocate space for
  684          * and load relocs
  685          */
  686         pb = 0;
  687         rl = 0;
  688         ra = 0;
  689         alignmask = 0;
  690         for (i = 0; i < hdr->e_shnum; i++) {
  691                 switch (shdr[i].sh_type) {
  692                 case SHT_PROGBITS:
  693                 case SHT_NOBITS:
  694                         alignmask = shdr[i].sh_addralign - 1;
  695                         mapbase += alignmask;
  696                         mapbase &= ~alignmask;
  697                         if (ef->shstrtab && shdr[i].sh_name != 0)
  698                                 ef->progtab[pb].name =
  699                                         ef->shstrtab + shdr[i].sh_name;
  700                         else if (shdr[i].sh_type == SHT_PROGBITS)
  701                                 ef->progtab[pb].name = "<<PROGBITS>>";
  702                         else
  703                                 ef->progtab[pb].name = "<<NOBITS>>";
  704 #if 0
  705                         if (ef->progtab[pb].name != NULL &&
  706                             !strcmp(ef->progtab[pb].name, "set_pcpu"))
  707                                 ef->progtab[pb].addr =
  708                                         dpcpu_alloc(shdr[i].sh_size);
  709 #ifdef VIMAGE
  710                         else if (ef->progtab[pb].name != NULL &&
  711                                  !strcmp(ef->progtab[pb].name, VNET_SETNAME))
  712                                 ef->progtab[pb].addr =
  713                                         vnet_data_alloc(shdr[i].sh_size);
  714 #endif
  715                         else
  716 #endif
  717                                 ef->progtab[pb].addr =
  718                                         (void *)(uintptr_t) mapbase;
  719                         if (ef->progtab[pb].addr == NULL) {
  720                                 error = ENOSPC;
  721                                 goto out;
  722                         }
  723                         ef->progtab[pb].size = shdr[i].sh_size;
  724                         ef->progtab[pb].sec = i;
  725                         if (shdr[i].sh_type == SHT_PROGBITS) {
  726                                 error = vn_rdwr(UIO_READ, vp,
  727                                                 ef->progtab[pb].addr,
  728                                                 shdr[i].sh_size, shdr[i].sh_offset,
  729                                                 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
  730                                                 &resid);
  731                                 if (error)
  732                                         goto out;
  733                                 if (resid != 0) {
  734                                         error = EINVAL;
  735                                         goto out;
  736                                 }
  737 #if 0
  738                                 /* Initialize the per-cpu or vnet area. */
  739                                 if (ef->progtab[pb].addr != (void *)mapbase &&
  740                                     !strcmp(ef->progtab[pb].name, "set_pcpu"))
  741                                         dpcpu_copy(ef->progtab[pb].addr,
  742                                                    shdr[i].sh_size);
  743 #ifdef VIMAGE
  744                                 else if (ef->progtab[pb].addr !=
  745                                          (void *)mapbase &&
  746                                          !strcmp(ef->progtab[pb].name, VNET_SETNAME))
  747                                         vnet_data_copy(ef->progtab[pb].addr,
  748                                                        shdr[i].sh_size);
  749 #endif
  750 #endif
  751                         } else
  752                                 bzero(ef->progtab[pb].addr, shdr[i].sh_size);
  753 
  754                         /* Update all symbol values with the offset. */
  755                         for (j = 0; j < ef->ddbsymcnt; j++) {
  756                                 es = &ef->ddbsymtab[j];
  757                                 if (es->st_shndx != i)
  758                                         continue;
  759                                 es->st_value += (Elf_Addr) ef->progtab[pb].addr;
  760                         }
  761                         mapbase += shdr[i].sh_size;
  762                         pb++;
  763                         break;
  764                 case SHT_REL:
  765                         ef->reltab[rl].rel = kmalloc(shdr[i].sh_size, M_LINKER, M_WAITOK);
  766                         ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
  767                         ef->reltab[rl].sec = shdr[i].sh_info;
  768                         error = vn_rdwr(UIO_READ, vp,
  769                                         (void *)ef->reltab[rl].rel,
  770                                         shdr[i].sh_size, shdr[i].sh_offset,
  771                                         UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
  772                         if (error)
  773                                 goto out;
  774                         if (resid != 0) {
  775                                 error = EINVAL;
  776                                 goto out;
  777                         }
  778                         rl++;
  779                         break;
  780                 case SHT_RELA:
  781                         ef->relatab[ra].rela = kmalloc(shdr[i].sh_size, M_LINKER, M_WAITOK);
  782                         ef->relatab[ra].nrela = shdr[i].sh_size / sizeof(Elf_Rela);
  783                         ef->relatab[ra].sec = shdr[i].sh_info;
  784                         error = vn_rdwr(UIO_READ, vp,
  785                                         (void *)ef->relatab[ra].rela,
  786                                         shdr[i].sh_size, shdr[i].sh_offset,
  787                                         UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
  788                         if (error)
  789                                 goto out;
  790                         if (resid != 0) {
  791                                 error = EINVAL;
  792                                 goto out;
  793                         }
  794                         ra++;
  795                         break;
  796                 }
  797         }
  798         if (pb != ef->nprogtab)
  799                 panic("lost progbits");
  800         if (rl != ef->nreltab)
  801                 panic("lost reltab");
  802         if (ra != ef->nrelatab)
  803                 panic("lost relatab");
  804         if (mapbase != (vm_offset_t) ef->address + mapsize)
  805                 panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)",
  806                       mapbase, ef->address, mapsize,
  807                       (vm_offset_t) ef->address + mapsize);
  808 
  809         /* Local intra-module relocations */
  810         link_elf_obj_reloc_local(lf);
  811 
  812         /* Pull in dependencies */
  813         error = linker_load_dependencies(lf);
  814         if (error)
  815                 goto out;
  816 
  817         /* External relocations */
  818         error = relocate_file(lf);
  819         if (error)
  820                 goto out;
  821 
  822         *result = lf;
  823 
  824 out:
  825         if (error && lf)
  826                 linker_file_unload(lf /*, LINKER_UNLOAD_FORCE */);
  827         if (hdr)
  828                 kfree(hdr, M_LINKER);
  829         vn_unlock(vp);
  830         vn_close(vp, FREAD);
  831 
  832         return error;
  833 }
  834 
  835 static void
  836 link_elf_obj_unload_file(linker_file_t file)
  837 {
  838         elf_file_t      ef = file->priv;
  839         int i;
  840 
  841         if (ef->progtab) {
  842                 for (i = 0; i < ef->nprogtab; i++) {
  843                         if (ef->progtab[i].size == 0)
  844                                 continue;
  845                         if (ef->progtab[i].name == NULL)
  846                                 continue;
  847 #if 0
  848                         if (!strcmp(ef->progtab[i].name, "set_pcpu"))
  849                                 dpcpu_free(ef->progtab[i].addr,
  850                                     ef->progtab[i].size);
  851 #ifdef VIMAGE
  852                         else if (!strcmp(ef->progtab[i].name, VNET_SETNAME))
  853                                 vnet_data_free(ef->progtab[i].addr,
  854                                     ef->progtab[i].size);
  855 #endif
  856 #endif
  857                 }
  858         }
  859         if (ef->preloaded) {
  860                 if (ef->reltab)
  861                         kfree(ef->reltab, M_LINKER);
  862                 if (ef->relatab)
  863                         kfree(ef->relatab, M_LINKER);
  864                 if (ef->progtab)
  865                         kfree(ef->progtab, M_LINKER);
  866                 if (ef->ctftab)
  867                         kfree(ef->ctftab, M_LINKER);
  868                 if (ef->ctfoff)
  869                         kfree(ef->ctfoff, M_LINKER);
  870                 if (ef->typoff)
  871                         kfree(ef->typoff, M_LINKER);
  872                 if (file->filename != NULL)
  873                         preload_delete_name(file->filename);
  874                 kfree(ef, M_LINKER);
  875                 /* XXX reclaim module memory? */
  876                 return;
  877         }
  878 
  879         for (i = 0; i < ef->nreltab; i++)
  880                 if (ef->reltab[i].rel)
  881                         kfree(ef->reltab[i].rel, M_LINKER);
  882         for (i = 0; i < ef->nrelatab; i++)
  883                 if (ef->relatab[i].rela)
  884                         kfree(ef->relatab[i].rela, M_LINKER);
  885         if (ef->reltab)
  886                 kfree(ef->reltab, M_LINKER);
  887         if (ef->relatab)
  888                 kfree(ef->relatab, M_LINKER);
  889         if (ef->progtab)
  890                 kfree(ef->progtab, M_LINKER);
  891 
  892         if (ef->object) {
  893 #if defined(__x86_64__) && defined(_KERNEL_VIRTUAL)
  894                 vkernel_module_memory_free((vm_offset_t)ef->address, ef->bytes);
  895 #else
  896                 vm_map_remove(&kernel_map, (vm_offset_t) ef->address,
  897                     (vm_offset_t) ef->address +
  898                     (ef->object->size << PAGE_SHIFT));
  899 #endif
  900                 vm_object_deallocate(ef->object);
  901                 ef->object = NULL;
  902         }
  903         if (ef->e_shdr)
  904                 kfree(ef->e_shdr, M_LINKER);
  905         if (ef->ddbsymtab)
  906                 kfree(ef->ddbsymtab, M_LINKER);
  907         if (ef->ddbstrtab)
  908                 kfree(ef->ddbstrtab, M_LINKER);
  909         if (ef->shstrtab)
  910                 kfree(ef->shstrtab, M_LINKER);
  911         if (ef->ctftab)
  912                 kfree(ef->ctftab, M_LINKER);
  913         if (ef->ctfoff)
  914                 kfree(ef->ctfoff, M_LINKER);
  915         if (ef->typoff)
  916                 kfree(ef->typoff, M_LINKER);
  917         kfree(ef, M_LINKER);
  918 }
  919 
  920 static const char *
  921 symbol_name(elf_file_t ef, Elf_Size r_info)
  922 {
  923         const Elf_Sym  *ref;
  924 
  925         if (ELF_R_SYM(r_info)) {
  926                 ref = ef->ddbsymtab + ELF_R_SYM(r_info);
  927                 return ef->ddbstrtab + ref->st_name;
  928         } else
  929                 return NULL;
  930 }
  931 
  932 static Elf_Addr
  933 findbase(elf_file_t ef, int sec)
  934 {
  935         int i;
  936         Elf_Addr base = 0;
  937 
  938         for (i = 0; i < ef->nprogtab; i++) {
  939                 if (sec == ef->progtab[i].sec) {
  940                         base = (Elf_Addr)ef->progtab[i].addr;
  941                         break;
  942                 }
  943         }
  944         return base;
  945 }
  946 
  947 static int
  948 relocate_file(linker_file_t lf)
  949 {
  950         elf_file_t      ef = lf->priv;
  951         const Elf_Rel *rellim;
  952         const Elf_Rel *rel;
  953         const Elf_Rela *relalim;
  954         const Elf_Rela *rela;
  955         const char *symname;
  956         const Elf_Sym *sym;
  957         int i;
  958         Elf_Size symidx;
  959         Elf_Addr base;
  960 
  961         /* Perform relocations without addend if there are any: */
  962         for (i = 0; i < ef->nreltab; i++) {
  963                 rel = ef->reltab[i].rel;
  964                 if (rel == NULL)
  965                         panic("lost a reltab!");
  966                 rellim = rel + ef->reltab[i].nrel;
  967                 base = findbase(ef, ef->reltab[i].sec);
  968                 if (base == 0)
  969                         panic("lost base for reltab");
  970                 for ( ; rel < rellim; rel++) {
  971                         symidx = ELF_R_SYM(rel->r_info);
  972                         if (symidx >= ef->ddbsymcnt)
  973                                 continue;
  974                         sym = ef->ddbsymtab + symidx;
  975                         /* Local relocs are already done */
  976                         if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
  977                                 continue;
  978                         if (elf_reloc(lf, base, rel, ELF_RELOC_REL,
  979                             elf_obj_lookup)) {
  980                                 symname = symbol_name(ef, rel->r_info);
  981                                 kprintf("link_elf_obj_obj: symbol %s undefined\n",
  982                                     symname);
  983                                 return ENOENT;
  984                         }
  985                 }
  986         }
  987 
  988         /* Perform relocations with addend if there are any: */
  989         for (i = 0; i < ef->nrelatab; i++) {
  990                 rela = ef->relatab[i].rela;
  991                 if (rela == NULL)
  992                         panic("lost a relatab!");
  993                 relalim = rela + ef->relatab[i].nrela;
  994                 base = findbase(ef, ef->relatab[i].sec);
  995                 if (base == 0)
  996                         panic("lost base for relatab");
  997                 for ( ; rela < relalim; rela++) {
  998                         symidx = ELF_R_SYM(rela->r_info);
  999                         if (symidx >= ef->ddbsymcnt)
 1000                                 continue;
 1001                         sym = ef->ddbsymtab + symidx;
 1002                         /* Local relocs are already done */
 1003                         if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
 1004                                 continue;
 1005                         if (elf_reloc(lf, base, rela, ELF_RELOC_RELA,
 1006                             elf_obj_lookup)) {
 1007                                 symname = symbol_name(ef, rela->r_info);
 1008                                 kprintf("link_elf_obj_obj: symbol %s undefined\n",
 1009                                     symname);
 1010                                 return ENOENT;
 1011                         }
 1012                 }
 1013         }
 1014 
 1015         return 0;
 1016 }
 1017 
 1018 static int
 1019 link_elf_obj_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
 1020 {
 1021         elf_file_t ef = lf->priv;
 1022         const Elf_Sym *symp;
 1023         const char *strp;
 1024         int i;
 1025 
 1026         for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
 1027                 strp = ef->ddbstrtab + symp->st_name;
 1028                 if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) {
 1029                         *sym = (c_linker_sym_t) symp;
 1030                         return 0;
 1031                 }
 1032         }
 1033         return ENOENT;
 1034 }
 1035 
 1036 static int
 1037 link_elf_obj_symbol_values(linker_file_t lf, c_linker_sym_t sym,
 1038     linker_symval_t *symval)
 1039 {
 1040         elf_file_t ef = lf->priv;
 1041         const Elf_Sym *es = (const Elf_Sym*) sym;
 1042 
 1043         if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
 1044                 symval->name = ef->ddbstrtab + es->st_name;
 1045                 symval->value = (caddr_t)es->st_value;
 1046                 symval->size = es->st_size;
 1047                 return 0;
 1048         }
 1049         return ENOENT;
 1050 }
 1051 
 1052 static int
 1053 link_elf_obj_search_symbol(linker_file_t lf, caddr_t value,
 1054     c_linker_sym_t *sym, long *diffp)
 1055 {
 1056         elf_file_t ef = lf->priv;
 1057         u_long off = (uintptr_t) (void *) value;
 1058         u_long diff = off;
 1059         u_long st_value;
 1060         const Elf_Sym *es;
 1061         const Elf_Sym *best = NULL;
 1062         int i;
 1063 
 1064         for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
 1065                 if (es->st_name == 0)
 1066                         continue;
 1067                 st_value = es->st_value;
 1068                 if (off >= st_value) {
 1069                         if (off - st_value < diff) {
 1070                                 diff = off - st_value;
 1071                                 best = es;
 1072                                 if (diff == 0)
 1073                                         break;
 1074                         } else if (off - st_value == diff) {
 1075                                 best = es;
 1076                         }
 1077                 }
 1078         }
 1079         if (best == NULL)
 1080                 *diffp = off;
 1081         else
 1082                 *diffp = diff;
 1083         *sym = (c_linker_sym_t) best;
 1084 
 1085         return 0;
 1086 }
 1087 
 1088 /*
 1089  * Look up a linker set on an ELF system.
 1090  */
 1091 static int
 1092 link_elf_obj_lookup_set(linker_file_t lf, const char *name,
 1093     void ***startp, void ***stopp, int *countp)
 1094 {
 1095         elf_file_t ef = lf->priv;
 1096         void **start, **stop;
 1097         int i, count;
 1098 
 1099         /* Relative to section number */
 1100         for (i = 0; i < ef->nprogtab; i++) {
 1101                 if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) &&
 1102                     strcmp(ef->progtab[i].name + 4, name) == 0) {
 1103                         start  = (void **)ef->progtab[i].addr;
 1104                         stop = (void **)((char *)ef->progtab[i].addr +
 1105                             ef->progtab[i].size);
 1106                         count = stop - start;
 1107                         if (startp)
 1108                                 *startp = start;
 1109                         if (stopp)
 1110                                 *stopp = stop;
 1111                         if (countp)
 1112                                 *countp = count;
 1113                         return (0);
 1114                 }
 1115         }
 1116         return (ESRCH);
 1117 }
 1118 
 1119 /*
 1120  * Symbol lookup function that can be used when the symbol index is known (ie
 1121  * in relocations). It uses the symbol index instead of doing a fully fledged
 1122  * hash table based lookup when such is valid. For example for local symbols.
 1123  * This is not only more efficient, it's also more correct. It's not always
 1124  * the case that the symbol can be found through the hash table.
 1125  */
 1126 static int
 1127 elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps, Elf_Addr *result)
 1128 {
 1129         elf_file_t ef = lf->priv;
 1130         const Elf_Sym *sym;
 1131         const char *symbol;
 1132 
 1133         /* Don't even try to lookup the symbol if the index is bogus. */
 1134         if (symidx >= ef->ddbsymcnt)
 1135                 return (ENOENT);
 1136 
 1137         sym = ef->ddbsymtab + symidx;
 1138 
 1139         /* Quick answer if there is a definition included. */
 1140         if (sym->st_shndx != SHN_UNDEF) {
 1141                 *result = sym->st_value;
 1142                 return (0);
 1143         }
 1144 
 1145         /* If we get here, then it is undefined and needs a lookup. */
 1146         switch (ELF_ST_BIND(sym->st_info)) {
 1147         case STB_LOCAL:
 1148                 /* Local, but undefined? huh? */
 1149                 return (ENOENT);
 1150 
 1151         case STB_GLOBAL:
 1152                 /* Relative to Data or Function name */
 1153                 symbol = ef->ddbstrtab + sym->st_name;
 1154 
 1155                 /* Force a lookup failure if the symbol name is bogus. */
 1156                 if (*symbol == 0)
 1157                         return (ENOENT);
 1158                 return (linker_file_lookup_symbol(lf, symbol, deps, (caddr_t *)result));
 1159 
 1160         case STB_WEAK:
 1161                 kprintf("link_elf_obj_obj: Weak symbols not supported\n");
 1162                 return (ENOENT);
 1163 
 1164         default:
 1165                 return (ENOENT);
 1166         }
 1167 }
 1168 
 1169 static void
 1170 link_elf_obj_fix_link_set(elf_file_t ef)
 1171 {
 1172         static const char startn[] = "__start_";
 1173         static const char stopn[] = "__stop_";
 1174         Elf_Sym *sym;
 1175         const char *sym_name, *linkset_name;
 1176         Elf_Addr startp, stopp;
 1177         Elf_Size symidx;
 1178         int start, i;
 1179 
 1180         startp = stopp = 0;
 1181         for (symidx = 1 /* zero entry is special */;
 1182                 symidx < ef->ddbsymcnt; symidx++) {
 1183                 sym = ef->ddbsymtab + symidx;
 1184                 if (sym->st_shndx != SHN_UNDEF)
 1185                         continue;
 1186 
 1187                 sym_name = ef->ddbstrtab + sym->st_name;
 1188                 if (strncmp(sym_name, startn, sizeof(startn) - 1) == 0) {
 1189                         start = 1;
 1190                         linkset_name = sym_name + sizeof(startn) - 1;
 1191                 }
 1192                 else if (strncmp(sym_name, stopn, sizeof(stopn) - 1) == 0) {
 1193                         start = 0;
 1194                         linkset_name = sym_name + sizeof(stopn) - 1;
 1195                 }
 1196                 else
 1197                         continue;
 1198 
 1199                 for (i = 0; i < ef->nprogtab; i++) {
 1200                         if (strcmp(ef->progtab[i].name, linkset_name) == 0) {
 1201                                 startp = (Elf_Addr)ef->progtab[i].addr;
 1202                                 stopp = (Elf_Addr)(startp + ef->progtab[i].size);
 1203                                 break;
 1204                         }
 1205                 }
 1206                 if (i == ef->nprogtab)
 1207                         continue;
 1208 
 1209                 sym->st_value = start ? startp : stopp;
 1210                 sym->st_shndx = i;
 1211         }
 1212 }
 1213 
 1214 static void
 1215 link_elf_obj_reloc_local(linker_file_t lf)
 1216 {
 1217         elf_file_t ef = lf->priv;
 1218         const Elf_Rel *rellim;
 1219         const Elf_Rel *rel;
 1220         const Elf_Rela *relalim;
 1221         const Elf_Rela *rela;
 1222         const Elf_Sym *sym;
 1223         Elf_Addr base;
 1224         int i;
 1225         Elf_Size symidx;
 1226 
 1227         link_elf_obj_fix_link_set(ef);
 1228 
 1229         /* Perform relocations without addend if there are any: */
 1230         for (i = 0; i < ef->nreltab; i++) {
 1231                 rel = ef->reltab[i].rel;
 1232                 if (rel == NULL)
 1233                         panic("lost a reltab!");
 1234                 rellim = rel + ef->reltab[i].nrel;
 1235                 base = findbase(ef, ef->reltab[i].sec);
 1236                 if (base == 0)
 1237                         panic("lost base for reltab");
 1238                 for ( ; rel < rellim; rel++) {
 1239                         symidx = ELF_R_SYM(rel->r_info);
 1240                         if (symidx >= ef->ddbsymcnt)
 1241                                 continue;
 1242                         sym = ef->ddbsymtab + symidx;
 1243                         /* Only do local relocs */
 1244                         if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
 1245                                 continue;
 1246                         elf_reloc_local(lf, base, rel, ELF_RELOC_REL,
 1247                             elf_obj_lookup);
 1248                 }
 1249         }
 1250 
 1251         /* Perform relocations with addend if there are any: */
 1252         for (i = 0; i < ef->nrelatab; i++) {
 1253                 rela = ef->relatab[i].rela;
 1254                 if (rela == NULL)
 1255                         panic("lost a relatab!");
 1256                 relalim = rela + ef->relatab[i].nrela;
 1257                 base = findbase(ef, ef->relatab[i].sec);
 1258                 if (base == 0)
 1259                         panic("lost base for relatab");
 1260                 for ( ; rela < relalim; rela++) {
 1261                         symidx = ELF_R_SYM(rela->r_info);
 1262                         if (symidx >= ef->ddbsymcnt)
 1263                                 continue;
 1264                         sym = ef->ddbsymtab + symidx;
 1265                         /* Only do local relocs */
 1266                         if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
 1267                                 continue;
 1268                         elf_reloc_local(lf, base, rela, ELF_RELOC_RELA,
 1269                             elf_obj_lookup);
 1270                 }
 1271         }
 1272 }

Cache object: 6e4288231ba6e45a8af523a48c79c8cb


[ 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.