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/lib/libsa/loadfile_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: loadfile_elf32.c,v 1.9 2003/10/23 15:06:26 he Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    9  * NASA Ames Research Center and by Christos Zoulas.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the NetBSD
   22  *      Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /* If not included by exec_elf64.c, ELFSIZE won't be defined. */
   41 #ifndef ELFSIZE
   42 #define ELFSIZE 32
   43 #endif
   44 
   45 #ifdef _STANDALONE
   46 #include <lib/libsa/stand.h>
   47 #include <lib/libkern/libkern.h>
   48 #else           
   49 #include <stdio.h>
   50 #include <string.h>
   51 #include <errno.h>
   52 #include <stdlib.h>
   53 #include <unistd.h>  
   54 #include <fcntl.h>
   55 #include <err.h>
   56 #endif  
   57 
   58 #include <sys/param.h> 
   59 #include <sys/exec.h>
   60 
   61 #include "loadfile.h"
   62 
   63 #if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \
   64     ((ELFSIZE == 64) && defined(BOOT_ELF64))
   65 
   66 #define ELFROUND        (ELFSIZE / 8)
   67 
   68 #ifndef _STANDALONE
   69 #include "byteorder.h"
   70 
   71 /*
   72  * Byte swapping may be necessary in the non-_STANDLONE case because
   73  * we may be built with a host compiler.
   74  */
   75 #define E16(f)                                                          \
   76         f = (bo == ELFDATA2LSB) ? sa_htole16(f) : sa_htobe16(f)
   77 #define E32(f)                                                          \
   78         f = (bo == ELFDATA2LSB) ? sa_htole32(f) : sa_htobe32(f)
   79 #define E64(f)                                                          \
   80         f = (bo == ELFDATA2LSB) ? sa_htole64(f) : sa_htobe64(f)
   81 
   82 #define I16(f)                                                          \
   83         f = (bo == ELFDATA2LSB) ? sa_le16toh(f) : sa_be16toh(f)
   84 #define I32(f)                                                          \
   85         f = (bo == ELFDATA2LSB) ? sa_le32toh(f) : sa_be32toh(f)
   86 #define I64(f)                                                          \
   87         f = (bo == ELFDATA2LSB) ? sa_le64toh(f) : sa_be64toh(f)
   88 
   89 static void
   90 internalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr)
   91 {
   92 
   93 #if ELFSIZE == 32
   94         I16(ehdr->e_type);
   95         I16(ehdr->e_machine);
   96         I32(ehdr->e_version);
   97         I32(ehdr->e_entry);
   98         I32(ehdr->e_phoff);
   99         I32(ehdr->e_shoff);
  100         I32(ehdr->e_flags);
  101         I16(ehdr->e_ehsize);
  102         I16(ehdr->e_phentsize);
  103         I16(ehdr->e_phnum);
  104         I16(ehdr->e_shentsize);
  105         I16(ehdr->e_shnum);
  106         I16(ehdr->e_shstrndx);
  107 #elif ELFSIZE == 64
  108         I16(ehdr->e_type);
  109         I16(ehdr->e_machine);
  110         I32(ehdr->e_version);
  111         I64(ehdr->e_entry);
  112         I64(ehdr->e_phoff);
  113         I64(ehdr->e_shoff);
  114         I32(ehdr->e_flags);
  115         I16(ehdr->e_ehsize);
  116         I16(ehdr->e_phentsize);
  117         I16(ehdr->e_phnum);
  118         I16(ehdr->e_shentsize);
  119         I16(ehdr->e_shnum);
  120         I16(ehdr->e_shstrndx);
  121 #else
  122 #error ELFSIZE is not 32 or 64
  123 #endif
  124 }
  125 
  126 static void
  127 externalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr)
  128 {
  129 
  130 #if ELFSIZE == 32
  131         E16(ehdr->e_type);
  132         E16(ehdr->e_machine);
  133         E32(ehdr->e_version);
  134         E32(ehdr->e_entry);
  135         E32(ehdr->e_phoff);
  136         E32(ehdr->e_shoff);
  137         E32(ehdr->e_flags);
  138         E16(ehdr->e_ehsize);
  139         E16(ehdr->e_phentsize);
  140         E16(ehdr->e_phnum);
  141         E16(ehdr->e_shentsize);
  142         E16(ehdr->e_shnum);
  143         E16(ehdr->e_shstrndx);
  144 #elif ELFSIZE == 64
  145         E16(ehdr->e_type);
  146         E16(ehdr->e_machine);
  147         E32(ehdr->e_version);
  148         E64(ehdr->e_entry);
  149         E64(ehdr->e_phoff);
  150         E64(ehdr->e_shoff);
  151         E32(ehdr->e_flags);
  152         E16(ehdr->e_ehsize);
  153         E16(ehdr->e_phentsize);
  154         E16(ehdr->e_phnum);
  155         E16(ehdr->e_shentsize);
  156         E16(ehdr->e_shnum);
  157         E16(ehdr->e_shstrndx);
  158 #else
  159 #error ELFSIZE is not 32 or 64
  160 #endif
  161 }
  162 
  163 static void
  164 internalize_phdr(Elf_Byte bo, Elf_Phdr *phdr)
  165 {
  166 
  167 #if ELFSIZE == 32
  168         I32(phdr->p_type);
  169         I32(phdr->p_offset);
  170         I32(phdr->p_vaddr);
  171         I32(phdr->p_paddr);
  172         I32(phdr->p_filesz);
  173         I32(phdr->p_memsz);
  174         I32(phdr->p_flags);
  175         I32(phdr->p_align);
  176 #elif ELFSIZE == 64
  177         I32(phdr->p_type);
  178         I32(phdr->p_offset);
  179         I64(phdr->p_vaddr);
  180         I64(phdr->p_paddr);
  181         I64(phdr->p_filesz);
  182         I64(phdr->p_memsz);
  183         I64(phdr->p_flags);
  184         I64(phdr->p_align);
  185 #else
  186 #error ELFSIZE is not 32 or 64
  187 #endif
  188 }
  189 
  190 static void
  191 internalize_shdr(Elf_Byte bo, Elf_Shdr *shdr)
  192 {
  193 
  194 #if ELFSIZE == 32
  195         I32(shdr->sh_name);
  196         I32(shdr->sh_type);
  197         I32(shdr->sh_flags);
  198         I32(shdr->sh_addr);
  199         I32(shdr->sh_offset);
  200         I32(shdr->sh_size);
  201         I32(shdr->sh_link);
  202         I32(shdr->sh_info);
  203         I32(shdr->sh_addralign);
  204         I32(shdr->sh_entsize);
  205 #elif ELFSIZE == 64
  206         I32(shdr->sh_name);
  207         I32(shdr->sh_type);
  208         I64(shdr->sh_flags);
  209         I64(shdr->sh_addr);
  210         I64(shdr->sh_offset);
  211         I64(shdr->sh_size);
  212         I32(shdr->sh_link);
  213         I32(shdr->sh_info);
  214         I64(shdr->sh_addralign);
  215         I64(shdr->sh_entsize);
  216 #else
  217 #error ELFSIZE is not 32 or 64
  218 #endif
  219 }
  220 
  221 static void
  222 externalize_shdr(Elf_Byte bo, Elf_Shdr *shdr)
  223 {
  224 
  225 #if ELFSIZE == 32
  226         E32(shdr->sh_name);
  227         E32(shdr->sh_type);
  228         E32(shdr->sh_flags);
  229         E32(shdr->sh_addr);
  230         E32(shdr->sh_offset);
  231         E32(shdr->sh_size);
  232         E32(shdr->sh_link);
  233         E32(shdr->sh_info);
  234         E32(shdr->sh_addralign);
  235         E32(shdr->sh_entsize);
  236 #elif ELFSIZE == 64
  237         E32(shdr->sh_name);
  238         E32(shdr->sh_type);
  239         E64(shdr->sh_flags);
  240         E64(shdr->sh_addr);
  241         E64(shdr->sh_offset);
  242         E64(shdr->sh_size);
  243         E32(shdr->sh_link);
  244         E32(shdr->sh_info);
  245         E64(shdr->sh_addralign);
  246         E64(shdr->sh_entsize);
  247 #else
  248 #error ELFSIZE is not 32 or 64
  249 #endif
  250 }
  251 #else /* _STANDALONE */
  252 /*
  253  * Byte swapping is never necessary in the _STANDALONE case because
  254  * we are being built with the target compiler.
  255  */
  256 #define internalize_ehdr(bo, ehdr)      /* nothing */
  257 #define externalize_ehdr(bo, ehdr)      /* nothing */
  258 
  259 #define internalize_phdr(bo, phdr)      /* nothing */
  260 
  261 #define internalize_shdr(bo, shdr)      /* nothing */
  262 #define externalize_shdr(bo, shdr)      /* nothing */
  263 #endif /* _STANDALONE */
  264 
  265 int
  266 ELFNAMEEND(loadfile)(fd, elf, marks, flags)
  267         int fd;
  268         Elf_Ehdr *elf;
  269         u_long *marks;
  270         int flags;
  271 {
  272         Elf_Shdr *shp;
  273         Elf_Phdr *phdr;
  274         int i, j;
  275         ssize_t sz;
  276         int first;
  277         paddr_t minp = ~0, maxp = 0, pos = 0;
  278         paddr_t offset = marks[MARK_START], shpp, elfp = 0;
  279 
  280         /* some ports dont use the offset */
  281         offset = offset;
  282 
  283         internalize_ehdr(elf->e_ident[EI_DATA], elf);
  284 
  285         sz = elf->e_phnum * sizeof(Elf_Phdr);
  286         phdr = ALLOC(sz);
  287 
  288         if (lseek(fd, elf->e_phoff, SEEK_SET) == -1)  {
  289                 WARN(("lseek phdr"));
  290                 FREE(phdr, sz);
  291                 return 1;
  292         }
  293         if (read(fd, phdr, sz) != sz) {
  294                 WARN(("read program headers"));
  295                 FREE(phdr, sz);
  296                 return 1;
  297         }
  298 
  299         for (first = 1, i = 0; i < elf->e_phnum; i++) {
  300                 internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]);
  301                 if (phdr[i].p_type != PT_LOAD ||
  302                     (phdr[i].p_flags & (PF_W|PF_X)) == 0)
  303                         continue;
  304 
  305 #define IS_TEXT(p)      (p.p_flags & PF_X)
  306 #define IS_DATA(p)      (p.p_flags & PF_W)
  307 #define IS_BSS(p)       (p.p_filesz < p.p_memsz)
  308                 /*
  309                  * XXX: Assume first address is lowest
  310                  */
  311                 if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) ||
  312                     (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
  313 
  314                         /* Read in segment. */
  315                         PROGRESS(("%s%lu", first ? "" : "+",
  316                             (u_long)phdr[i].p_filesz));
  317 
  318                         if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1)  {
  319                                 WARN(("lseek text"));
  320                                 FREE(phdr, sz);
  321                                 return 1;
  322                         }
  323                         if (READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz) !=
  324                             (ssize_t)phdr[i].p_filesz) {
  325                                 WARN(("read text"));
  326                                 FREE(phdr, sz);
  327                                 return 1;
  328                         }
  329                         first = 0;
  330 
  331                 }
  332                 if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) ||
  333                     (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_TEXT)))) {
  334                         pos = phdr[i].p_vaddr;
  335                         if (minp > pos)
  336                                 minp = pos;
  337                         pos += phdr[i].p_filesz;
  338                         if (maxp < pos)
  339                                 maxp = pos;
  340                 }
  341 
  342                 /* Zero out bss. */
  343                 if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
  344                         PROGRESS(("+%lu",
  345                             (u_long)(phdr[i].p_memsz - phdr[i].p_filesz)));
  346                         BZERO((phdr[i].p_vaddr + phdr[i].p_filesz),
  347                             phdr[i].p_memsz - phdr[i].p_filesz);
  348                 }
  349                 if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) {
  350                         pos += phdr[i].p_memsz - phdr[i].p_filesz;
  351                         if (maxp < pos)
  352                                 maxp = pos;
  353                 }
  354         }
  355         FREE(phdr, sz);
  356 
  357         /*
  358          * Copy the ELF and section headers.
  359          */
  360         maxp = roundup(maxp, ELFROUND);
  361         if (flags & (LOAD_HDR|COUNT_HDR)) {
  362                 elfp = maxp;
  363                 maxp += sizeof(Elf_Ehdr);
  364         }
  365 
  366         if (flags & (LOAD_SYM|COUNT_SYM)) {
  367                 if (lseek(fd, elf->e_shoff, SEEK_SET) == -1)  {
  368                         WARN(("lseek section headers"));
  369                         return 1;
  370                 }
  371                 sz = elf->e_shnum * sizeof(Elf_Shdr);
  372 
  373                 shp = ALLOC(sz);
  374 
  375                 if (read(fd, shp, sz) != sz) {
  376                         WARN(("read section headers"));
  377                         return 1;
  378                 }
  379 
  380                 shpp = maxp;
  381                 maxp += roundup(sz, ELFROUND);
  382 
  383 #ifndef _STANDALONE
  384                 /* Internalize the section headers. */
  385                 for (i = 0; i < elf->e_shnum; i++)
  386                         internalize_shdr(elf->e_ident[EI_DATA], &shp[i]);
  387 #endif /* ! _STANDALONE */
  388 
  389                 /*
  390                  * Now load the symbol sections themselves.  Make sure
  391                  * the sections are aligned. Don't bother with any
  392                  * string table that isn't referenced by a symbol
  393                  * table.
  394                  */
  395                 for (first = 1, i = 0; i < elf->e_shnum; i++) {
  396                         switch (shp[i].sh_type) {
  397                         case SHT_STRTAB:
  398                                 for (j = 0; j < elf->e_shnum; j++)
  399                                         if (shp[j].sh_type == SHT_SYMTAB &&
  400                                             shp[j].sh_link == (unsigned)i)
  401                                                 goto havesym;
  402                                 /* FALLTHROUGH */
  403                         default:
  404                                 /* Not loading this, so zero out the offset. */
  405                                 shp[i].sh_offset = 0;
  406                                 break;
  407                         havesym:
  408                         case SHT_SYMTAB:
  409                                 if (flags & LOAD_SYM) {
  410                                         PROGRESS(("%s%ld", first ? " [" : "+",
  411                                             (u_long)shp[i].sh_size));
  412                                         if (lseek(fd, shp[i].sh_offset,
  413                                             SEEK_SET) == -1) {
  414                                                 WARN(("lseek symbols"));
  415                                                 FREE(shp, sz);
  416                                                 return 1;
  417                                         }
  418                                         if (READ(fd, maxp, shp[i].sh_size) !=
  419                                             (ssize_t)shp[i].sh_size) {
  420                                                 WARN(("read symbols"));
  421                                                 FREE(shp, sz);
  422                                                 return 1;
  423                                         }
  424                                 }
  425                                 shp[i].sh_offset = maxp - elfp;
  426                                 maxp += roundup(shp[i].sh_size, ELFROUND);
  427                                 first = 0;
  428                         }
  429                         /* Since we don't load .shstrtab, zero the name. */
  430                         shp[i].sh_name = 0;
  431                 }
  432                 if (flags & LOAD_SYM) {
  433 #ifndef _STANDALONE
  434                         /* Externalize the section headers. */
  435                         for (i = 0; i < elf->e_shnum; i++)
  436                                 externalize_shdr(elf->e_ident[EI_DATA],
  437                                     &shp[i]);
  438 #endif /* ! _STANDALONE */
  439                         BCOPY(shp, shpp, sz);
  440 
  441                         if (first == 0)
  442                                 PROGRESS(("]"));
  443                 }
  444                 FREE(shp, sz);
  445         }
  446 
  447         /*
  448          * Frob the copied ELF header to give information relative
  449          * to elfp.
  450          */
  451         if (flags & LOAD_HDR) {
  452                 elf->e_phoff = 0;
  453                 elf->e_shoff = sizeof(Elf_Ehdr);
  454                 elf->e_phentsize = 0;
  455                 elf->e_phnum = 0;
  456                 elf->e_shstrndx = SHN_UNDEF;
  457                 externalize_ehdr(elf->e_ident[EI_DATA], elf);
  458                 BCOPY(elf, elfp, sizeof(*elf));
  459                 internalize_ehdr(elf->e_ident[EI_DATA], elf);
  460         }
  461 
  462         marks[MARK_START] = LOADADDR(minp);
  463         marks[MARK_ENTRY] = LOADADDR(elf->e_entry);
  464         /*
  465          * Since there can be more than one symbol section in the code
  466          * and we need to find strtab too in order to do anything
  467          * useful with the symbols, we just pass the whole elf
  468          * header back and we let the kernel debugger find the
  469          * location and number of symbols by itself.
  470          */
  471         marks[MARK_NSYM] = 1;   /* XXX: Kernel needs >= 0 */
  472         marks[MARK_SYM] = LOADADDR(elfp);
  473         marks[MARK_END] = LOADADDR(maxp);
  474         return 0;
  475 }
  476 
  477 #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */

Cache object: b523e52491cee76d7b81e53aacebeca4


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