| .. | .. |
|---|
| 11 | 11 | #define Elf_Shdr ElfW(Shdr) |
|---|
| 12 | 12 | #define Elf_Sym ElfW(Sym) |
|---|
| 13 | 13 | |
|---|
| 14 | | -static Elf_Ehdr ehdr; |
|---|
| 14 | +static Elf_Ehdr ehdr; |
|---|
| 15 | +static unsigned long shnum; |
|---|
| 16 | +static unsigned int shstrndx; |
|---|
| 15 | 17 | |
|---|
| 16 | 18 | struct relocs { |
|---|
| 17 | 19 | uint32_t *offset; |
|---|
| .. | .. |
|---|
| 131 | 133 | REG_EXTENDED|REG_NOSUB); |
|---|
| 132 | 134 | |
|---|
| 133 | 135 | if (err) { |
|---|
| 134 | | - regerror(err, &sym_regex_c[i], errbuf, sizeof errbuf); |
|---|
| 136 | + regerror(err, &sym_regex_c[i], errbuf, sizeof(errbuf)); |
|---|
| 135 | 137 | die("%s", errbuf); |
|---|
| 136 | 138 | } |
|---|
| 137 | 139 | } |
|---|
| .. | .. |
|---|
| 197 | 199 | #if ELF_BITS == 64 |
|---|
| 198 | 200 | REL_TYPE(R_X86_64_NONE), |
|---|
| 199 | 201 | REL_TYPE(R_X86_64_64), |
|---|
| 202 | + REL_TYPE(R_X86_64_PC64), |
|---|
| 200 | 203 | REL_TYPE(R_X86_64_PC32), |
|---|
| 201 | 204 | REL_TYPE(R_X86_64_GOT32), |
|---|
| 202 | 205 | REL_TYPE(R_X86_64_PLT32), |
|---|
| .. | .. |
|---|
| 241 | 244 | { |
|---|
| 242 | 245 | const char *sec_strtab; |
|---|
| 243 | 246 | const char *name; |
|---|
| 244 | | - sec_strtab = secs[ehdr.e_shstrndx].strtab; |
|---|
| 247 | + sec_strtab = secs[shstrndx].strtab; |
|---|
| 245 | 248 | name = "<noname>"; |
|---|
| 246 | | - if (shndx < ehdr.e_shnum) { |
|---|
| 249 | + if (shndx < shnum) { |
|---|
| 247 | 250 | name = sec_strtab + secs[shndx].shdr.sh_name; |
|---|
| 248 | 251 | } |
|---|
| 249 | 252 | else if (shndx == SHN_ABS) { |
|---|
| .. | .. |
|---|
| 271 | 274 | static Elf_Sym *sym_lookup(const char *symname) |
|---|
| 272 | 275 | { |
|---|
| 273 | 276 | int i; |
|---|
| 274 | | - for (i = 0; i < ehdr.e_shnum; i++) { |
|---|
| 277 | + for (i = 0; i < shnum; i++) { |
|---|
| 275 | 278 | struct section *sec = &secs[i]; |
|---|
| 276 | 279 | long nsyms; |
|---|
| 277 | 280 | char *strtab; |
|---|
| .. | .. |
|---|
| 366 | 369 | ehdr.e_shnum = elf_half_to_cpu(ehdr.e_shnum); |
|---|
| 367 | 370 | ehdr.e_shstrndx = elf_half_to_cpu(ehdr.e_shstrndx); |
|---|
| 368 | 371 | |
|---|
| 369 | | - if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) { |
|---|
| 372 | + shnum = ehdr.e_shnum; |
|---|
| 373 | + shstrndx = ehdr.e_shstrndx; |
|---|
| 374 | + |
|---|
| 375 | + if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) |
|---|
| 370 | 376 | die("Unsupported ELF header type\n"); |
|---|
| 371 | | - } |
|---|
| 372 | | - if (ehdr.e_machine != ELF_MACHINE) { |
|---|
| 377 | + if (ehdr.e_machine != ELF_MACHINE) |
|---|
| 373 | 378 | die("Not for %s\n", ELF_MACHINE_NAME); |
|---|
| 374 | | - } |
|---|
| 375 | | - if (ehdr.e_version != EV_CURRENT) { |
|---|
| 379 | + if (ehdr.e_version != EV_CURRENT) |
|---|
| 376 | 380 | die("Unknown ELF version\n"); |
|---|
| 377 | | - } |
|---|
| 378 | | - if (ehdr.e_ehsize != sizeof(Elf_Ehdr)) { |
|---|
| 381 | + if (ehdr.e_ehsize != sizeof(Elf_Ehdr)) |
|---|
| 379 | 382 | die("Bad Elf header size\n"); |
|---|
| 380 | | - } |
|---|
| 381 | | - if (ehdr.e_phentsize != sizeof(Elf_Phdr)) { |
|---|
| 383 | + if (ehdr.e_phentsize != sizeof(Elf_Phdr)) |
|---|
| 382 | 384 | die("Bad program header entry\n"); |
|---|
| 383 | | - } |
|---|
| 384 | | - if (ehdr.e_shentsize != sizeof(Elf_Shdr)) { |
|---|
| 385 | + if (ehdr.e_shentsize != sizeof(Elf_Shdr)) |
|---|
| 385 | 386 | die("Bad section header entry\n"); |
|---|
| 387 | + |
|---|
| 388 | + |
|---|
| 389 | + if (shnum == SHN_UNDEF || shstrndx == SHN_XINDEX) { |
|---|
| 390 | + Elf_Shdr shdr; |
|---|
| 391 | + |
|---|
| 392 | + if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) |
|---|
| 393 | + die("Seek to %d failed: %s\n", ehdr.e_shoff, strerror(errno)); |
|---|
| 394 | + |
|---|
| 395 | + if (fread(&shdr, sizeof(shdr), 1, fp) != 1) |
|---|
| 396 | + die("Cannot read initial ELF section header: %s\n", strerror(errno)); |
|---|
| 397 | + |
|---|
| 398 | + if (shnum == SHN_UNDEF) |
|---|
| 399 | + shnum = elf_xword_to_cpu(shdr.sh_size); |
|---|
| 400 | + |
|---|
| 401 | + if (shstrndx == SHN_XINDEX) |
|---|
| 402 | + shstrndx = elf_word_to_cpu(shdr.sh_link); |
|---|
| 386 | 403 | } |
|---|
| 387 | | - if (ehdr.e_shstrndx >= ehdr.e_shnum) { |
|---|
| 404 | + |
|---|
| 405 | + if (shstrndx >= shnum) |
|---|
| 388 | 406 | die("String table index out of bounds\n"); |
|---|
| 389 | | - } |
|---|
| 390 | 407 | } |
|---|
| 391 | 408 | |
|---|
| 392 | 409 | static void read_shdrs(FILE *fp) |
|---|
| .. | .. |
|---|
| 394 | 411 | int i; |
|---|
| 395 | 412 | Elf_Shdr shdr; |
|---|
| 396 | 413 | |
|---|
| 397 | | - secs = calloc(ehdr.e_shnum, sizeof(struct section)); |
|---|
| 414 | + secs = calloc(shnum, sizeof(struct section)); |
|---|
| 398 | 415 | if (!secs) { |
|---|
| 399 | 416 | die("Unable to allocate %d section headers\n", |
|---|
| 400 | | - ehdr.e_shnum); |
|---|
| 417 | + shnum); |
|---|
| 401 | 418 | } |
|---|
| 402 | 419 | if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) { |
|---|
| 403 | 420 | die("Seek to %d failed: %s\n", |
|---|
| 404 | 421 | ehdr.e_shoff, strerror(errno)); |
|---|
| 405 | 422 | } |
|---|
| 406 | | - for (i = 0; i < ehdr.e_shnum; i++) { |
|---|
| 423 | + for (i = 0; i < shnum; i++) { |
|---|
| 407 | 424 | struct section *sec = &secs[i]; |
|---|
| 408 | | - if (fread(&shdr, sizeof shdr, 1, fp) != 1) |
|---|
| 425 | + if (fread(&shdr, sizeof(shdr), 1, fp) != 1) |
|---|
| 409 | 426 | die("Cannot read ELF section headers %d/%d: %s\n", |
|---|
| 410 | | - i, ehdr.e_shnum, strerror(errno)); |
|---|
| 427 | + i, shnum, strerror(errno)); |
|---|
| 411 | 428 | sec->shdr.sh_name = elf_word_to_cpu(shdr.sh_name); |
|---|
| 412 | 429 | sec->shdr.sh_type = elf_word_to_cpu(shdr.sh_type); |
|---|
| 413 | 430 | sec->shdr.sh_flags = elf_xword_to_cpu(shdr.sh_flags); |
|---|
| .. | .. |
|---|
| 418 | 435 | sec->shdr.sh_info = elf_word_to_cpu(shdr.sh_info); |
|---|
| 419 | 436 | sec->shdr.sh_addralign = elf_xword_to_cpu(shdr.sh_addralign); |
|---|
| 420 | 437 | sec->shdr.sh_entsize = elf_xword_to_cpu(shdr.sh_entsize); |
|---|
| 421 | | - if (sec->shdr.sh_link < ehdr.e_shnum) |
|---|
| 438 | + if (sec->shdr.sh_link < shnum) |
|---|
| 422 | 439 | sec->link = &secs[sec->shdr.sh_link]; |
|---|
| 423 | 440 | } |
|---|
| 424 | 441 | |
|---|
| .. | .. |
|---|
| 427 | 444 | static void read_strtabs(FILE *fp) |
|---|
| 428 | 445 | { |
|---|
| 429 | 446 | int i; |
|---|
| 430 | | - for (i = 0; i < ehdr.e_shnum; i++) { |
|---|
| 447 | + for (i = 0; i < shnum; i++) { |
|---|
| 431 | 448 | struct section *sec = &secs[i]; |
|---|
| 432 | 449 | if (sec->shdr.sh_type != SHT_STRTAB) { |
|---|
| 433 | 450 | continue; |
|---|
| .. | .. |
|---|
| 452 | 469 | static void read_symtabs(FILE *fp) |
|---|
| 453 | 470 | { |
|---|
| 454 | 471 | int i,j; |
|---|
| 455 | | - for (i = 0; i < ehdr.e_shnum; i++) { |
|---|
| 472 | + for (i = 0; i < shnum; i++) { |
|---|
| 456 | 473 | struct section *sec = &secs[i]; |
|---|
| 457 | 474 | if (sec->shdr.sh_type != SHT_SYMTAB) { |
|---|
| 458 | 475 | continue; |
|---|
| .. | .. |
|---|
| 485 | 502 | static void read_relocs(FILE *fp) |
|---|
| 486 | 503 | { |
|---|
| 487 | 504 | int i,j; |
|---|
| 488 | | - for (i = 0; i < ehdr.e_shnum; i++) { |
|---|
| 505 | + for (i = 0; i < shnum; i++) { |
|---|
| 489 | 506 | struct section *sec = &secs[i]; |
|---|
| 490 | 507 | if (sec->shdr.sh_type != SHT_REL_TYPE) { |
|---|
| 491 | 508 | continue; |
|---|
| .. | .. |
|---|
| 528 | 545 | |
|---|
| 529 | 546 | printf("Absolute symbols\n"); |
|---|
| 530 | 547 | printf(" Num: Value Size Type Bind Visibility Name\n"); |
|---|
| 531 | | - for (i = 0; i < ehdr.e_shnum; i++) { |
|---|
| 548 | + for (i = 0; i < shnum; i++) { |
|---|
| 532 | 549 | struct section *sec = &secs[i]; |
|---|
| 533 | 550 | char *sym_strtab; |
|---|
| 534 | 551 | int j; |
|---|
| .. | .. |
|---|
| 566 | 583 | else |
|---|
| 567 | 584 | format = "%08"PRIx32" %08"PRIx32" %10s %08"PRIx32" %s\n"; |
|---|
| 568 | 585 | |
|---|
| 569 | | - for (i = 0; i < ehdr.e_shnum; i++) { |
|---|
| 586 | + for (i = 0; i < shnum; i++) { |
|---|
| 570 | 587 | struct section *sec = &secs[i]; |
|---|
| 571 | 588 | struct section *sec_applies, *sec_symtab; |
|---|
| 572 | 589 | char *sym_strtab; |
|---|
| .. | .. |
|---|
| 650 | 667 | { |
|---|
| 651 | 668 | int i; |
|---|
| 652 | 669 | /* Walk through the relocations */ |
|---|
| 653 | | - for (i = 0; i < ehdr.e_shnum; i++) { |
|---|
| 670 | + for (i = 0; i < shnum; i++) { |
|---|
| 654 | 671 | char *sym_strtab; |
|---|
| 655 | 672 | Elf_Sym *sh_symtab; |
|---|
| 656 | 673 | struct section *sec_applies, *sec_symtab; |
|---|
| .. | .. |
|---|
| 706 | 723 | static void percpu_init(void) |
|---|
| 707 | 724 | { |
|---|
| 708 | 725 | int i; |
|---|
| 709 | | - for (i = 0; i < ehdr.e_shnum; i++) { |
|---|
| 726 | + for (i = 0; i < shnum; i++) { |
|---|
| 710 | 727 | ElfW(Sym) *sym; |
|---|
| 711 | 728 | if (strcmp(sec_name(i), ".data..percpu")) |
|---|
| 712 | 729 | continue; |
|---|
| .. | .. |
|---|
| 738 | 755 | * __per_cpu_load |
|---|
| 739 | 756 | * |
|---|
| 740 | 757 | * The "gold" linker incorrectly associates: |
|---|
| 741 | | - * init_per_cpu__irq_stack_union |
|---|
| 758 | + * init_per_cpu__fixed_percpu_data |
|---|
| 742 | 759 | * init_per_cpu__gdt_page |
|---|
| 743 | 760 | */ |
|---|
| 744 | 761 | static int is_percpu_sym(ElfW(Sym) *sym, const char *symname) |
|---|
| .. | .. |
|---|
| 783 | 800 | add_reloc(&relocs32neg, offset); |
|---|
| 784 | 801 | break; |
|---|
| 785 | 802 | |
|---|
| 803 | + case R_X86_64_PC64: |
|---|
| 804 | + /* |
|---|
| 805 | + * Only used by jump labels |
|---|
| 806 | + */ |
|---|
| 807 | + if (is_percpu_sym(sym, symname)) |
|---|
| 808 | + die("Invalid R_X86_64_PC64 relocation against per-CPU symbol %s\n", |
|---|
| 809 | + symname); |
|---|
| 810 | + break; |
|---|
| 811 | + |
|---|
| 786 | 812 | case R_X86_64_8: |
|---|
| 787 | 813 | if (!shn_abs || !is_reloc(S_ABS, symname)) |
|---|
| 788 | 814 | die("Non-whitelisted %s relocation: %s\n", |
|---|