root/lib/libsa/loadfile_elf.c

/* [<][>][^][v][top][bottom][index][help] */
    1 /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
    2 /* $OpenBSD: loadfile_elf.c,v 1.1 2007/05/30 01:25:43 tom Exp $ */
    3 
    4 /*-
    5  * Copyright (c) 1997 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
   10  * NASA Ames Research Center and by Christos Zoulas.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * Copyright (c) 1992, 1993
   43  *      The Regents of the University of California.  All rights reserved.
   44  *
   45  * This code is derived from software contributed to Berkeley by
   46  * Ralph Campbell.
   47  *
   48  * Redistribution and use in source and binary forms, with or without
   49  * modification, are permitted provided that the following conditions
   50  * are met:
   51  * 1. Redistributions of source code must retain the above copyright
   52  *    notice, this list of conditions and the following disclaimer.
   53  * 2. Redistributions in binary form must reproduce the above copyright
   54  *    notice, this list of conditions and the following disclaimer in the
   55  *    documentation and/or other materials provided with the distribution.
   56  * 3. Neither the name of the University nor the names of its contributors
   57  *    may be used to endorse or promote products derived from this software
   58  *    without specific prior written permission.
   59  *
   60  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   61  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   62  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   63  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   64  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   65  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   66  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   67  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   68  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   69  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   70  * SUCH DAMAGE.
   71  *
   72  *      @(#)boot.c      8.1 (Berkeley) 6/10/93
   73  */
   74 
   75 int ELFNAME(exec)(int, Elf_Ehdr *, u_long *, int);
   76 
   77 int
   78 ELFNAME(exec)(int fd, Elf_Ehdr *elf, u_long *marks, int flags)
   79 {
   80         Elf_Shdr *shp;
   81         Elf_Phdr *phdr;
   82         Elf_Off off;
   83         int i;
   84         size_t sz;
   85         int first;
   86         int havesyms;
   87         paddr_t minp = ~0, maxp = 0, pos = 0;
   88         paddr_t offset = marks[MARK_START], shpp, elfp;
   89 
   90         sz = elf->e_phnum * sizeof(Elf_Phdr);
   91         phdr = ALLOC(sz);
   92 
   93         if (lseek(fd, (off_t)elf->e_phoff, SEEK_SET) == -1)  {
   94                 WARN(("lseek phdr"));
   95                 FREE(phdr, sz);
   96                 return 1;
   97         }
   98         if (read(fd, phdr, sz) != sz) {
   99                 WARN(("read program headers"));
  100                 FREE(phdr, sz);
  101                 return 1;
  102         }
  103 
  104         for (first = 1, i = 0; i < elf->e_phnum; i++) {
  105 
  106                 if (phdr[i].p_type != PT_LOAD ||
  107                     (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
  108                         continue;
  109 
  110 #define IS_TEXT(p)      (p.p_flags & PF_X)
  111 #define IS_DATA(p)      ((p.p_flags & PF_X) == 0)
  112 #define IS_BSS(p)       (p.p_filesz < p.p_memsz)
  113                 /*
  114                  * XXX: Assume first address is lowest
  115                  */
  116                 if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) ||
  117                     (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
  118 
  119                         /* Read in segment. */
  120                         PROGRESS(("%s%lu", first ? "" : "+",
  121                             (u_long)phdr[i].p_filesz));
  122 
  123                         if (lseek(fd, (off_t)phdr[i].p_offset, SEEK_SET) == -1)  {
  124                                 WARN(("lseek text"));
  125                                 FREE(phdr, sz);
  126                                 return 1;
  127                         }
  128                         if (READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz) !=
  129                             phdr[i].p_filesz) {
  130                                 WARN(("read text"));
  131                                 FREE(phdr, sz);
  132                                 return 1;
  133                         }
  134                         first = 0;
  135 
  136                 }
  137                 if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) ||
  138                     (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_TEXT)))) {
  139                         pos = phdr[i].p_vaddr;
  140                         if (minp > pos)
  141                                 minp = pos;
  142                         pos += phdr[i].p_filesz;
  143                         if (maxp < pos)
  144                                 maxp = pos;
  145                 }
  146 
  147                 /* Zero out bss. */
  148                 if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
  149                         PROGRESS(("+%lu",
  150                             (u_long)(phdr[i].p_memsz - phdr[i].p_filesz)));
  151                         BZERO((phdr[i].p_vaddr + phdr[i].p_filesz),
  152                             phdr[i].p_memsz - phdr[i].p_filesz);
  153                 }
  154                 if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) {
  155                         pos += phdr[i].p_memsz - phdr[i].p_filesz;
  156                         if (maxp < pos)
  157                                 maxp = pos;
  158                 }
  159         }
  160         FREE(phdr, sz);
  161 
  162         /*
  163          * Copy the ELF and section headers.
  164          */
  165         elfp = maxp = roundup(maxp, sizeof(long));
  166         if (flags & (LOAD_HDR|COUNT_HDR))
  167                 maxp += sizeof(Elf_Ehdr);
  168 
  169         if (flags & (LOAD_SYM|COUNT_SYM)) {
  170                 if (lseek(fd, (off_t)elf->e_shoff, SEEK_SET) == -1)  {
  171                         WARN(("lseek section headers"));
  172                         return 1;
  173                 }
  174                 sz = elf->e_shnum * sizeof(Elf_Shdr);
  175                 shp = ALLOC(sz);
  176 
  177                 if (read(fd, shp, sz) != sz) {
  178                         WARN(("read section headers"));
  179                         FREE(shp, sz);
  180                         return 1;
  181                 }
  182 
  183                 shpp = maxp;
  184                 maxp += roundup(sz, sizeof(long));
  185 
  186                 /*
  187                  * Now load the symbol sections themselves.  Make sure the
  188                  * sections are aligned. Don't bother with string tables if
  189                  * there are no symbol sections.
  190                  */
  191                 off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(long));
  192 
  193                 for (havesyms = i = 0; i < elf->e_shnum; i++)
  194                         if (shp[i].sh_type == SHT_SYMTAB)
  195                                 havesyms = 1;
  196 
  197                 for (first = 1, i = 0; i < elf->e_shnum; i++) {
  198                         if (shp[i].sh_type == SHT_SYMTAB ||
  199                             shp[i].sh_type == SHT_STRTAB) {
  200                                 if (havesyms && (flags & LOAD_SYM)) {
  201                                         PROGRESS(("%s%ld", first ? " [" : "+",
  202                                             (u_long)shp[i].sh_size));
  203                                         if (lseek(fd, (off_t)shp[i].sh_offset,
  204                                             SEEK_SET) == -1) {
  205                                                 WARN(("lseek symbols"));
  206                                                 FREE(shp, sz);
  207                                                 return 1;
  208                                         }
  209                                         if (READ(fd, maxp, shp[i].sh_size) !=
  210                                             shp[i].sh_size) {
  211                                                 WARN(("read symbols"));
  212                                                 FREE(shp, sz);
  213                                                 return 1;
  214                                         }
  215                                 }
  216                                 maxp += roundup(shp[i].sh_size,
  217                                     sizeof(long));
  218                                 shp[i].sh_offset = off;
  219                                 off += roundup(shp[i].sh_size, sizeof(long));
  220                                 first = 0;
  221                         }
  222                 }
  223                 if (flags & LOAD_SYM) {
  224                         BCOPY(shp, shpp, sz);
  225 
  226                         if (havesyms && first == 0)
  227                                 PROGRESS(("]"));
  228                 }
  229                 FREE(shp, sz);
  230         }
  231 
  232         /*
  233          * Frob the copied ELF header to give information relative
  234          * to elfp.
  235          */
  236         if (flags & LOAD_HDR) {
  237                 elf->e_phoff = 0;
  238                 elf->e_shoff = sizeof(Elf_Ehdr);
  239                 elf->e_phentsize = 0;
  240                 elf->e_phnum = 0;
  241                 BCOPY(elf, elfp, sizeof(*elf));
  242         }
  243 
  244         marks[MARK_START] = LOADADDR(minp);
  245         marks[MARK_ENTRY] = LOADADDR(elf->e_entry);
  246         marks[MARK_NSYM] = 1;   /* XXX: Kernel needs >= 0 */
  247         marks[MARK_SYM] = LOADADDR(elfp);
  248         marks[MARK_END] = LOADADDR(maxp);
  249         return 0;
  250 }

/* [<][>][^][v][top][bottom][index][help] */