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