Mercurial > emacs
comparison src/unexelf.c @ 15719:fdac027af4e1
Undo previous change.
author | Karl Heuer <kwzh@gnu.org> |
---|---|
date | Tue, 16 Jul 1996 22:39:31 +0000 |
parents | 8978d34759dc |
children | 2c15b1cd3b84 |
comparison
equal
deleted
inserted
replaced
15718:8db4678b2fd8 | 15719:fdac027af4e1 |
---|---|
420 #include <errno.h> | 420 #include <errno.h> |
421 #include <unistd.h> | 421 #include <unistd.h> |
422 #include <fcntl.h> | 422 #include <fcntl.h> |
423 #include <elf.h> | 423 #include <elf.h> |
424 #include <sys/mman.h> | 424 #include <sys/mman.h> |
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 | 425 |
442 #ifndef emacs | 426 #ifndef emacs |
443 #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1) | 427 #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1) |
444 #else | 428 #else |
445 #include <config.h> | 429 #include <config.h> |
476 deumens@qtp.ufl.edu | 460 deumens@qtp.ufl.edu |
477 Apr 23, 1996 | 461 Apr 23, 1996 |
478 */ | 462 */ |
479 | 463 |
480 #define OLD_SECTION_H(n) \ | 464 #define OLD_SECTION_H(n) \ |
481 (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) | 465 (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) |
482 #define NEW_SECTION_H(n) \ | 466 #define NEW_SECTION_H(n) \ |
483 (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) | 467 (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) |
484 #define OLD_PROGRAM_H(n) \ | 468 #define OLD_PROGRAM_H(n) \ |
485 (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) | 469 (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) |
486 #define NEW_PROGRAM_H(n) \ | 470 #define NEW_PROGRAM_H(n) \ |
487 (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) | 471 (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) |
488 | 472 |
489 #define PATCH_INDEX(n) \ | 473 #define PATCH_INDEX(n) \ |
490 do { \ | 474 do { \ |
491 if ((int) (n) >= old_bss_index) \ | 475 if ((int) (n) >= old_bss_index) \ |
492 (n)++; } while (0) | 476 (n)++; } while (0) |
524 caddr_t old_base, new_base; | 508 caddr_t old_base, new_base; |
525 | 509 |
526 /* Pointers to the file, program and section headers for the old and new | 510 /* Pointers to the file, program and section headers for the old and new |
527 * files. | 511 * files. |
528 */ | 512 */ |
529 ElfW(Ehdr) *old_file_h, *new_file_h; | 513 Elf32_Ehdr *old_file_h, *new_file_h; |
530 ElfW(Phdr) *old_program_h, *new_program_h; | 514 Elf32_Phdr *old_program_h, *new_program_h; |
531 ElfW(Shdr) *old_section_h, *new_section_h; | 515 Elf32_Shdr *old_section_h, *new_section_h; |
532 | 516 |
533 /* Point to the section name table in the old file */ | 517 /* Point to the section name table in the old file */ |
534 char *old_section_names; | 518 char *old_section_names; |
535 | 519 |
536 ElfW(Addr) old_bss_addr, new_bss_addr; | 520 Elf32_Addr old_bss_addr, new_bss_addr; |
537 ElfW(Addr) old_bss_size, new_data2_size; | 521 Elf32_Word old_bss_size, new_data2_size; |
538 ElfW(Off) new_data2_offset; | 522 Elf32_Off new_data2_offset; |
539 ElfW(Addr) new_data2_addr; | 523 Elf32_Addr new_data2_addr; |
540 | 524 |
541 int n, nn, old_bss_index, old_data_index; | 525 int n, nn, old_bss_index, old_data_index, new_data2_index; |
542 struct stat stat_buf; | 526 struct stat stat_buf; |
543 | 527 |
544 /* Open the old file & map it into the address space. */ | 528 /* Open the old file & map it into the address space. */ |
545 | 529 |
546 old_file = open (old_name, O_RDONLY); | 530 old_file = open (old_name, O_RDONLY); |
555 | 539 |
556 if (old_base == (caddr_t) -1) | 540 if (old_base == (caddr_t) -1) |
557 fatal ("Can't mmap (%s): errno %d\n", old_name, errno); | 541 fatal ("Can't mmap (%s): errno %d\n", old_name, errno); |
558 | 542 |
559 #ifdef DEBUG | 543 #ifdef DEBUG |
560 fprintf (stderr, "mmap (%s, %lx) -> %lx\n", old_name, stat_buf.st_size, | 544 fprintf (stderr, "mmap (%s, %x) -> %x\n", old_name, stat_buf.st_size, |
561 (unsigned long) old_base); | 545 old_base); |
562 #endif | 546 #endif |
563 | 547 |
564 /* Get pointers to headers & section names */ | 548 /* Get pointers to headers & section names */ |
565 | 549 |
566 old_file_h = (ElfW(Ehdr) *) old_base; | 550 old_file_h = (Elf32_Ehdr *) old_base; |
567 old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff); | 551 old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff); |
568 old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff); | 552 old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff); |
569 old_section_names = (char *) old_base | 553 old_section_names = (char *) old_base |
570 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; | 554 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; |
571 | 555 |
572 /* Find the old .bss section. Figure out parameters of the new | 556 /* Find the old .bss section. Figure out parameters of the new |
573 * data2 and bss sections. | 557 * data2 and bss sections. |
588 fatal ("Can't find .bss in %s.\n", old_name, 0); | 572 fatal ("Can't find .bss in %s.\n", old_name, 0); |
589 | 573 |
590 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; | 574 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; |
591 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; | 575 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; |
592 #if defined(emacs) || !defined(DEBUG) | 576 #if defined(emacs) || !defined(DEBUG) |
593 new_bss_addr = (ElfW(Addr)) sbrk (0); | 577 new_bss_addr = (Elf32_Addr) sbrk (0); |
594 #else | 578 #else |
595 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; | 579 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; |
596 #endif | 580 #endif |
597 new_data2_addr = old_bss_addr; | 581 new_data2_addr = old_bss_addr; |
598 new_data2_size = new_bss_addr - old_bss_addr; | 582 new_data2_size = new_bss_addr - old_bss_addr; |
599 new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; | 583 new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; |
600 | 584 |
601 #ifdef DEBUG | 585 #ifdef DEBUG |
602 fprintf (stderr, "old_bss_index %d\n", old_bss_index); | 586 fprintf (stderr, "old_bss_index %d\n", old_bss_index); |
603 fprintf (stderr, "old_bss_addr %lx\n", old_bss_addr); | 587 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); |
604 fprintf (stderr, "old_bss_size %lx\n", old_bss_size); | 588 fprintf (stderr, "old_bss_size %x\n", old_bss_size); |
605 fprintf (stderr, "new_bss_addr %lx\n", new_bss_addr); | 589 fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); |
606 fprintf (stderr, "new_data2_addr %lx\n", new_data2_addr); | 590 fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); |
607 fprintf (stderr, "new_data2_size %lx\n", new_data2_size); | 591 fprintf (stderr, "new_data2_size %x\n", new_data2_size); |
608 fprintf (stderr, "new_data2_offset %lx\n", new_data2_offset); | 592 fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); |
609 #endif | 593 #endif |
610 | 594 |
611 if ((unsigned long) new_bss_addr | 595 if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size) |
612 < (unsigned long) old_bss_addr + old_bss_size) | |
613 fatal (".bss shrank when undumping???\n", 0, 0); | 596 fatal (".bss shrank when undumping???\n", 0, 0); |
614 | 597 |
615 /* Set the output file to the right size and mmap it. Set | 598 /* Set the output file to the right size and mmap it. Set |
616 * pointers to various interesting objects. stat_buf still has | 599 * pointers to various interesting objects. stat_buf still has |
617 * old_file data. | 600 * old_file data. |
635 #endif | 618 #endif |
636 | 619 |
637 if (new_base == (caddr_t) -1) | 620 if (new_base == (caddr_t) -1) |
638 fatal ("Can't mmap (%s): errno %d\n", new_name, errno); | 621 fatal ("Can't mmap (%s): errno %d\n", new_name, errno); |
639 | 622 |
640 new_file_h = (ElfW(Ehdr) *) new_base; | 623 new_file_h = (Elf32_Ehdr *) new_base; |
641 new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff); | 624 new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff); |
642 new_section_h = (ElfW(Shdr) *) | 625 new_section_h = (Elf32_Shdr *) |
643 ((byte *) new_base + old_file_h->e_shoff + new_data2_size); | 626 ((byte *) new_base + old_file_h->e_shoff + new_data2_size); |
644 | 627 |
645 /* Make our new file, program and section headers as copies of the | 628 /* Make our new file, program and section headers as copies of the |
646 * originals. | 629 * originals. |
647 */ | 630 */ |
659 | 642 |
660 new_file_h->e_shoff += new_data2_size; | 643 new_file_h->e_shoff += new_data2_size; |
661 new_file_h->e_shnum += 1; | 644 new_file_h->e_shnum += 1; |
662 | 645 |
663 #ifdef DEBUG | 646 #ifdef DEBUG |
664 fprintf (stderr, "Old section offset %lx\n", old_file_h->e_shoff); | 647 fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff); |
665 fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); | 648 fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); |
666 fprintf (stderr, "New section offset %lx\n", new_file_h->e_shoff); | 649 fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff); |
667 fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); | 650 fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); |
668 #endif | 651 #endif |
669 | 652 |
670 /* Fix up a new program header. Extend the writable data segment so | 653 /* Fix up a new program header. Extend the writable data segment so |
671 * that the bss area is covered too. Find that segment by looking | 654 * that the bss area is covered too. Find that segment by looking |
676 */ | 659 */ |
677 | 660 |
678 for (n = new_file_h->e_phnum - 1; n >= 0; n--) | 661 for (n = new_file_h->e_phnum - 1; n >= 0; n--) |
679 { | 662 { |
680 /* Compute maximum of all requirements for alignment of section. */ | 663 /* Compute maximum of all requirements for alignment of section. */ |
681 unsigned int alignment = (NEW_PROGRAM_H (n)).p_align; | 664 int alignment = (NEW_PROGRAM_H (n)).p_align; |
682 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) | 665 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) |
683 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; | 666 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; |
684 | 667 |
685 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) | 668 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) |
686 fatal ("Program segment above .bss in %s\n", old_name, 0); | 669 fatal ("Program segment above .bss in %s\n", old_name, 0); |
823 src = old_base + OLD_SECTION_H (n).sh_offset; | 806 src = old_base + OLD_SECTION_H (n).sh_offset; |
824 | 807 |
825 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, | 808 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, |
826 NEW_SECTION_H (nn).sh_size); | 809 NEW_SECTION_H (nn).sh_size); |
827 | 810 |
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 | |
849 /* If it is the symbol table, its st_shndx field needs to be patched. */ | 811 /* If it is the symbol table, its st_shndx field needs to be patched. */ |
850 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB | 812 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB |
851 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) | 813 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) |
852 { | 814 { |
853 ElfW(Shdr) *spt = &NEW_SECTION_H (nn); | 815 Elf32_Shdr *spt = &NEW_SECTION_H (nn); |
854 unsigned int num = spt->sh_size / spt->sh_entsize; | 816 unsigned int num = spt->sh_size / spt->sh_entsize; |
855 ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset + | 817 Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset + |
856 new_base); | 818 new_base); |
857 for (; num--; sym++) | 819 for (; num--; sym++) |
858 { | 820 { |
859 if ((sym->st_shndx == SHN_UNDEF) | 821 if ((sym->st_shndx == SHN_UNDEF) |
860 || (sym->st_shndx == SHN_ABS) | 822 || (sym->st_shndx == SHN_ABS) |
868 | 830 |
869 /* Update the symbol values of _edata and _end. */ | 831 /* Update the symbol values of _edata and _end. */ |
870 for (n = new_file_h->e_shnum - 1; n; n--) | 832 for (n = new_file_h->e_shnum - 1; n; n--) |
871 { | 833 { |
872 byte *symnames; | 834 byte *symnames; |
873 ElfW(Sym) *symp, *symendp; | 835 Elf32_Sym *symp, *symendp; |
874 | 836 |
875 if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM | 837 if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM |
876 && NEW_SECTION_H (n).sh_type != SHT_SYMTAB) | 838 && NEW_SECTION_H (n).sh_type != SHT_SYMTAB) |
877 continue; | 839 continue; |
878 | 840 |
879 symnames = ((byte *) new_base | 841 symnames = ((byte *) new_base |
880 + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset); | 842 + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset); |
881 symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base); | 843 symp = (Elf32_Sym *) (NEW_SECTION_H (n).sh_offset + new_base); |
882 symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size); | 844 symendp = (Elf32_Sym *) ((byte *)symp + NEW_SECTION_H (n).sh_size); |
883 | 845 |
884 for (; symp < symendp; symp ++) | 846 for (; symp < symendp; symp ++) |
885 if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0 | 847 if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0 |
886 || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0) | 848 || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0) |
887 memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr)); | 849 memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr)); |
889 | 851 |
890 /* This loop seeks out relocation sections for the data section, so | 852 /* This loop seeks out relocation sections for the data section, so |
891 that it can undo relocations performed by the runtime linker. */ | 853 that it can undo relocations performed by the runtime linker. */ |
892 for (n = new_file_h->e_shnum - 1; n; n--) | 854 for (n = new_file_h->e_shnum - 1; n; n--) |
893 { | 855 { |
894 ElfW(Shdr) section = NEW_SECTION_H (n); | 856 Elf32_Shdr section = NEW_SECTION_H (n); |
895 switch (section.sh_type) { | 857 switch (section.sh_type) { |
896 default: | 858 default: |
897 break; | 859 break; |
898 case SHT_REL: | 860 case SHT_REL: |
899 case SHT_RELA: | 861 case SHT_RELA: |
903 nn = section.sh_info; | 865 nn = section.sh_info; |
904 if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") | 866 if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") |
905 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | 867 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), |
906 ".data1")) | 868 ".data1")) |
907 { | 869 { |
908 ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - | 870 Elf32_Addr offset = NEW_SECTION_H (nn).sh_addr - |
909 NEW_SECTION_H (nn).sh_offset; | 871 NEW_SECTION_H (nn).sh_offset; |
910 caddr_t reloc = old_base + section.sh_offset, end; | 872 caddr_t reloc = old_base + section.sh_offset, end; |
911 for (end = reloc + section.sh_size; reloc < end; | 873 for (end = reloc + section.sh_size; reloc < end; |
912 reloc += section.sh_entsize) | 874 reloc += section.sh_entsize) |
913 { | 875 { |
914 ElfW(Addr) addr; | 876 Elf32_Addr addr = ((Elf32_Rel *) reloc)->r_offset - offset; |
915 #ifdef __alpha__ | 877 memcpy (new_base + addr, old_base + addr, 4); |
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))); | |
924 } | 878 } |
925 } | 879 } |
926 break; | 880 break; |
927 } | 881 } |
928 } | 882 } |