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