1 /* $OpenBSD: elf.c,v 1.34 2015/12/09 19:28:34 mmcc Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/mman.h> 30 #include <unistd.h> 31 #include <a.out.h> 32 #include <elf_abi.h> 33 #include <errno.h> 34 #include <err.h> 35 #include <stdint.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <ctype.h> 40 #include "util.h" 41 #include "elfuncs.h" 42 43 #if ELFSIZE == 32 44 #define swap_addr swap32 45 #define swap_off swap32 46 #define swap_sword swap32 47 #define swap_word swap32 48 #define swap_sxword swap32 49 #define swap_xword swap32 50 #define swap_half swap16 51 #define swap_quarter swap16 52 #define elf_fix_header elf32_fix_header 53 #define elf_load_shdrs elf32_load_shdrs 54 #define elf_load_phdrs elf32_load_phdrs 55 #define elf_fix_shdrs elf32_fix_shdrs 56 #define elf_fix_phdrs elf32_fix_phdrs 57 #define elf_fix_sym elf32_fix_sym 58 #define elf_size elf32_size 59 #define elf_symloadx elf32_symloadx 60 #define elf_symload elf32_symload 61 #define elf2nlist elf32_2nlist 62 #define elf_shn2type elf32_shn2type 63 #elif ELFSIZE == 64 64 #define swap_addr swap64 65 #define swap_off swap64 66 #ifdef __alpha__ 67 #define swap_sword swap64 68 #define swap_word swap64 69 #else 70 #define swap_sword swap32 71 #define swap_word swap32 72 #endif 73 #define swap_sxword swap64 74 #define swap_xword swap64 75 #define swap_half swap64 76 #define swap_quarter swap16 77 #define elf_fix_header elf64_fix_header 78 #define elf_load_shdrs elf64_load_shdrs 79 #define elf_load_phdrs elf64_load_phdrs 80 #define elf_fix_shdrs elf64_fix_shdrs 81 #define elf_fix_phdrs elf64_fix_phdrs 82 #define elf_fix_sym elf64_fix_sym 83 #define elf_size elf64_size 84 #define elf_symloadx elf64_symloadx 85 #define elf_symload elf64_symload 86 #define elf2nlist elf64_2nlist 87 #define elf_shn2type elf64_shn2type 88 #else 89 #error "Unsupported ELF class" 90 #endif 91 92 #define ELF_SDATA ".sdata" 93 #define ELF_TDATA ".tdata" 94 #define ELF_SBSS ".sbss" 95 #define ELF_TBSS ".tbss" 96 #define ELF_PLT ".plt" 97 98 #ifndef SHN_MIPS_ACOMMON 99 #define SHN_MIPS_ACOMMON SHN_LOPROC + 0 100 #endif 101 #ifndef SHN_MIPS_TEXT 102 #define SHN_MIPS_TEXT SHN_LOPROC + 1 103 #endif 104 #ifndef SHN_MIPS_DATA 105 #define SHN_MIPS_DATA SHN_LOPROC + 2 106 #endif 107 #ifndef SHN_MIPS_SUNDEFINED 108 #define SHN_MIPS_SUNDEFINED SHN_LOPROC + 4 109 #endif 110 #ifndef SHN_MIPS_SCOMMON 111 #define SHN_MIPS_SCOMMON SHN_LOPROC + 3 112 #endif 113 114 #ifndef STT_PARISC_MILLI 115 #define STT_PARISC_MILLI STT_LOPROC + 0 116 #endif 117 118 int elf_shn2type(Elf_Ehdr *, u_int, const char *); 119 int elf2nlist(Elf_Sym *, Elf_Ehdr *, Elf_Shdr *, char *, struct xnlist *); 120 121 int 122 elf_fix_header(Elf_Ehdr *eh) 123 { 124 /* nothing to do */ 125 if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) 126 return (0); 127 128 eh->e_type = swap16(eh->e_type); 129 eh->e_machine = swap16(eh->e_machine); 130 eh->e_version = swap32(eh->e_version); 131 eh->e_entry = swap_addr(eh->e_entry); 132 eh->e_phoff = swap_off(eh->e_phoff); 133 eh->e_shoff = swap_off(eh->e_shoff); 134 eh->e_flags = swap32(eh->e_flags); 135 eh->e_ehsize = swap16(eh->e_ehsize); 136 eh->e_phentsize = swap16(eh->e_phentsize); 137 eh->e_phnum = swap16(eh->e_phnum); 138 eh->e_shentsize = swap16(eh->e_shentsize); 139 eh->e_shnum = swap16(eh->e_shnum); 140 eh->e_shstrndx = swap16(eh->e_shstrndx); 141 142 return (1); 143 } 144 145 Elf_Shdr * 146 elf_load_shdrs(const char *name, FILE *fp, off_t foff, Elf_Ehdr *head) 147 { 148 Elf_Shdr *shdr; 149 150 elf_fix_header(head); 151 152 if (head->e_shnum == 0) { 153 warnx("%s: no section header table", name); 154 return (NULL); 155 } 156 157 if (head->e_shstrndx >= head->e_shnum) { 158 warnx("%s: inconsistent section header table", name); 159 return (NULL); 160 } 161 162 if (head->e_shentsize < sizeof(Elf_Shdr)) { 163 warnx("%s: inconsistent section header size", name); 164 return (NULL); 165 } 166 167 if ((shdr = calloc(head->e_shnum, head->e_shentsize)) == NULL) { 168 warn("%s: malloc shdr", name); 169 return (NULL); 170 } 171 172 if (fseeko(fp, foff + head->e_shoff, SEEK_SET)) { 173 warn("%s: fseeko", name); 174 free(shdr); 175 return (NULL); 176 } 177 178 if (fread(shdr, head->e_shentsize, head->e_shnum, fp) != head->e_shnum) { 179 warnx("%s: premature EOF", name); 180 free(shdr); 181 return (NULL); 182 } 183 184 elf_fix_shdrs(head, shdr); 185 return (shdr); 186 } 187 188 Elf_Phdr * 189 elf_load_phdrs(const char *name, FILE *fp, off_t foff, Elf_Ehdr *head) 190 { 191 Elf_Phdr *phdr; 192 193 if ((phdr = calloc(head->e_phentsize, head->e_phnum)) == NULL) { 194 warn("%s: malloc phdr", name); 195 return (NULL); 196 } 197 198 if (fseeko(fp, foff + head->e_phoff, SEEK_SET)) { 199 warn("%s: fseeko", name); 200 free(phdr); 201 return (NULL); 202 } 203 204 if (fread(phdr, head->e_phentsize, head->e_phnum, fp) != head->e_phnum) { 205 warnx("%s: premature EOF", name); 206 free(phdr); 207 return (NULL); 208 } 209 210 elf_fix_phdrs(head, phdr); 211 return (phdr); 212 } 213 214 int 215 elf_fix_shdrs(Elf_Ehdr *eh, Elf_Shdr *shdr) 216 { 217 int i; 218 219 /* nothing to do */ 220 if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) 221 return (0); 222 223 for (i = eh->e_shnum; i--; shdr++) { 224 shdr->sh_name = swap32(shdr->sh_name); 225 shdr->sh_type = swap32(shdr->sh_type); 226 shdr->sh_flags = swap_xword(shdr->sh_flags); 227 shdr->sh_addr = swap_addr(shdr->sh_addr); 228 shdr->sh_offset = swap_off(shdr->sh_offset); 229 shdr->sh_size = swap_xword(shdr->sh_size); 230 shdr->sh_link = swap32(shdr->sh_link); 231 shdr->sh_info = swap32(shdr->sh_info); 232 shdr->sh_addralign = swap_xword(shdr->sh_addralign); 233 shdr->sh_entsize = swap_xword(shdr->sh_entsize); 234 } 235 236 return (1); 237 } 238 239 int 240 elf_fix_phdrs(Elf_Ehdr *eh, Elf_Phdr *phdr) 241 { 242 int i; 243 244 /* nothing to do */ 245 if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) 246 return (0); 247 248 for (i = eh->e_phnum; i--; phdr++) { 249 phdr->p_type = swap32(phdr->p_type); 250 phdr->p_flags = swap32(phdr->p_flags); 251 phdr->p_offset = swap_off(phdr->p_offset); 252 phdr->p_vaddr = swap_addr(phdr->p_vaddr); 253 phdr->p_paddr = swap_addr(phdr->p_paddr); 254 phdr->p_filesz = swap_xword(phdr->p_filesz); 255 phdr->p_memsz = swap_xword(phdr->p_memsz); 256 phdr->p_align = swap_xword(phdr->p_align); 257 } 258 259 return (1); 260 } 261 262 int 263 elf_fix_sym(Elf_Ehdr *eh, Elf_Sym *sym) 264 { 265 /* nothing to do */ 266 if (eh->e_ident[EI_DATA] == ELF_TARG_DATA) 267 return (0); 268 269 sym->st_name = swap32(sym->st_name); 270 sym->st_shndx = swap16(sym->st_shndx); 271 sym->st_value = swap_addr(sym->st_value); 272 sym->st_size = swap_xword(sym->st_size); 273 274 return (1); 275 } 276 277 int 278 elf_shn2type(Elf_Ehdr *eh, u_int shn, const char *sn) 279 { 280 switch (shn) { 281 case SHN_MIPS_SUNDEFINED: 282 if (eh->e_machine == EM_MIPS) 283 return (N_UNDF | N_EXT); 284 break; 285 286 case SHN_UNDEF: 287 return (N_UNDF | N_EXT); 288 289 case SHN_ABS: 290 return (N_ABS); 291 292 case SHN_MIPS_ACOMMON: 293 if (eh->e_machine == EM_MIPS) 294 return (N_COMM); 295 break; 296 297 case SHN_MIPS_SCOMMON: 298 if (eh->e_machine == EM_MIPS) 299 return (N_COMM); 300 break; 301 302 case SHN_COMMON: 303 return (N_COMM); 304 305 case SHN_MIPS_TEXT: 306 if (eh->e_machine == EM_MIPS) 307 return (N_TEXT); 308 break; 309 310 case SHN_MIPS_DATA: 311 if (eh->e_machine == EM_MIPS) 312 return (N_DATA); 313 break; 314 315 default: 316 /* TODO: beyond 8 a table-driven binsearch should be used */ 317 if (sn == NULL) 318 return (-1); 319 else if (!strcmp(sn, ELF_TEXT)) 320 return (N_TEXT); 321 else if (!strcmp(sn, ELF_RODATA)) 322 return (N_SIZE); 323 else if (!strcmp(sn, ELF_DATA)) 324 return (N_DATA); 325 else if (!strcmp(sn, ELF_SDATA)) 326 return (N_DATA); 327 else if (!strcmp(sn, ELF_TDATA)) 328 return (N_DATA); 329 else if (!strcmp(sn, ELF_BSS)) 330 return (N_BSS); 331 else if (!strcmp(sn, ELF_SBSS)) 332 return (N_BSS); 333 else if (!strcmp(sn, ELF_TBSS)) 334 return (N_BSS); 335 else if (!strncmp(sn, ELF_GOT, sizeof(ELF_GOT) - 1)) 336 return (N_DATA); 337 else if (!strncmp(sn, ELF_PLT, sizeof(ELF_PLT) - 1)) 338 return (N_DATA); 339 } 340 341 return (-1); 342 } 343 344 /* 345 * Devise xnlist's type from Elf_Sym. 346 * XXX this task is done as well in libc and kvm_mkdb. 347 */ 348 int 349 elf2nlist(Elf_Sym *sym, Elf_Ehdr *eh, Elf_Shdr *shdr, char *shstr, 350 struct xnlist *np) 351 { 352 u_char stt; 353 const char *sn; 354 int type; 355 356 if (sym->st_shndx < eh->e_shnum) 357 sn = shstr + shdr[sym->st_shndx].sh_name; 358 else 359 sn = NULL; 360 #if 0 361 { 362 extern char *stab; 363 printf("%d:%s %d %d %s\n", sym->st_shndx, sn? sn : "", 364 ELF_ST_TYPE(sym->st_info), ELF_ST_BIND(sym->st_info), 365 stab + sym->st_name); 366 } 367 #endif 368 369 switch (stt = ELF_ST_TYPE(sym->st_info)) { 370 case STT_NOTYPE: 371 case STT_OBJECT: 372 case STT_TLS: 373 type = elf_shn2type(eh, sym->st_shndx, sn); 374 if (type < 0) { 375 if (sn == NULL) 376 np->nl.n_other = '?'; 377 else 378 np->nl.n_type = stt == STT_NOTYPE ? 379 N_COMM : N_DATA; 380 } else { 381 /* a hack for .rodata check (; */ 382 if (type == N_SIZE) { 383 np->nl.n_type = N_DATA; 384 np->nl.n_other = 'r'; 385 } else 386 np->nl.n_type = type; 387 } 388 if (ELF_ST_BIND(sym->st_info) == STB_WEAK) 389 np->nl.n_other = 'W'; 390 break; 391 392 case STT_FUNC: 393 type = elf_shn2type(eh, sym->st_shndx, NULL); 394 np->nl.n_type = type < 0? N_TEXT : type; 395 if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { 396 np->nl.n_other = 'W'; 397 } else if (sn != NULL && *sn != 0 && 398 strcmp(sn, ELF_INIT) && 399 strcmp(sn, ELF_TEXT) && 400 strcmp(sn, ELF_FINI)) /* XXX GNU compat */ 401 np->nl.n_other = '?'; 402 break; 403 404 case STT_SECTION: 405 type = elf_shn2type(eh, sym->st_shndx, NULL); 406 if (type < 0) 407 np->nl.n_other = '?'; 408 else 409 np->nl.n_type = type; 410 break; 411 412 case STT_FILE: 413 np->nl.n_type = N_FN | N_EXT; 414 break; 415 416 case STT_PARISC_MILLI: 417 if (eh->e_machine == EM_PARISC) 418 np->nl.n_type = N_TEXT; 419 else 420 np->nl.n_other = '?'; 421 break; 422 423 default: 424 np->nl.n_other = '?'; 425 break; 426 } 427 if (np->nl.n_type != N_UNDF && ELF_ST_BIND(sym->st_info) != STB_LOCAL) { 428 np->nl.n_type |= N_EXT; 429 if (np->nl.n_other) 430 np->nl.n_other = toupper((unsigned char)np->nl.n_other); 431 } 432 433 return (0); 434 } 435 436 int 437 elf_size(Elf_Ehdr *head, Elf_Shdr *shdr, 438 u_long *ptext, u_long *pdata, u_long *pbss) 439 { 440 int i; 441 442 *ptext = *pdata = *pbss = 0; 443 444 for (i = 0; i < head->e_shnum; i++) { 445 if (!(shdr[i].sh_flags & SHF_ALLOC)) 446 ; 447 else if (shdr[i].sh_flags & SHF_EXECINSTR || 448 !(shdr[i].sh_flags & SHF_WRITE)) 449 *ptext += shdr[i].sh_size; 450 else if (shdr[i].sh_type == SHT_NOBITS) 451 *pbss += shdr[i].sh_size; 452 else 453 *pdata += shdr[i].sh_size; 454 } 455 456 return (0); 457 } 458 459 int 460 elf_symloadx(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, 461 Elf_Shdr *shdr, char *shstr, long shstrsize, struct xnlist **pnames, 462 struct xnlist ***psnames, size_t *pstabsize, int *pnrawnames, 463 const char *strtab, const char *symtab) 464 { 465 long symsize; 466 struct xnlist *np; 467 Elf_Sym sbuf; 468 int i; 469 470 for (i = 0; i < eh->e_shnum; i++) { 471 if (shdr[i].sh_name >= shstrsize) { 472 warnx("%s: corrupt file", name); 473 return (1); 474 } 475 if (!strcmp(shstr + shdr[i].sh_name, strtab)) { 476 *pstabsize = shdr[i].sh_size; 477 if (*pstabsize > SIZE_MAX) { 478 warnx("%s: corrupt file", name); 479 return (1); 480 } 481 482 MMAP(stab, *pstabsize, PROT_READ, MAP_PRIVATE|MAP_FILE, 483 fileno(fp), foff + shdr[i].sh_offset); 484 if (stab == MAP_FAILED) 485 return (1); 486 } 487 } 488 for (i = 0; i < eh->e_shnum; i++) { 489 if (!strcmp(shstr + shdr[i].sh_name, symtab)) { 490 symsize = shdr[i].sh_size; 491 if (fseeko(fp, foff + shdr[i].sh_offset, SEEK_SET)) { 492 warn("%s: fseeko", name); 493 if (stab) 494 MUNMAP(stab, *pstabsize); 495 return (1); 496 } 497 498 *pnrawnames = symsize / sizeof(sbuf); 499 if ((*pnames = calloc(*pnrawnames, sizeof(*np))) == NULL) { 500 warn("%s: malloc names", name); 501 if (stab) 502 MUNMAP(stab, *pstabsize); 503 *pnrawnames = 0; 504 return (1); 505 } 506 if ((*psnames = calloc(*pnrawnames, sizeof(np))) == NULL) { 507 warn("%s: malloc snames", name); 508 if (stab) 509 MUNMAP(stab, *pstabsize); 510 free(*pnames); 511 *pnames = NULL; 512 *pnrawnames = 0; 513 return (1); 514 } 515 516 for (np = *pnames; symsize > 0; symsize -= sizeof(sbuf)) { 517 if (fread(&sbuf, 1, sizeof(sbuf), 518 fp) != sizeof(sbuf)) { 519 warn("%s: read symbol", name); 520 if (stab) 521 MUNMAP(stab, *pstabsize); 522 free(*pnames); 523 free(*psnames); 524 *pnames = NULL; 525 *psnames = NULL; 526 *pnrawnames = 0; 527 return (1); 528 } 529 530 elf_fix_sym(eh, &sbuf); 531 532 if (!sbuf.st_name || 533 sbuf.st_name > *pstabsize) 534 continue; 535 536 elf2nlist(&sbuf, eh, shdr, shstr, np); 537 np->nl.n_value = sbuf.st_value; 538 np->nl.n_un.n_strx = sbuf.st_name; 539 np->n_size = sbuf.st_size; 540 np++; 541 } 542 *pnrawnames = np - *pnames; 543 } 544 } 545 return (0); 546 } 547 548 int 549 elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, 550 Elf_Shdr *shdr, struct xnlist **pnames, struct xnlist ***psnames, 551 size_t *pstabsize, int *pnrawnames) 552 { 553 long shstrsize; 554 char *shstr; 555 556 shstrsize = shdr[eh->e_shstrndx].sh_size; 557 if (shstrsize == 0) { 558 warnx("%s: no name list", name); 559 return (1); 560 } 561 562 if ((shstr = malloc(shstrsize)) == NULL) { 563 warn("%s: malloc shsrt", name); 564 return (1); 565 } 566 567 if (fseeko(fp, foff + shdr[eh->e_shstrndx].sh_offset, SEEK_SET)) { 568 warn("%s: fseeko", name); 569 free(shstr); 570 return (1); 571 } 572 573 if (fread(shstr, 1, shstrsize, fp) != shstrsize) { 574 warnx("%s: premature EOF", name); 575 free(shstr); 576 return(1); 577 } 578 579 stab = NULL; 580 *pnames = NULL; *psnames = NULL; *pnrawnames = 0; 581 if (!dynamic_only) { 582 elf_symloadx(name, fp, foff, eh, shdr, shstr, shstrsize, pnames, 583 psnames, pstabsize, pnrawnames, ELF_STRTAB, ELF_SYMTAB); 584 } 585 if (stab == NULL) { 586 elf_symloadx(name, fp, foff, eh, shdr, shstr, shstrsize, pnames, 587 psnames, pstabsize, pnrawnames, ELF_DYNSTR, ELF_DYNSYM); 588 } 589 590 free(shstr); 591 if (stab == NULL) { 592 warnx("%s: no name list", name); 593 free(*pnames); 594 free(*psnames); 595 return (1); 596 } 597 598 return (0); 599 } 600