diff options
| author | Karl Heuer | 1996-07-15 22:00:12 +0000 |
|---|---|---|
| committer | Karl Heuer | 1996-07-15 22:00:12 +0000 |
| commit | 9da3f2d46ec6e9d337ff0bae5b4d382bfdf0ea51 (patch) | |
| tree | 1170119c260bef7cd26e9624c3c44ad51caa5b4f /src | |
| parent | e493299546bcc220e94e3d53501607f0e7d7823f (diff) | |
| download | emacs-9da3f2d46ec6e9d337ff0bae5b4d382bfdf0ea51.tar.gz emacs-9da3f2d46ec6e9d337ff0bae5b4d382bfdf0ea51.zip | |
Add 64-bit ELF and Alpha/ELF support.
Diffstat (limited to 'src')
| -rw-r--r-- | src/unexelf.c | 126 |
1 files changed, 86 insertions, 40 deletions
diff --git a/src/unexelf.c b/src/unexelf.c index 60e82cc6a95..1575b23b51d 100644 --- a/src/unexelf.c +++ b/src/unexelf.c | |||
| @@ -423,6 +423,22 @@ Filesz Memsz Flags Align | |||
| 423 | #include <elf.h> | 423 | #include <elf.h> |
| 424 | #include <sys/mman.h> | 424 | #include <sys/mman.h> |
| 425 | 425 | ||
| 426 | #ifdef __alpha__ | ||
| 427 | # include <sym.h> /* get COFF debugging symbol table declaration */ | ||
| 428 | #endif | ||
| 429 | |||
| 430 | #ifdef __GNU_LIBRARY__ | ||
| 431 | # include <link.h> /* get definition of ElfW */ | ||
| 432 | #endif | ||
| 433 | |||
| 434 | #ifndef ElfW | ||
| 435 | # ifdef __STDC__ | ||
| 436 | # define ElfW(type) Elf32_##type | ||
| 437 | # else | ||
| 438 | # define ElfW(type) Elf32_/**/type | ||
| 439 | # endif | ||
| 440 | #endif | ||
| 441 | |||
| 426 | #ifndef emacs | 442 | #ifndef emacs |
| 427 | #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1) | 443 | #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1) |
| 428 | #else | 444 | #else |
| @@ -462,13 +478,13 @@ extern void fatal (char *, ...); | |||
| 462 | */ | 478 | */ |
| 463 | 479 | ||
| 464 | #define OLD_SECTION_H(n) \ | 480 | #define OLD_SECTION_H(n) \ |
| 465 | (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) | 481 | (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) |
| 466 | #define NEW_SECTION_H(n) \ | 482 | #define NEW_SECTION_H(n) \ |
| 467 | (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) | 483 | (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) |
| 468 | #define OLD_PROGRAM_H(n) \ | 484 | #define OLD_PROGRAM_H(n) \ |
| 469 | (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) | 485 | (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) |
| 470 | #define NEW_PROGRAM_H(n) \ | 486 | #define NEW_PROGRAM_H(n) \ |
| 471 | (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) | 487 | (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) |
| 472 | 488 | ||
| 473 | #define PATCH_INDEX(n) \ | 489 | #define PATCH_INDEX(n) \ |
| 474 | do { \ | 490 | do { \ |
| @@ -510,19 +526,19 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 510 | /* Pointers to the file, program and section headers for the old and new | 526 | /* Pointers to the file, program and section headers for the old and new |
| 511 | * files. | 527 | * files. |
| 512 | */ | 528 | */ |
| 513 | Elf32_Ehdr *old_file_h, *new_file_h; | 529 | ElfW(Ehdr) *old_file_h, *new_file_h; |
| 514 | Elf32_Phdr *old_program_h, *new_program_h; | 530 | ElfW(Phdr) *old_program_h, *new_program_h; |
| 515 | Elf32_Shdr *old_section_h, *new_section_h; | 531 | ElfW(Shdr) *old_section_h, *new_section_h; |
| 516 | 532 | ||
| 517 | /* Point to the section name table in the old file */ | 533 | /* Point to the section name table in the old file */ |
| 518 | char *old_section_names; | 534 | char *old_section_names; |
| 519 | 535 | ||
| 520 | Elf32_Addr old_bss_addr, new_bss_addr; | 536 | ElfW(Addr) old_bss_addr, new_bss_addr; |
| 521 | Elf32_Word old_bss_size, new_data2_size; | 537 | ElfW(Addr) old_bss_size, new_data2_size; |
| 522 | Elf32_Off new_data2_offset; | 538 | ElfW(Off) new_data2_offset; |
| 523 | Elf32_Addr new_data2_addr; | 539 | ElfW(Addr) new_data2_addr; |
| 524 | 540 | ||
| 525 | int n, nn, old_bss_index, old_data_index, new_data2_index; | 541 | int n, nn, old_bss_index, old_data_index; |
| 526 | struct stat stat_buf; | 542 | struct stat stat_buf; |
| 527 | 543 | ||
| 528 | /* Open the old file & map it into the address space. */ | 544 | /* Open the old file & map it into the address space. */ |
| @@ -541,15 +557,15 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 541 | fatal ("Can't mmap (%s): errno %d\n", old_name, errno); | 557 | fatal ("Can't mmap (%s): errno %d\n", old_name, errno); |
| 542 | 558 | ||
| 543 | #ifdef DEBUG | 559 | #ifdef DEBUG |
| 544 | fprintf (stderr, "mmap (%s, %x) -> %x\n", old_name, stat_buf.st_size, | 560 | fprintf (stderr, "mmap (%s, %lx) -> %lx\n", old_name, stat_buf.st_size, |
| 545 | old_base); | 561 | (unsigned long) old_base); |
| 546 | #endif | 562 | #endif |
| 547 | 563 | ||
| 548 | /* Get pointers to headers & section names */ | 564 | /* Get pointers to headers & section names */ |
| 549 | 565 | ||
| 550 | old_file_h = (Elf32_Ehdr *) old_base; | 566 | old_file_h = (ElfW(Ehdr) *) old_base; |
| 551 | old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff); | 567 | old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff); |
| 552 | old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff); | 568 | old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff); |
| 553 | old_section_names = (char *) old_base | 569 | old_section_names = (char *) old_base |
| 554 | + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; | 570 | + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; |
| 555 | 571 | ||
| @@ -574,7 +590,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 574 | old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; | 590 | old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; |
| 575 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; | 591 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; |
| 576 | #if defined(emacs) || !defined(DEBUG) | 592 | #if defined(emacs) || !defined(DEBUG) |
| 577 | new_bss_addr = (Elf32_Addr) sbrk (0); | 593 | new_bss_addr = (ElfW(Addr)) sbrk (0); |
| 578 | #else | 594 | #else |
| 579 | new_bss_addr = old_bss_addr + old_bss_size + 0x1234; | 595 | new_bss_addr = old_bss_addr + old_bss_size + 0x1234; |
| 580 | #endif | 596 | #endif |
| @@ -584,15 +600,16 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 584 | 600 | ||
| 585 | #ifdef DEBUG | 601 | #ifdef DEBUG |
| 586 | fprintf (stderr, "old_bss_index %d\n", old_bss_index); | 602 | fprintf (stderr, "old_bss_index %d\n", old_bss_index); |
| 587 | fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); | 603 | fprintf (stderr, "old_bss_addr %lx\n", old_bss_addr); |
| 588 | fprintf (stderr, "old_bss_size %x\n", old_bss_size); | 604 | fprintf (stderr, "old_bss_size %lx\n", old_bss_size); |
| 589 | fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); | 605 | fprintf (stderr, "new_bss_addr %lx\n", new_bss_addr); |
| 590 | fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); | 606 | fprintf (stderr, "new_data2_addr %lx\n", new_data2_addr); |
| 591 | fprintf (stderr, "new_data2_size %x\n", new_data2_size); | 607 | fprintf (stderr, "new_data2_size %lx\n", new_data2_size); |
| 592 | fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); | 608 | fprintf (stderr, "new_data2_offset %lx\n", new_data2_offset); |
| 593 | #endif | 609 | #endif |
| 594 | 610 | ||
| 595 | if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size) | 611 | if ((unsigned long) new_bss_addr |
| 612 | < (unsigned long) old_bss_addr + old_bss_size) | ||
| 596 | fatal (".bss shrank when undumping???\n", 0, 0); | 613 | fatal (".bss shrank when undumping???\n", 0, 0); |
| 597 | 614 | ||
| 598 | /* Set the output file to the right size and mmap it. Set | 615 | /* Set the output file to the right size and mmap it. Set |
| @@ -620,9 +637,9 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 620 | if (new_base == (caddr_t) -1) | 637 | if (new_base == (caddr_t) -1) |
| 621 | fatal ("Can't mmap (%s): errno %d\n", new_name, errno); | 638 | fatal ("Can't mmap (%s): errno %d\n", new_name, errno); |
| 622 | 639 | ||
| 623 | new_file_h = (Elf32_Ehdr *) new_base; | 640 | new_file_h = (ElfW(Ehdr) *) new_base; |
| 624 | new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff); | 641 | new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff); |
| 625 | new_section_h = (Elf32_Shdr *) | 642 | new_section_h = (ElfW(Shdr) *) |
| 626 | ((byte *) new_base + old_file_h->e_shoff + new_data2_size); | 643 | ((byte *) new_base + old_file_h->e_shoff + new_data2_size); |
| 627 | 644 | ||
| 628 | /* Make our new file, program and section headers as copies of the | 645 | /* Make our new file, program and section headers as copies of the |
| @@ -644,9 +661,9 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 644 | new_file_h->e_shnum += 1; | 661 | new_file_h->e_shnum += 1; |
| 645 | 662 | ||
| 646 | #ifdef DEBUG | 663 | #ifdef DEBUG |
| 647 | fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff); | 664 | fprintf (stderr, "Old section offset %lx\n", old_file_h->e_shoff); |
| 648 | fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); | 665 | fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); |
| 649 | fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff); | 666 | fprintf (stderr, "New section offset %lx\n", new_file_h->e_shoff); |
| 650 | fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); | 667 | fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); |
| 651 | #endif | 668 | #endif |
| 652 | 669 | ||
| @@ -661,7 +678,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 661 | for (n = new_file_h->e_phnum - 1; n >= 0; n--) | 678 | for (n = new_file_h->e_phnum - 1; n >= 0; n--) |
| 662 | { | 679 | { |
| 663 | /* Compute maximum of all requirements for alignment of section. */ | 680 | /* Compute maximum of all requirements for alignment of section. */ |
| 664 | int alignment = (NEW_PROGRAM_H (n)).p_align; | 681 | unsigned int alignment = (NEW_PROGRAM_H (n)).p_align; |
| 665 | if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) | 682 | if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) |
| 666 | alignment = OLD_SECTION_H (old_bss_index).sh_addralign; | 683 | alignment = OLD_SECTION_H (old_bss_index).sh_addralign; |
| 667 | 684 | ||
| @@ -808,13 +825,34 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 808 | memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, | 825 | memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, |
| 809 | NEW_SECTION_H (nn).sh_size); | 826 | NEW_SECTION_H (nn).sh_size); |
| 810 | 827 | ||
| 828 | #ifdef __alpha__ | ||
| 829 | /* Update Alpha COFF symbol table: */ | ||
| 830 | if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug") | ||
| 831 | == 0) | ||
| 832 | { | ||
| 833 | pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base); | ||
| 834 | |||
| 835 | symhdr->cbLineOffset += new_data2_size; | ||
| 836 | symhdr->cbDnOffset += new_data2_size; | ||
| 837 | symhdr->cbPdOffset += new_data2_size; | ||
| 838 | symhdr->cbSymOffset += new_data2_size; | ||
| 839 | symhdr->cbOptOffset += new_data2_size; | ||
| 840 | symhdr->cbAuxOffset += new_data2_size; | ||
| 841 | symhdr->cbSsOffset += new_data2_size; | ||
| 842 | symhdr->cbSsExtOffset += new_data2_size; | ||
| 843 | symhdr->cbFdOffset += new_data2_size; | ||
| 844 | symhdr->cbRfdOffset += new_data2_size; | ||
| 845 | symhdr->cbExtOffset += new_data2_size; | ||
| 846 | } | ||
| 847 | #endif /* __alpha__ */ | ||
| 848 | |||
| 811 | /* If it is the symbol table, its st_shndx field needs to be patched. */ | 849 | /* If it is the symbol table, its st_shndx field needs to be patched. */ |
| 812 | if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB | 850 | if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB |
| 813 | || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) | 851 | || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) |
| 814 | { | 852 | { |
| 815 | Elf32_Shdr *spt = &NEW_SECTION_H (nn); | 853 | ElfW(Shdr) *spt = &NEW_SECTION_H (nn); |
| 816 | unsigned int num = spt->sh_size / spt->sh_entsize; | 854 | unsigned int num = spt->sh_size / spt->sh_entsize; |
| 817 | Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset + | 855 | ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset + |
| 818 | new_base); | 856 | new_base); |
| 819 | for (; num--; sym++) | 857 | for (; num--; sym++) |
| 820 | { | 858 | { |
| @@ -832,7 +870,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 832 | for (n = new_file_h->e_shnum - 1; n; n--) | 870 | for (n = new_file_h->e_shnum - 1; n; n--) |
| 833 | { | 871 | { |
| 834 | byte *symnames; | 872 | byte *symnames; |
| 835 | Elf32_Sym *symp, *symendp; | 873 | ElfW(Sym) *symp, *symendp; |
| 836 | 874 | ||
| 837 | if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM | 875 | if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM |
| 838 | && NEW_SECTION_H (n).sh_type != SHT_SYMTAB) | 876 | && NEW_SECTION_H (n).sh_type != SHT_SYMTAB) |
| @@ -840,8 +878,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 840 | 878 | ||
| 841 | symnames = ((byte *) new_base | 879 | symnames = ((byte *) new_base |
| 842 | + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset); | 880 | + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset); |
| 843 | symp = (Elf32_Sym *) (NEW_SECTION_H (n).sh_offset + new_base); | 881 | symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base); |
| 844 | symendp = (Elf32_Sym *) ((byte *)symp + NEW_SECTION_H (n).sh_size); | 882 | symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size); |
| 845 | 883 | ||
| 846 | for (; symp < symendp; symp ++) | 884 | for (; symp < symendp; symp ++) |
| 847 | if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0 | 885 | if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0 |
| @@ -853,7 +891,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 853 | that it can undo relocations performed by the runtime linker. */ | 891 | that it can undo relocations performed by the runtime linker. */ |
| 854 | for (n = new_file_h->e_shnum - 1; n; n--) | 892 | for (n = new_file_h->e_shnum - 1; n; n--) |
| 855 | { | 893 | { |
| 856 | Elf32_Shdr section = NEW_SECTION_H (n); | 894 | ElfW(Shdr) section = NEW_SECTION_H (n); |
| 857 | switch (section.sh_type) { | 895 | switch (section.sh_type) { |
| 858 | default: | 896 | default: |
| 859 | break; | 897 | break; |
| @@ -867,14 +905,22 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 867 | || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | 905 | || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), |
| 868 | ".data1")) | 906 | ".data1")) |
| 869 | { | 907 | { |
| 870 | Elf32_Addr offset = NEW_SECTION_H (nn).sh_addr - | 908 | ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - |
| 871 | NEW_SECTION_H (nn).sh_offset; | 909 | NEW_SECTION_H (nn).sh_offset; |
| 872 | caddr_t reloc = old_base + section.sh_offset, end; | 910 | caddr_t reloc = old_base + section.sh_offset, end; |
| 873 | for (end = reloc + section.sh_size; reloc < end; | 911 | for (end = reloc + section.sh_size; reloc < end; |
| 874 | reloc += section.sh_entsize) | 912 | reloc += section.sh_entsize) |
| 875 | { | 913 | { |
| 876 | Elf32_Addr addr = ((Elf32_Rel *) reloc)->r_offset - offset; | 914 | ElfW(Addr) addr; |
| 877 | memcpy (new_base + addr, old_base + addr, 4); | 915 | #ifdef __alpha__ |
| 916 | /* The Alpha ELF binutils currently have a bug that | ||
| 917 | sometimes results in relocs that contain all | ||
| 918 | zeroes. Work around this for now... */ | ||
| 919 | if (((ElfW(Rel) *) reloc)->r_offset == 0) | ||
| 920 | continue; | ||
| 921 | #endif | ||
| 922 | addr = ((ElfW(Rel) *) reloc)->r_offset - offset; | ||
| 923 | memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr))); | ||
| 878 | } | 924 | } |
| 879 | } | 925 | } |
| 880 | break; | 926 | break; |