elfread.c (14837B)
1 #include <assert.h> 2 #include <errno.h> 3 #include <limits.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <scc/mach.h> 9 #include <scc/elf.h> 10 11 #include <scc/elf/elftypes.h> 12 #include <scc/elf/elfhdr.h> 13 #include <scc/elf/elfphdr.h> 14 #include <scc/elf/elfshdr.h> 15 #include <scc/elf/elfent.h> 16 #include <scc/elf/elfrel.h> 17 18 #include "../libmach.h" 19 #include "fun.h" 20 21 struct elfunpack { 22 void (*hdr)(int, unsigned char *, Elfhdr *); 23 void (*phdr)(int, unsigned char *, Elfphdr *); 24 void (*sec)(int, unsigned char *, Elfsec *); 25 void (*sym)(int, unsigned char *, Elfsym *); 26 void (*rel)(int, unsigned char *, Elfrel *); 27 void (*rela)(int, unsigned char *, Elfrel *); 28 29 int hdrsiz; 30 int phdrsiz; 31 int shentsiz; 32 int symsiz; 33 int relsiz; 34 int relasiz; 35 }; 36 37 struct elfunpack unpack64; 38 struct elfunpack unpack32; 39 40 static void 41 unpack_hdr64(int order, unsigned char *buf, Elfhdr *hdr) 42 { 43 Elf64_Ehdr ehdr; 44 int n; 45 46 n = unpack(order, 47 buf, 48 "'16sslqqqlssssss", 49 ehdr.e_ident, 50 &ehdr.e_type, 51 &ehdr.e_machine, 52 &ehdr.e_version, 53 &ehdr.e_entry, 54 &ehdr.e_phoff, 55 &ehdr.e_shoff, 56 &ehdr.e_flags, 57 &ehdr.e_ehsize, 58 &ehdr.e_phentsize, 59 &ehdr.e_phnum, 60 &ehdr.e_shentsize, 61 &ehdr.e_shnum, 62 &ehdr.e_shstrndx); 63 64 assert(n == ELFH64SZ); 65 66 memcpy(hdr->ident, ehdr.e_ident, EI_NIDENT); 67 hdr->type = ehdr.e_type; 68 hdr->machine = ehdr.e_machine; 69 hdr->version = ehdr.e_version; 70 hdr->entry = ehdr.e_entry; 71 hdr->phoff = ehdr.e_phoff; 72 hdr->shoff = ehdr.e_shoff; 73 hdr->flags = ehdr.e_flags; 74 hdr->ehsize = ehdr.e_ehsize; 75 hdr->phentsize = ehdr.e_phentsize; 76 hdr->phnum = ehdr.e_phnum; 77 hdr->shentsize = ehdr.e_shentsize; 78 hdr->shnum = ehdr.e_shnum; 79 hdr->shstrndx = ehdr.e_shstrndx; 80 } 81 82 static void 83 unpack_hdr32(int order, unsigned char *buf, Elfhdr *hdr) 84 { 85 Elf32_Ehdr ehdr; 86 int n; 87 88 n = unpack(order, 89 buf, 90 "'16sslllllssssss", 91 ehdr.e_ident, 92 &ehdr.e_type, 93 &ehdr.e_machine, 94 &ehdr.e_version, 95 &ehdr.e_entry, 96 &ehdr.e_phoff, 97 &ehdr.e_shoff, 98 &ehdr.e_flags, 99 &ehdr.e_ehsize, 100 &ehdr.e_phentsize, 101 &ehdr.e_phnum, 102 &ehdr.e_shentsize, 103 &ehdr.e_shnum, 104 &ehdr.e_shstrndx); 105 106 assert(n == ELFH32SZ); 107 108 memcpy(hdr->ident, ehdr.e_ident, EI_NIDENT); 109 hdr->type = ehdr.e_type; 110 hdr->machine = ehdr.e_machine; 111 hdr->version = ehdr.e_version; 112 hdr->entry = ehdr.e_entry; 113 hdr->phoff = ehdr.e_phoff; 114 hdr->shoff = ehdr.e_shoff; 115 hdr->flags = ehdr.e_flags; 116 hdr->ehsize = ehdr.e_ehsize; 117 hdr->phentsize = ehdr.e_phentsize; 118 hdr->phnum = ehdr.e_phnum; 119 hdr->shentsize = ehdr.e_shentsize; 120 hdr->shnum = ehdr.e_shnum; 121 hdr->shstrndx = ehdr.e_shstrndx; 122 } 123 124 static void 125 unpack_phdr64(int order, unsigned char *buf, Elfphdr *hdr) 126 { 127 int n; 128 Elf64_Phdr phdr; 129 130 n = unpack(order, 131 buf, 132 "llqqqqqq", 133 &phdr.p_type, 134 &phdr.p_flags, 135 &phdr.p_offset, 136 &phdr.p_vaddr, 137 &phdr.p_paddr, 138 &phdr.p_filesz, 139 &phdr.p_memsz, 140 &phdr.p_align); 141 142 assert(n == ELFP64SZ); 143 144 hdr->type = phdr.p_type; 145 hdr->flags = phdr.p_flags; 146 hdr->offset = phdr.p_offset; 147 hdr->vaddr = phdr.p_vaddr; 148 hdr->paddr = phdr.p_paddr; 149 hdr->filesz = phdr.p_filesz; 150 hdr->memsz = phdr.p_memsz; 151 hdr->align = phdr.p_align; 152 } 153 154 static void 155 unpack_phdr32(int order, unsigned char *buf, Elfphdr *hdr) 156 { 157 int n; 158 Elf32_Phdr phdr; 159 160 n = unpack(order, 161 buf, 162 "llllllll", 163 &phdr.p_type, 164 &phdr.p_offset, 165 &phdr.p_vaddr, 166 &phdr.p_paddr, 167 &phdr.p_filesz, 168 &phdr.p_memsz, 169 &phdr.p_flags, 170 &phdr.p_align); 171 172 assert(n == ELFP32SZ); 173 174 hdr->type = phdr.p_type; 175 hdr->flags = phdr.p_flags; 176 hdr->offset = phdr.p_offset; 177 hdr->vaddr = phdr.p_vaddr; 178 hdr->paddr = phdr.p_paddr; 179 hdr->filesz = phdr.p_filesz; 180 hdr->memsz = phdr.p_memsz; 181 hdr->align = phdr.p_align; 182 } 183 184 static void 185 unpack_shdr64(int order, unsigned char *buf, Elfsec *sec) 186 { 187 int n; 188 Elf64_Shdr shdr; 189 190 n = unpack(order, 191 buf, 192 "llqqqqllqq", 193 &shdr.sh_name, 194 &shdr.sh_type, 195 &shdr.sh_flags, 196 &shdr.sh_addr, 197 &shdr.sh_offset, 198 &shdr.sh_size, 199 &shdr.sh_link, 200 &shdr.sh_info, 201 &shdr.sh_addralign, 202 &shdr.sh_entsize); 203 204 assert(n == ELFS64SZ); 205 206 sec->sh_name = shdr.sh_name; 207 sec->type = shdr.sh_type; 208 sec->flags = shdr.sh_flags; 209 sec->addr = shdr.sh_addr; 210 sec->offset = shdr.sh_offset; 211 sec->size = shdr.sh_size; 212 sec->link = shdr.sh_link; 213 sec->info = shdr.sh_info; 214 sec->addralign = shdr.sh_addralign; 215 sec->entsize = shdr.sh_entsize; 216 } 217 218 static void 219 unpack_shdr32(int order, unsigned char *buf, Elfsec *sec) 220 { 221 int n; 222 Elf32_Shdr shdr; 223 224 n = unpack(order, 225 buf, 226 "llllllllll", 227 &shdr.sh_name, 228 &shdr.sh_type, 229 &shdr.sh_flags, 230 &shdr.sh_addr, 231 &shdr.sh_offset, 232 &shdr.sh_size, 233 &shdr.sh_link, 234 &shdr.sh_info, 235 &shdr.sh_addralign, 236 &shdr.sh_entsize); 237 238 assert(n == ELFS32SZ); 239 240 sec->sh_name = shdr.sh_name; 241 sec->type = shdr.sh_type; 242 sec->flags = shdr.sh_flags; 243 sec->addr = shdr.sh_addr; 244 sec->offset = shdr.sh_offset; 245 sec->size = shdr.sh_size; 246 sec->link = shdr.sh_link; 247 sec->info = shdr.sh_info; 248 sec->addralign = shdr.sh_addralign; 249 sec->entsize = shdr.sh_entsize; 250 } 251 252 static void 253 unpack_sym64(int order, unsigned char *buf, Elfsym *sym) 254 { 255 int n; 256 Elf64_Sym ent; 257 258 n = unpack(order, 259 buf, 260 "lccsqq", 261 &ent.st_name, 262 &ent.st_info, 263 &ent.st_other, 264 &ent.st_shndx, 265 &ent.st_value, 266 &ent.st_size); 267 268 assert(n == ELFE64SZ); 269 270 sym->st_name = ent.st_name; 271 sym->info = ent.st_info; 272 sym->other = ent.st_other; 273 sym->shndx = ent.st_shndx; 274 sym->value = ent.st_value; 275 sym->size = ent.st_size; 276 } 277 278 static void 279 unpack_sym32(int order, unsigned char *buf, Elfsym *sym) 280 { 281 int n; 282 Elf32_Sym ent; 283 284 n = unpack(order, 285 buf, 286 "lllccs", 287 &ent.st_name, 288 &ent.st_value, 289 &ent.st_size, 290 &ent.st_info, 291 &ent.st_other, 292 &ent.st_shndx); 293 294 assert(n == ELFE32SZ); 295 296 sym->st_name = ent.st_name; 297 sym->info = ent.st_info; 298 sym->other = ent.st_other; 299 sym->shndx = ent.st_shndx; 300 sym->value = ent.st_value; 301 sym->size = ent.st_size; 302 } 303 304 static void 305 unpack_rel64(int order, unsigned char *buf, Elfrel *rp) 306 { 307 int n; 308 Elf64_Rel r; 309 310 n = unpack(order, 311 buf, 312 "qq", 313 &r.r_offset, 314 &r.r_info); 315 316 assert(n == ELFR64SZ); 317 318 rp->off = r.r_offset; 319 rp->info = r.r_info; 320 rp->addend = 0; 321 } 322 323 static void 324 unpack_rel32(int order, unsigned char *buf, Elfrel *rp) 325 { 326 int n; 327 Elf32_Rel r; 328 329 n = unpack(order, 330 buf, 331 "ll", 332 &r.r_offset, 333 &r.r_info); 334 335 assert(n == ELFR32SZ); 336 337 rp->off = r.r_offset; 338 rp->info = r.r_info; 339 rp->addend = 0; 340 } 341 342 static void 343 unpack_rela64(int order, unsigned char *buf, Elfrel *rp) 344 { 345 int n; 346 Elf64_Rela r; 347 348 n = unpack(order, 349 buf, 350 "qqq", 351 &r.r_offset, 352 &r.r_info, 353 &r.r_addend); 354 355 assert(n == ELFRA64SZ); 356 357 rp->off = r.r_offset; 358 rp->info = r.r_info; 359 rp->addend = r.r_addend; 360 } 361 362 static void 363 unpack_rela32(int order, unsigned char *buf, Elfrel *rp) 364 { 365 int n; 366 Elf32_Rela r; 367 368 n = unpack(order, 369 buf, 370 "lll", 371 &r.r_offset, 372 &r.r_info, 373 &r.r_addend); 374 375 assert(n == ELFRA32SZ); 376 377 rp->off = r.r_offset; 378 rp->info = r.r_info; 379 rp->addend = r.r_addend; 380 } 381 382 static int 383 readhdr(Obj *obj, FILE *fp) 384 { 385 Elf *elf = obj->data; 386 Elfhdr *hdr = &elf->hdr; 387 Elfunpack *u = elf->unpack; 388 unsigned char buf[ELFH64SZ]; 389 390 if (fread(buf, u->hdrsiz, 1, fp) != 1) 391 return 0; 392 (*u->hdr)(ORDER(obj->type), buf, hdr); 393 394 if (hdr->shnum > INT_MAX || hdr->phnum > INT_MAX) 395 return 0; 396 397 switch (hdr->type) { 398 case ET_REL: 399 case ET_EXEC: 400 case ET_DYN: 401 return 1; 402 default: 403 return 0; 404 } 405 } 406 407 static int 408 readphdr(Obj *obj, FILE *fp) 409 { 410 int i, r; 411 Elfphdr *phdr; 412 Elf *elf = obj->data; 413 Elfhdr *hdr = &elf->hdr; 414 Elfunpack *u = elf->unpack; 415 unsigned char *buf; 416 417 r = 0; 418 if (hdr->phnum > 0 419 && (hdr->phoff == 0 || hdr->phentsize < u->phdrsiz)) { 420 errno = ERANGE; 421 goto err0; 422 } 423 if (hdr->phoff == 0 || hdr->phnum == 0) 424 return 1; 425 426 if ((buf = malloc(hdr->phentsize)) == NULL) 427 goto err0; 428 if ((phdr = calloc(hdr->phnum, sizeof(*phdr))) == NULL) 429 goto err1; 430 elf->phdr = phdr; 431 432 if (!objpos(obj, fp, hdr->phoff)) 433 goto err1; 434 435 for (i = 0; i < hdr->phnum; i++) { 436 if (fread(buf, hdr->phentsize, 1, fp) != 1) 437 goto err1; 438 (*u->phdr)(ORDER(obj->type), buf, &phdr[i]); 439 if (phdr[i].offset > LONG_MAX) 440 goto err1; 441 } 442 r = 1; 443 444 err1: 445 free(buf); 446 err0: 447 return r; 448 } 449 450 static int 451 readshdr(Obj *obj, FILE *fp) 452 { 453 int r, nsec; 454 Elfsec *sec; 455 Elf *elf = obj->data; 456 Elfhdr *hdr = &elf->hdr; 457 Elfunpack *u = elf->unpack; 458 unsigned char *buf; 459 460 if (hdr->shoff == 0) 461 return 1; 462 463 if (!objpos(obj, fp, hdr->shoff)) 464 return 0; 465 466 if (hdr->shnum != SHN_UNDEF) { 467 if (hdr->shnum > INT_MAX) 468 return 0; 469 nsec = hdr->shnum; 470 } else { 471 Elfsec sec0; 472 fpos_t pos; 473 unsigned char buf0[ELFS64SZ]; 474 475 fgetpos(fp, &pos); 476 fread(buf0, u->shentsiz, 1, fp); 477 fsetpos(fp, &pos); 478 479 if (ferror(fp)) 480 return 0; 481 482 (*u->sec)(ORDER(obj->type), buf0, &sec0); 483 if (sec0.size > INT_MAX) 484 return 0; 485 nsec = sec0.size; 486 } 487 488 if (nsec == 0) 489 return 1; 490 491 r = 0; 492 if ((buf = malloc(hdr->shentsize)) == NULL) 493 return 0; 494 if ((sec = calloc(nsec, sizeof(*sec))) == NULL) 495 goto err; 496 elf->secs = sec; 497 elf->nsec = nsec; 498 499 for ( ; nsec-- > 0; ++sec) { 500 if (fread(buf, hdr->shentsize, 1, fp) != 1) 501 goto err; 502 (*u->sec)(ORDER(obj->type), buf, sec); 503 } 504 r = 1; 505 err: 506 free(buf); 507 return r; 508 } 509 510 static int 511 readstrtbl(Obj *obj, FILE *fp) 512 { 513 char *s; 514 int idx; 515 Elfsec *tbl, *sec; 516 Elf *elf = obj->data; 517 Elfhdr *hdr = &elf->hdr; 518 519 if (hdr->shstrndx != SHN_XINDEX) { 520 idx = hdr->shstrndx; 521 } else { 522 if (hdr->shnum == 0) 523 return 0; 524 sec = elf->secs; 525 if (sec->link > INT_MAX) 526 return 0; 527 idx = sec->link; 528 } 529 if (idx > elf->nsec || elf->secs[idx].type != SHT_STRTAB) 530 return 0; 531 elf->secstrtbl = idx; 532 533 for (sec = elf->secs; sec < &elf->secs[elf->nsec]; ++sec) { 534 if (sec->type != SHT_STRTAB) 535 continue; 536 537 if (sec->size > SIZE_MAX) 538 return 0; 539 if ((s = malloc(sec->size)) == NULL) 540 return 0; 541 sec->strtbl = s; 542 543 if (!objpos(obj, fp, sec->offset)) 544 return 0; 545 if (fread(s, sec->size, 1, fp) != 1) 546 return 0; 547 } 548 549 return 1; 550 } 551 552 static int 553 secsize(Elfsec *sec, int onent, int entsiz) 554 { 555 unsigned long long nent; 556 557 if (sec->entsize == 0 || sec->entsize < entsiz) 558 return -1; 559 nent = sec->size / sec->entsize; 560 if (nent > INT_MAX - onent) 561 return -1; 562 563 return nent; 564 } 565 566 static int 567 readsyms(Obj *obj, Elfsec *sec, FILE *fp) 568 { 569 int r = 0, n, oldn; 570 Elfsym *sym; 571 Elfsec *tbl; 572 Elf *elf = obj->data; 573 Elfunpack *u = elf->unpack; 574 Elfhdr *hdr = &elf->hdr; 575 unsigned char *buf; 576 577 if ((n = secsize(sec, elf->nsym, u->symsiz)) <= 0) 578 return n; 579 if ((buf = malloc(sec->entsize)) == NULL) 580 return 0; 581 582 oldn = elf->nsym; 583 sym = realloc(elf->syms, (oldn + n) * sizeof(Elfsym)); 584 if (!sym) 585 goto err; 586 elf->syms = sym; 587 elf->nsym += n; 588 589 if (!objpos(obj, fp, sec->offset)) 590 goto err; 591 592 if (sec->link >= hdr->shnum) 593 goto err; 594 tbl = &elf->secs[sec->link]; 595 if (tbl->type != SHT_STRTAB) 596 goto err; 597 598 for (sym = &elf->syms[oldn] ; n-- > 0 ; ++sym) { 599 if (fread(buf, sec->entsize, 1, fp) != 1) 600 goto err; 601 (*u->sym)(ORDER(obj->type), buf, sym); 602 sym->symsec = sec; 603 if (sym->st_name >= tbl->size) 604 goto err; 605 sym->name = &tbl->strtbl[sym->st_name]; 606 607 switch (sym->shndx) { 608 case SHN_XINDEX: 609 /* 610 * Elf supports an extension mechanism to allow 611 * indexes bigger than 4 bytes. We don't care 612 * and we reject elf files using this feature. 613 */ 614 goto err; 615 case SHN_UNDEF: 616 case SHN_ABS: 617 case SHN_COMMON: 618 break; 619 default: 620 if (sym->shndx >= elf->nsec) 621 goto err; 622 break; 623 } 624 } 625 r = 1; 626 627 err: 628 free(buf); 629 return r; 630 } 631 632 static int 633 readrels(Obj *obj, Elfsec *sec, FILE *fp) 634 { 635 int r = 0, oldn, n, min; 636 Elf *elf = obj->data; 637 Elfunpack *u = elf->unpack; 638 Elfrel *rp; 639 void (*fn)(int, unsigned char *, Elfrel *); 640 unsigned char *buf; 641 642 if (sec->type == SHT_RELA) { 643 fn = u->rela; 644 min = u->relasiz; 645 } else { 646 fn = u->rel; 647 min = u->relsiz; 648 } 649 650 if (!objpos(obj, fp, sec->offset)) 651 goto err; 652 653 if ((n = secsize(sec, elf->nrel, min)) <= 0) 654 return n; 655 if ((buf = malloc(sec->entsize)) == NULL) 656 return 0; 657 658 oldn = elf->nrel; 659 rp = realloc(elf->rels, (oldn + n) * sizeof(Elfrel)); 660 if (!rp) 661 goto err; 662 elf->rels = rp; 663 elf->nrel += n; 664 665 for (rp = &elf->rels[oldn]; n-- > 0; ++rp) { 666 if (fread(buf, sec->entsize, 1, fp) != 1) 667 goto err; 668 (*fn)(ORDER(obj->type), buf, rp); 669 } 670 r = 1; 671 672 err: 673 free(buf); 674 return r; 675 } 676 677 static int 678 procsecs(Obj *obj, FILE *fp) 679 { 680 Elf *elf = obj->data; 681 Elfsec *tbl, *sec; 682 683 tbl = &elf->secs[elf->secstrtbl]; 684 for (sec = elf->secs; sec < &elf->secs[elf->nsec]; ++sec) { 685 if (sec->sh_name >= tbl->size) 686 return 0; 687 sec->name = &tbl->strtbl[sec->sh_name]; 688 689 switch (sec->type) { 690 case SHT_DYNSYM: 691 case SHT_SYMTAB: 692 if (!readsyms(obj, sec, fp)) 693 return 0; 694 break; 695 case SHT_RELA: 696 case SHT_REL: 697 if (!readrels(obj, sec, fp)) 698 return 0; 699 break; 700 } 701 } 702 703 return 1; 704 } 705 706 int 707 elfread(Obj *obj, FILE *fp) 708 { 709 fpos_t pos; 710 Elf *elf = obj->data; 711 unsigned char buf[EI_CLASS+1]; 712 713 fgetpos(fp, &pos); 714 fread(buf, sizeof(buf), 1, fp); 715 fsetpos(fp, &pos); 716 717 if (buf[EI_CLASS] == ELFCLASS64) { 718 if (elf->is32) 719 return 0; 720 elf->is32 = 0; 721 elf->unpack = &unpack64; 722 } else { 723 elf->is32 = 1; 724 elf->unpack = &unpack32; 725 } 726 727 if (!readhdr(obj, fp)) 728 return -1; 729 if (!readphdr(obj, fp)) 730 return -1; 731 if (!readshdr(obj, fp)) 732 return -1; 733 if (!readstrtbl(obj, fp)) 734 return -1; 735 if (!procsecs(obj, fp)) 736 return -1; 737 738 return 0; 739 } 740 741 struct elfunpack unpack64 = { 742 .hdr = unpack_hdr64, 743 .phdr = unpack_phdr64, 744 .sec = unpack_shdr64, 745 .sym = unpack_sym64, 746 .rel = unpack_rel64, 747 .rela = unpack_rela64, 748 749 .hdrsiz = ELFH64SZ, 750 .phdrsiz = ELFP64SZ, 751 .shentsiz = ELFS64SZ, 752 .symsiz = ELFE64SZ, 753 .relsiz = ELFR64SZ, 754 .relasiz = ELFRA64SZ, 755 }; 756 757 struct elfunpack unpack32 = { 758 .hdr = unpack_hdr32, 759 .phdr = unpack_phdr32, 760 .sec = unpack_shdr32, 761 .sym = unpack_sym32, 762 .rel = unpack_rel32, 763 .rela = unpack_rela32, 764 765 .hdrsiz = ELFH32SZ, 766 .phdrsiz = ELFP32SZ, 767 .shentsiz = ELFS32SZ, 768 .symsiz = ELFE32SZ, 769 .relsiz = ELFR32SZ, 770 .relasiz = ELFRA32SZ, 771 };