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