123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
- /* $OpenBSD: loadfile_elf.c,v 1.11 2015/05/19 20:39:12 miod Exp $ */
- /*-
- * Copyright (c) 1997 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
- * NASA Ames Research Center and by Christos Zoulas.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- /*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Ralph Campbell.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)boot.c 8.1 (Berkeley) 6/10/93
- */
- int ELFNAME(exec)(int, Elf_Ehdr *, u_long *, int);
- int
- ELFNAME(exec)(int fd, Elf_Ehdr *elf, u_long *marks, int flags)
- {
- Elf_Shdr *shp;
- Elf_Phdr *phdr;
- Elf_Off off;
- int i;
- size_t sz;
- int first;
- int havesyms, havelines;
- paddr_t minp = ~0, maxp = 0, pos = 0;
- paddr_t offset = marks[MARK_START], shpp, elfp;
- sz = elf->e_phnum * sizeof(Elf_Phdr);
- phdr = ALLOC(sz);
- if (lseek(fd, (off_t)elf->e_phoff, SEEK_SET) == -1) {
- WARN(("lseek phdr"));
- FREE(phdr, sz);
- return 1;
- }
- if (read(fd, phdr, sz) != sz) {
- WARN(("read program headers"));
- FREE(phdr, sz);
- return 1;
- }
- for (first = 1, i = 0; i < elf->e_phnum; i++) {
- if (phdr[i].p_type == PT_OPENBSD_RANDOMIZE) {
- int m;
- /* Fill segment if asked for. */
- if (flags & LOAD_RANDOM) {
- for (pos = 0; pos < phdr[i].p_filesz;
- pos += m) {
- m = MIN(phdr[i].p_filesz - pos,
- sizeof(rnddata));
- BCOPY(rnddata, phdr[i].p_paddr + pos,
- m);
- }
- }
- if (flags & (LOAD_RANDOM | COUNT_RANDOM)) {
- marks[MARK_RANDOM] = LOADADDR(phdr[i].p_paddr);
- marks[MARK_ERANDOM] =
- marks[MARK_RANDOM] + phdr[i].p_filesz;
- }
- continue;
- }
- if (phdr[i].p_type != PT_LOAD ||
- (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
- continue;
- #ifdef CHECK_PHDR
- if (CHECK_PHDR(ELFSIZE, &phdr[i])) {
- FREE(phdr, sz);
- return 1;
- }
- #endif
- #define IS_TEXT(p) (p.p_flags & PF_X)
- #define IS_DATA(p) ((p.p_flags & PF_X) == 0)
- #define IS_BSS(p) (p.p_filesz < p.p_memsz)
- /*
- * XXX: Assume first address is lowest
- */
- if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) ||
- (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
- /* Read in segment. */
- PROGRESS(("%s%lu", first ? "" : "+",
- (u_long)phdr[i].p_filesz));
- if (lseek(fd, (off_t)phdr[i].p_offset, SEEK_SET) == -1) {
- WARN(("lseek text"));
- FREE(phdr, sz);
- return 1;
- }
- if (READ(fd, phdr[i].p_paddr, phdr[i].p_filesz) !=
- phdr[i].p_filesz) {
- WARN(("read text"));
- FREE(phdr, sz);
- return 1;
- }
- first = 0;
- }
- if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT | COUNT_TEXT))) ||
- (IS_DATA(phdr[i]) && (flags & (LOAD_DATA | COUNT_TEXT)))) {
- pos = phdr[i].p_paddr;
- if (minp > pos)
- minp = pos;
- pos += phdr[i].p_filesz;
- if (maxp < pos)
- maxp = pos;
- }
- /* Zero out BSS. */
- if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
- PROGRESS(("+%lu",
- (u_long)(phdr[i].p_memsz - phdr[i].p_filesz)));
- BZERO((phdr[i].p_paddr + phdr[i].p_filesz),
- phdr[i].p_memsz - phdr[i].p_filesz);
- }
- if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) {
- pos += phdr[i].p_memsz - phdr[i].p_filesz;
- if (maxp < pos)
- maxp = pos;
- }
- }
- FREE(phdr, sz);
- /*
- * Copy the ELF and section headers.
- */
- elfp = maxp = roundup(maxp, sizeof(Elf_Addr));
- if (flags & (LOAD_HDR | COUNT_HDR))
- maxp += sizeof(Elf_Ehdr);
- if (flags & (LOAD_SYM | COUNT_SYM)) {
- if (lseek(fd, (off_t)elf->e_shoff, SEEK_SET) == -1) {
- WARN(("lseek section headers"));
- return 1;
- }
- sz = elf->e_shnum * sizeof(Elf_Shdr);
- shp = ALLOC(sz);
- if (read(fd, shp, sz) != sz) {
- WARN(("read section headers"));
- FREE(shp, sz);
- return 1;
- }
- shpp = maxp;
- maxp += roundup(sz, sizeof(Elf_Addr));
- size_t shstrsz = shp[elf->e_shstrndx].sh_size;
- char *shstr = ALLOC(shstrsz);
- if (lseek(fd, (off_t)shp[elf->e_shstrndx].sh_offset, SEEK_SET) == -1) {
- WARN(("lseek section header string table"));
- FREE(shstr, shstrsz);
- FREE(shp, sz);
- return 1;
- }
- if (read(fd, shstr, shstrsz) != shstrsz) {
- WARN(("read section header string table"));
- FREE(shstr, shstrsz);
- FREE(shp, sz);
- return 1;
- }
- /*
- * Now load the symbol sections themselves. Make sure the
- * sections are aligned. Don't bother with string tables if
- * there are no symbol sections.
- */
- off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(Elf_Addr));
- for (havesyms = havelines = i = 0; i < elf->e_shnum; i++)
- if (shp[i].sh_type == SHT_SYMTAB)
- havesyms = 1;
- for (first = 1, i = 0; i < elf->e_shnum; i++) {
- if (shp[i].sh_type == SHT_SYMTAB ||
- shp[i].sh_type == SHT_STRTAB ||
- !strcmp(shstr + shp[i].sh_name, ".debug_line")) {
- if (havesyms && (flags & LOAD_SYM)) {
- PROGRESS(("%s%ld", first ? " [" : "+",
- (u_long)shp[i].sh_size));
- if (lseek(fd, (off_t)shp[i].sh_offset,
- SEEK_SET) == -1) {
- WARN(("lseek symbols"));
- FREE(shstr, shstrsz);
- FREE(shp, sz);
- return 1;
- }
- if (READ(fd, maxp, shp[i].sh_size) !=
- shp[i].sh_size) {
- WARN(("read symbols"));
- FREE(shstr, shstrsz);
- FREE(shp, sz);
- return 1;
- }
- }
- maxp += roundup(shp[i].sh_size,
- sizeof(Elf_Addr));
- shp[i].sh_offset = off;
- shp[i].sh_flags |= SHF_ALLOC;
- off += roundup(shp[i].sh_size, sizeof(Elf_Addr));
- first = 0;
- }
- }
- if (flags & LOAD_SYM) {
- BCOPY(shp, shpp, sz);
- if (havesyms && first == 0)
- PROGRESS(("]"));
- }
- FREE(shstr, shstrsz);
- FREE(shp, sz);
- }
- /*
- * Frob the copied ELF header to give information relative
- * to elfp.
- */
- if (flags & LOAD_HDR) {
- elf->e_phoff = 0;
- elf->e_shoff = sizeof(Elf_Ehdr);
- elf->e_phentsize = 0;
- elf->e_phnum = 0;
- BCOPY(elf, elfp, sizeof(*elf));
- }
- marks[MARK_START] = LOADADDR(minp);
- marks[MARK_ENTRY] = LOADADDR(elf->e_entry);
- marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */
- marks[MARK_SYM] = LOADADDR(elfp);
- marks[MARK_END] = LOADADDR(maxp);
- return 0;
- }
|