1 /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */ 2 /* $OpenBSD: loadfile_elf.c,v 1.10 2014/10/26 10:33:48 miod 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, havelines; 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 if (phdr[i].p_type == PT_OPENBSD_RANDOMIZE) { 99 int m; 100 101 /* Fill segment if asked for. */ 102 if (flags & LOAD_DATA) { 103 for (pos = 0; pos < phdr[i].p_filesz; 104 pos += m) { 105 m = MIN(phdr[i].p_filesz - pos, 106 sizeof(rnddata)); 107 BCOPY(rnddata, phdr[i].p_paddr + pos, 108 m); 109 } 110 } 111 continue; 112 } 113 114 if (phdr[i].p_type != PT_LOAD || 115 (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0) 116 continue; 117 118 #ifdef CHECK_PHDR 119 if (CHECK_PHDR(ELFSIZE, &phdr[i])) { 120 FREE(phdr, sz); 121 return 1; 122 } 123 #endif 124 125 #define IS_TEXT(p) (p.p_flags & PF_X) 126 #define IS_DATA(p) ((p.p_flags & PF_X) == 0) 127 #define IS_BSS(p) (p.p_filesz < p.p_memsz) 128 /* 129 * XXX: Assume first address is lowest 130 */ 131 if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || 132 (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { 133 134 /* Read in segment. */ 135 PROGRESS(("%s%lu", first ? "" : "+", 136 (u_long)phdr[i].p_filesz)); 137 138 if (lseek(fd, (off_t)phdr[i].p_offset, SEEK_SET) == -1) { 139 WARN(("lseek text")); 140 FREE(phdr, sz); 141 return 1; 142 } 143 if (READ(fd, phdr[i].p_paddr, phdr[i].p_filesz) != 144 phdr[i].p_filesz) { 145 WARN(("read text")); 146 FREE(phdr, sz); 147 return 1; 148 } 149 150 first = 0; 151 } 152 153 if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT | COUNT_TEXT))) || 154 (IS_DATA(phdr[i]) && (flags & (LOAD_DATA | COUNT_TEXT)))) { 155 pos = phdr[i].p_paddr; 156 if (minp > pos) 157 minp = pos; 158 pos += phdr[i].p_filesz; 159 if (maxp < pos) 160 maxp = pos; 161 } 162 163 /* Zero out BSS. */ 164 if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { 165 PROGRESS(("+%lu", 166 (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); 167 BZERO((phdr[i].p_paddr + phdr[i].p_filesz), 168 phdr[i].p_memsz - phdr[i].p_filesz); 169 } 170 if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { 171 pos += phdr[i].p_memsz - phdr[i].p_filesz; 172 if (maxp < pos) 173 maxp = pos; 174 } 175 } 176 FREE(phdr, sz); 177 178 /* 179 * Copy the ELF and section headers. 180 */ 181 elfp = maxp = roundup(maxp, sizeof(Elf_Addr)); 182 if (flags & (LOAD_HDR | COUNT_HDR)) 183 maxp += sizeof(Elf_Ehdr); 184 185 if (flags & (LOAD_SYM | COUNT_SYM)) { 186 if (lseek(fd, (off_t)elf->e_shoff, SEEK_SET) == -1) { 187 WARN(("lseek section headers")); 188 return 1; 189 } 190 sz = elf->e_shnum * sizeof(Elf_Shdr); 191 shp = ALLOC(sz); 192 193 if (read(fd, shp, sz) != sz) { 194 WARN(("read section headers")); 195 FREE(shp, sz); 196 return 1; 197 } 198 199 shpp = maxp; 200 maxp += roundup(sz, sizeof(Elf_Addr)); 201 202 size_t shstrsz = shp[elf->e_shstrndx].sh_size; 203 char *shstr = ALLOC(shstrsz); 204 if (lseek(fd, (off_t)shp[elf->e_shstrndx].sh_offset, SEEK_SET) == -1) { 205 WARN(("lseek section header string table")); 206 FREE(shstr, shstrsz); 207 FREE(shp, sz); 208 return 1; 209 } 210 if (read(fd, shstr, shstrsz) != shstrsz) { 211 WARN(("read section header string table")); 212 FREE(shstr, shstrsz); 213 FREE(shp, sz); 214 return 1; 215 } 216 217 /* 218 * Now load the symbol sections themselves. Make sure the 219 * sections are aligned. Don't bother with string tables if 220 * there are no symbol sections. 221 */ 222 off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(Elf_Addr)); 223 224 for (havesyms = havelines = i = 0; i < elf->e_shnum; i++) 225 if (shp[i].sh_type == SHT_SYMTAB) 226 havesyms = 1; 227 228 for (first = 1, i = 0; i < elf->e_shnum; i++) { 229 if (shp[i].sh_type == SHT_SYMTAB || 230 shp[i].sh_type == SHT_STRTAB || 231 !strcmp(shstr + shp[i].sh_name, ".debug_line")) { 232 if (havesyms && (flags & LOAD_SYM)) { 233 PROGRESS(("%s%ld", first ? " [" : "+", 234 (u_long)shp[i].sh_size)); 235 if (lseek(fd, (off_t)shp[i].sh_offset, 236 SEEK_SET) == -1) { 237 WARN(("lseek symbols")); 238 FREE(shstr, shstrsz); 239 FREE(shp, sz); 240 return 1; 241 } 242 if (READ(fd, maxp, shp[i].sh_size) != 243 shp[i].sh_size) { 244 WARN(("read symbols")); 245 FREE(shstr, shstrsz); 246 FREE(shp, sz); 247 return 1; 248 } 249 } 250 maxp += roundup(shp[i].sh_size, 251 sizeof(Elf_Addr)); 252 shp[i].sh_offset = off; 253 shp[i].sh_flags |= SHF_ALLOC; 254 off += roundup(shp[i].sh_size, sizeof(Elf_Addr)); 255 first = 0; 256 } 257 } 258 if (flags & LOAD_SYM) { 259 BCOPY(shp, shpp, sz); 260 261 if (havesyms && first == 0) 262 PROGRESS(("]")); 263 } 264 FREE(shstr, shstrsz); 265 FREE(shp, sz); 266 } 267 268 /* 269 * Frob the copied ELF header to give information relative 270 * to elfp. 271 */ 272 if (flags & LOAD_HDR) { 273 elf->e_phoff = 0; 274 elf->e_shoff = sizeof(Elf_Ehdr); 275 elf->e_phentsize = 0; 276 elf->e_phnum = 0; 277 BCOPY(elf, elfp, sizeof(*elf)); 278 } 279 280 marks[MARK_START] = LOADADDR(minp); 281 marks[MARK_ENTRY] = LOADADDR(elf->e_entry); 282 marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ 283 marks[MARK_SYM] = LOADADDR(elfp); 284 marks[MARK_END] = LOADADDR(maxp); 285 286 return 0; 287 } 288