.. | .. |
---|
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", |
---|