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