1 /* $NetBSD: loadfile_elf32.c,v 1.20 2007/12/03 09:51:30 isaki 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 ssize_t sz; 276 int first; 277 paddr_t minp = ~0, maxp = 0, pos = 0; 278 paddr_t offset = marks[MARK_START], shpp, elfp = 0; 279 ssize_t nr; 280 281 /* some ports dont use the offset */ 282 offset = offset; 283 284 internalize_ehdr(elf->e_ident[EI_DATA], elf); 285 286 sz = elf->e_phnum * sizeof(Elf_Phdr); 287 phdr = ALLOC(sz); 288 289 if (lseek(fd, elf->e_phoff, SEEK_SET) == -1) { 290 WARN(("lseek phdr")); 291 goto freephdr; 292 } 293 nr = read(fd, phdr, sz); 294 if (nr == -1) { 295 WARN(("read program headers")); 296 goto freephdr; 297 } 298 if (nr != sz) { 299 errno = EIO; 300 WARN(("read program headers")); 301 goto freephdr; 302 } 303 304 for (first = 1, i = 0; i < elf->e_phnum; i++) { 305 internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]); 306 307 #ifndef MD_LOADSEG /* Allow processor ABI specific segment loads */ 308 #define MD_LOADSEG(a) /*CONSTCOND*/0 309 #endif 310 if (MD_LOADSEG(&phdr[i])) 311 goto loadseg; 312 313 314 if (phdr[i].p_type != PT_LOAD || 315 (phdr[i].p_flags & (PF_W|PF_X)) == 0) 316 continue; 317 318 #define IS_TEXT(p) (p.p_flags & PF_X) 319 #define IS_DATA(p) (p.p_flags & PF_W) 320 #define IS_BSS(p) (p.p_filesz < p.p_memsz) 321 /* 322 * XXX: Assume first address is lowest 323 */ 324 if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || 325 (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { 326 327 loadseg: 328 if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i])) 329 marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr); 330 331 /* Read in segment. */ 332 PROGRESS(("%s%lu", first ? "" : "+", 333 (u_long)phdr[i].p_filesz)); 334 335 if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) { 336 WARN(("lseek text")); 337 goto freephdr; 338 } 339 nr = READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz); 340 if (nr == -1) { 341 WARN(("read text error")); 342 goto freephdr; 343 } 344 if (nr != (ssize_t)phdr[i].p_filesz) { 345 errno = EIO; 346 WARN(("read text")); 347 goto freephdr; 348 } 349 first = 0; 350 351 } 352 if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) || 353 (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_TEXT)))) { 354 pos = phdr[i].p_vaddr; 355 if (minp > pos) 356 minp = pos; 357 pos += phdr[i].p_filesz; 358 if (maxp < pos) 359 maxp = pos; 360 } 361 362 /* Zero out bss. */ 363 if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { 364 PROGRESS(("+%lu", 365 (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); 366 BZERO((phdr[i].p_vaddr + phdr[i].p_filesz), 367 phdr[i].p_memsz - phdr[i].p_filesz); 368 } 369 if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { 370 pos += phdr[i].p_memsz - phdr[i].p_filesz; 371 if (maxp < pos) 372 maxp = pos; 373 } 374 } 375 DEALLOC(phdr, sz); 376 377 /* 378 * Copy the ELF and section headers. 379 */ 380 maxp = roundup(maxp, ELFROUND); 381 if (flags & (LOAD_HDR|COUNT_HDR)) { 382 elfp = maxp; 383 maxp += sizeof(Elf_Ehdr); 384 } 385 386 if (flags & (LOAD_SYM|COUNT_SYM)) { 387 if (lseek(fd, elf->e_shoff, SEEK_SET) == -1) { 388 WARN(("lseek section headers")); 389 return 1; 390 } 391 sz = elf->e_shnum * sizeof(Elf_Shdr); 392 393 shp = ALLOC(sz); 394 395 nr = read(fd, shp, sz); 396 if (nr == -1) { 397 WARN(("read section headers")); 398 goto freeshp; 399 } 400 if (nr != sz) { 401 errno = EIO; 402 WARN(("read section headers")); 403 goto freeshp; 404 } 405 406 shpp = maxp; 407 maxp += roundup(sz, ELFROUND); 408 409 #ifndef _STANDALONE 410 /* Internalize the section headers. */ 411 for (i = 0; i < elf->e_shnum; i++) 412 internalize_shdr(elf->e_ident[EI_DATA], &shp[i]); 413 #endif /* ! _STANDALONE */ 414 415 /* 416 * Now load the symbol sections themselves. Make sure 417 * the sections are aligned. Don't bother with any 418 * string table that isn't referenced by a symbol 419 * table. 420 */ 421 for (first = 1, i = 0; i < elf->e_shnum; i++) { 422 switch (shp[i].sh_type) { 423 case SHT_STRTAB: 424 for (j = 0; j < elf->e_shnum; j++) 425 if (shp[j].sh_type == SHT_SYMTAB && 426 shp[j].sh_link == (unsigned int)i) 427 goto havesym; 428 /* FALLTHROUGH */ 429 default: 430 /* Not loading this, so zero out the offset. */ 431 shp[i].sh_offset = 0; 432 break; 433 havesym: 434 case SHT_SYMTAB: 435 if (flags & LOAD_SYM) { 436 PROGRESS(("%s%ld", first ? " [" : "+", 437 (u_long)shp[i].sh_size)); 438 if (lseek(fd, shp[i].sh_offset, 439 SEEK_SET) == -1) { 440 WARN(("lseek symbols")); 441 goto freeshp; 442 } 443 nr = READ(fd, maxp, shp[i].sh_size); 444 if (nr == -1) { 445 WARN(("read symbols")); 446 goto freeshp; 447 } 448 if (nr != (ssize_t)shp[i].sh_size) { 449 errno = EIO; 450 WARN(("read symbols")); 451 goto freeshp; 452 } 453 } 454 shp[i].sh_offset = maxp - elfp; 455 maxp += roundup(shp[i].sh_size, ELFROUND); 456 first = 0; 457 } 458 /* Since we don't load .shstrtab, zero the name. */ 459 shp[i].sh_name = 0; 460 } 461 if (flags & LOAD_SYM) { 462 #ifndef _STANDALONE 463 /* Externalize the section headers. */ 464 for (i = 0; i < elf->e_shnum; i++) 465 externalize_shdr(elf->e_ident[EI_DATA], 466 &shp[i]); 467 #endif /* ! _STANDALONE */ 468 BCOPY(shp, shpp, sz); 469 470 if (first == 0) 471 PROGRESS(("]")); 472 } 473 DEALLOC(shp, sz); 474 } 475 476 /* 477 * Frob the copied ELF header to give information relative 478 * to elfp. 479 */ 480 if (flags & LOAD_HDR) { 481 elf->e_phoff = 0; 482 elf->e_shoff = sizeof(Elf_Ehdr); 483 elf->e_phentsize = 0; 484 elf->e_phnum = 0; 485 elf->e_shstrndx = SHN_UNDEF; 486 externalize_ehdr(elf->e_ident[EI_DATA], elf); 487 BCOPY(elf, elfp, sizeof(*elf)); 488 internalize_ehdr(elf->e_ident[EI_DATA], elf); 489 } 490 491 marks[MARK_START] = LOADADDR(minp); 492 marks[MARK_ENTRY] = LOADADDR(elf->e_entry); 493 /* 494 * Since there can be more than one symbol section in the code 495 * and we need to find strtab too in order to do anything 496 * useful with the symbols, we just pass the whole elf 497 * header back and we let the kernel debugger find the 498 * location and number of symbols by itself. 499 */ 500 marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ 501 marks[MARK_SYM] = LOADADDR(elfp); 502 marks[MARK_END] = LOADADDR(maxp); 503 return 0; 504 freephdr: 505 DEALLOC(phdr, sz); 506 return 1; 507 freeshp: 508 DEALLOC(shp, sz); 509 return 1; 510 } 511 512 #endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */ 513