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