1 /* $NetBSD: loadfile_elf32.c,v 1.6 2001/11/09 19:27:25 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center and by Christos Zoulas. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* If not included by exec_elf64.c, ELFSIZE won't be defined. */ 41 #ifndef ELFSIZE 42 #define ELFSIZE 32 43 #endif 44 45 #ifdef _STANDALONE 46 #include <lib/libsa/stand.h> 47 #include <lib/libkern/libkern.h> 48 #else 49 #include <stdio.h> 50 #include <string.h> 51 #include <errno.h> 52 #include <stdlib.h> 53 #include <unistd.h> 54 #include <fcntl.h> 55 #include <err.h> 56 #endif 57 58 #include <sys/param.h> 59 #include <sys/exec.h> 60 61 #include "loadfile.h" 62 63 #if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \ 64 ((ELFSIZE == 64) && defined(BOOT_ELF64)) 65 66 #define ELFROUND (ELFSIZE / 8) 67 68 #ifndef _STANDALONE 69 #include "byteorder.h" 70 71 /* 72 * Byte swapping may be necessary in the non-_STANDLONE case because 73 * we may be built with a host compiler. 74 */ 75 #define E16(f) \ 76 f = (bo == ELFDATA2LSB) ? sa_htole16(f) : sa_htobe16(f) 77 #define E32(f) \ 78 f = (bo == ELFDATA2LSB) ? sa_htole32(f) : sa_htobe32(f) 79 #define E64(f) \ 80 f = (bo == ELFDATA2LSB) ? sa_htole64(f) : sa_htobe64(f) 81 82 #define I16(f) \ 83 f = (bo == ELFDATA2LSB) ? sa_le16toh(f) : sa_be16toh(f) 84 #define I32(f) \ 85 f = (bo == ELFDATA2LSB) ? sa_le32toh(f) : sa_be32toh(f) 86 #define I64(f) \ 87 f = (bo == ELFDATA2LSB) ? sa_le64toh(f) : sa_be64toh(f) 88 89 static void 90 internalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr) 91 { 92 93 #if ELFSIZE == 32 94 I16(ehdr->e_type); 95 I16(ehdr->e_machine); 96 I32(ehdr->e_version); 97 I32(ehdr->e_entry); 98 I32(ehdr->e_phoff); 99 I32(ehdr->e_shoff); 100 I32(ehdr->e_flags); 101 I16(ehdr->e_ehsize); 102 I16(ehdr->e_phentsize); 103 I16(ehdr->e_phnum); 104 I16(ehdr->e_shentsize); 105 I16(ehdr->e_shnum); 106 I16(ehdr->e_shstrndx); 107 #elif ELFSIZE == 64 108 I16(ehdr->e_type); 109 I16(ehdr->e_machine); 110 I32(ehdr->e_version); 111 I64(ehdr->e_entry); 112 I64(ehdr->e_phoff); 113 I64(ehdr->e_shoff); 114 I32(ehdr->e_flags); 115 I16(ehdr->e_ehsize); 116 I16(ehdr->e_phentsize); 117 I16(ehdr->e_phnum); 118 I16(ehdr->e_shentsize); 119 I16(ehdr->e_shnum); 120 I16(ehdr->e_shstrndx); 121 #else 122 #error ELFSIZE is not 32 or 64 123 #endif 124 } 125 126 static void 127 externalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr) 128 { 129 130 #if ELFSIZE == 32 131 E16(ehdr->e_type); 132 E16(ehdr->e_machine); 133 E32(ehdr->e_version); 134 E32(ehdr->e_entry); 135 E32(ehdr->e_phoff); 136 E32(ehdr->e_shoff); 137 E32(ehdr->e_flags); 138 E16(ehdr->e_ehsize); 139 E16(ehdr->e_phentsize); 140 E16(ehdr->e_phnum); 141 E16(ehdr->e_shentsize); 142 E16(ehdr->e_shnum); 143 E16(ehdr->e_shstrndx); 144 #elif ELFSIZE == 64 145 E16(ehdr->e_type); 146 E16(ehdr->e_machine); 147 E32(ehdr->e_version); 148 E64(ehdr->e_entry); 149 E64(ehdr->e_phoff); 150 E64(ehdr->e_shoff); 151 E32(ehdr->e_flags); 152 E16(ehdr->e_ehsize); 153 E16(ehdr->e_phentsize); 154 E16(ehdr->e_phnum); 155 E16(ehdr->e_shentsize); 156 E16(ehdr->e_shnum); 157 E16(ehdr->e_shstrndx); 158 #else 159 #error ELFSIZE is not 32 or 64 160 #endif 161 } 162 163 static void 164 internalize_phdr(Elf_Byte bo, Elf_Phdr *phdr) 165 { 166 167 #if ELFSIZE == 32 168 I32(phdr->p_type); 169 I32(phdr->p_offset); 170 I32(phdr->p_vaddr); 171 I32(phdr->p_paddr); 172 I32(phdr->p_filesz); 173 I32(phdr->p_memsz); 174 I32(phdr->p_flags); 175 I32(phdr->p_align); 176 #elif ELFSIZE == 64 177 I32(phdr->p_type); 178 I32(phdr->p_offset); 179 I64(phdr->p_vaddr); 180 I64(phdr->p_paddr); 181 I64(phdr->p_filesz); 182 I64(phdr->p_memsz); 183 I64(phdr->p_flags); 184 I64(phdr->p_align); 185 #else 186 #error ELFSIZE is not 32 or 64 187 #endif 188 } 189 190 static void 191 internalize_shdr(Elf_Byte bo, Elf_Shdr *shdr) 192 { 193 194 #if ELFSIZE == 32 195 I32(shdr->sh_name); 196 I32(shdr->sh_type); 197 I32(shdr->sh_flags); 198 I32(shdr->sh_addr); 199 I32(shdr->sh_offset); 200 I32(shdr->sh_size); 201 I32(shdr->sh_link); 202 I32(shdr->sh_info); 203 I32(shdr->sh_addralign); 204 I32(shdr->sh_entsize); 205 #elif ELFSIZE == 64 206 I32(shdr->sh_name); 207 I32(shdr->sh_type); 208 I64(shdr->sh_flags); 209 I64(shdr->sh_addr); 210 I64(shdr->sh_offset); 211 I64(shdr->sh_size); 212 I32(shdr->sh_link); 213 I32(shdr->sh_info); 214 I64(shdr->sh_addralign); 215 I64(shdr->sh_entsize); 216 #else 217 #error ELFSIZE is not 32 or 64 218 #endif 219 } 220 221 static void 222 externalize_shdr(Elf_Byte bo, Elf_Shdr *shdr) 223 { 224 225 #if ELFSIZE == 32 226 E32(shdr->sh_name); 227 E32(shdr->sh_type); 228 E32(shdr->sh_flags); 229 E32(shdr->sh_addr); 230 E32(shdr->sh_offset); 231 E32(shdr->sh_size); 232 E32(shdr->sh_link); 233 E32(shdr->sh_info); 234 E32(shdr->sh_addralign); 235 E32(shdr->sh_entsize); 236 #elif ELFSIZE == 64 237 E32(shdr->sh_name); 238 E32(shdr->sh_type); 239 E64(shdr->sh_flags); 240 E64(shdr->sh_addr); 241 E64(shdr->sh_offset); 242 E64(shdr->sh_size); 243 E32(shdr->sh_link); 244 E32(shdr->sh_info); 245 E64(shdr->sh_addralign); 246 E64(shdr->sh_entsize); 247 #else 248 #error ELFSIZE is not 32 or 64 249 #endif 250 } 251 #else /* _STANDALONE */ 252 /* 253 * Byte swapping is never necessary in the _STANDALONE case because 254 * we are being built with the target compiler. 255 */ 256 #define internalize_ehdr(bo, ehdr) /* nothing */ 257 #define externalize_ehdr(bo, ehdr) /* nothing */ 258 259 #define internalize_phdr(bo, phdr) /* nothing */ 260 261 #define internalize_shdr(bo, shdr) /* nothing */ 262 #define externalize_shdr(bo, shdr) /* nothing */ 263 #endif /* _STANDALONE */ 264 265 int 266 ELFNAMEEND(loadfile)(fd, elf, marks, flags) 267 int fd; 268 Elf_Ehdr *elf; 269 u_long *marks; 270 int flags; 271 { 272 Elf_Shdr *shp; 273 Elf_Phdr *phdr; 274 int i, j; 275 size_t sz; 276 int first; 277 paddr_t minp = ~0, maxp = 0, pos = 0; 278 paddr_t offset = marks[MARK_START], shpp, elfp = NULL; 279 280 internalize_ehdr(elf->e_ident[EI_DATA], elf); 281 282 sz = elf->e_phnum * sizeof(Elf_Phdr); 283 phdr = ALLOC(sz); 284 285 if (lseek(fd, elf->e_phoff, SEEK_SET) == -1) { 286 WARN(("lseek phdr")); 287 FREE(phdr, sz); 288 return 1; 289 } 290 if (read(fd, phdr, sz) != sz) { 291 WARN(("read program headers")); 292 FREE(phdr, sz); 293 return 1; 294 } 295 296 for (first = 1, i = 0; i < elf->e_phnum; i++) { 297 internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]); 298 if (phdr[i].p_type != PT_LOAD || 299 (phdr[i].p_flags & (PF_W|PF_X)) == 0) 300 continue; 301 302 #define IS_TEXT(p) (p.p_flags & PF_X) 303 #define IS_DATA(p) (p.p_flags & PF_W) 304 #define IS_BSS(p) (p.p_filesz < p.p_memsz) 305 /* 306 * XXX: Assume first address is lowest 307 */ 308 if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || 309 (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { 310 311 /* Read in segment. */ 312 PROGRESS(("%s%lu", first ? "" : "+", 313 (u_long)phdr[i].p_filesz)); 314 315 if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) { 316 WARN(("lseek text")); 317 FREE(phdr, sz); 318 return 1; 319 } 320 if (READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz) != 321 phdr[i].p_filesz) { 322 WARN(("read text")); 323 FREE(phdr, sz); 324 return 1; 325 } 326 first = 0; 327 328 } 329 if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) || 330 (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_TEXT)))) { 331 pos = phdr[i].p_vaddr; 332 if (minp > pos) 333 minp = pos; 334 pos += phdr[i].p_filesz; 335 if (maxp < pos) 336 maxp = pos; 337 } 338 339 /* Zero out bss. */ 340 if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { 341 PROGRESS(("+%lu", 342 (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); 343 BZERO((phdr[i].p_vaddr + phdr[i].p_filesz), 344 phdr[i].p_memsz - phdr[i].p_filesz); 345 } 346 if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { 347 pos += phdr[i].p_memsz - phdr[i].p_filesz; 348 if (maxp < pos) 349 maxp = pos; 350 } 351 } 352 FREE(phdr, sz); 353 354 /* 355 * Copy the ELF and section headers. 356 */ 357 maxp = roundup(maxp, ELFROUND); 358 if (flags & (LOAD_HDR|COUNT_HDR)) { 359 elfp = maxp; 360 maxp += sizeof(Elf_Ehdr); 361 } 362 363 if (flags & (LOAD_SYM|COUNT_SYM)) { 364 if (lseek(fd, elf->e_shoff, SEEK_SET) == -1) { 365 WARN(("lseek section headers")); 366 return 1; 367 } 368 sz = elf->e_shnum * sizeof(Elf_Shdr); 369 370 shp = ALLOC(sz); 371 372 if (read(fd, shp, sz) != sz) { 373 WARN(("read section headers")); 374 return 1; 375 } 376 377 shpp = maxp; 378 maxp += roundup(sz, ELFROUND); 379 380 #ifndef _STANDALONE 381 /* Internalize the section headers. */ 382 for (i = 0; i < elf->e_shnum; i++) 383 internalize_shdr(elf->e_ident[EI_DATA], &shp[i]); 384 #endif /* ! _STANDALONE */ 385 386 /* 387 * Now load the symbol sections themselves. Make sure 388 * the sections are aligned. Don't bother with any 389 * string table that isn't referenced by a symbol 390 * table. 391 */ 392 for (first = 1, i = 0; i < elf->e_shnum; i++) { 393 switch (shp[i].sh_type) { 394 case SHT_STRTAB: 395 for (j = 0; j < elf->e_shnum; j++) 396 if (shp[j].sh_type == SHT_SYMTAB && 397 shp[j].sh_link == i) 398 goto havesym; 399 /* FALLTHROUGH */ 400 default: 401 /* Not loading this, so zero out the offset. */ 402 shp[i].sh_offset = 0; 403 break; 404 havesym: 405 case SHT_SYMTAB: 406 if (flags & LOAD_SYM) { 407 PROGRESS(("%s%ld", first ? " [" : "+", 408 (u_long)shp[i].sh_size)); 409 if (lseek(fd, shp[i].sh_offset, 410 SEEK_SET) == -1) { 411 WARN(("lseek symbols")); 412 FREE(shp, sz); 413 return 1; 414 } 415 if (READ(fd, maxp, shp[i].sh_size) != 416 shp[i].sh_size) { 417 WARN(("read symbols")); 418 FREE(shp, sz); 419 return 1; 420 } 421 } 422 shp[i].sh_offset = maxp - elfp; 423 maxp += roundup(shp[i].sh_size, ELFROUND); 424 first = 0; 425 } 426 /* Since we don't load .shstrtab, zero the name. */ 427 shp[i].sh_name = 0; 428 } 429 if (flags & LOAD_SYM) { 430 #ifndef _STANDALONE 431 /* Externalize the section headers. */ 432 for (i = 0; i < elf->e_shnum; i++) 433 externalize_shdr(elf->e_ident[EI_DATA], 434 &shp[i]); 435 #endif /* ! _STANDALONE */ 436 BCOPY(shp, shpp, sz); 437 438 if (first == 0) 439 PROGRESS(("]")); 440 } 441 FREE(shp, sz); 442 } 443 444 /* 445 * Frob the copied ELF header to give information relative 446 * to elfp. 447 */ 448 if (flags & LOAD_HDR) { 449 elf->e_phoff = 0; 450 elf->e_shoff = sizeof(Elf_Ehdr); 451 elf->e_phentsize = 0; 452 elf->e_phnum = 0; 453 elf->e_shstrndx = SHN_UNDEF; 454 externalize_ehdr(elf->e_ident[EI_DATA], elf); 455 BCOPY(elf, elfp, sizeof(*elf)); 456 internalize_ehdr(elf->e_ident[EI_DATA], elf); 457 } 458 459 marks[MARK_START] = LOADADDR(minp); 460 marks[MARK_ENTRY] = LOADADDR(elf->e_entry); 461 /* 462 * Since there can be more than one symbol section in the code 463 * and we need to find strtab too in order to do anything 464 * useful with the symbols, we just pass the whole elf 465 * header back and we let the kernel debugger find the 466 * location and number of symbols by itself. 467 */ 468 marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ 469 marks[MARK_SYM] = LOADADDR(elfp); 470 marks[MARK_END] = LOADADDR(maxp); 471 return 0; 472 } 473 474 #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */ 475