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