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