Mercurial > hg > xemacs-beta
comparison src/unexelfsgi.c @ 50:ee648375d8d6 r19-16b91
Import from CVS: tag r19-16b91
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:56:41 +0200 |
parents | 376386a54a3c |
children | 8b0bdfdf0cf0 |
comparison
equal
deleted
inserted
replaced
49:b46643e427ac | 50:ee648375d8d6 |
---|---|
477 So, the shift for all sections beyond the playing field is: | 477 So, the shift for all sections beyond the playing field is: |
478 | 478 |
479 new_bss_addr - roundup(old_bss_addr,0x1000) | 479 new_bss_addr - roundup(old_bss_addr,0x1000) |
480 | 480 |
481 */ | 481 */ |
482 | 482 /* Still more mods... Olivier Galibert 19971705 |
483 - support for .sbss section (automagically changed to data without | |
484 name change) | |
485 - support for 64bits ABI (will need a bunch of fixes in the rest | |
486 of the code before it works | |
487 */ | |
483 | 488 |
484 #include <sys/types.h> | 489 #include <sys/types.h> |
485 #include <stdio.h> | 490 #include <stdio.h> |
486 #include <sys/stat.h> | 491 #include <sys/stat.h> |
487 #include <memory.h> | 492 #include <memory.h> |
490 #include <unistd.h> | 495 #include <unistd.h> |
491 #include <fcntl.h> | 496 #include <fcntl.h> |
492 #include <elf.h> | 497 #include <elf.h> |
493 #include <sym.h> /* for HDRR declaration */ | 498 #include <sym.h> /* for HDRR declaration */ |
494 #include <sys/mman.h> | 499 #include <sys/mman.h> |
500 #include <config.h> | |
501 #include "sysdep.h" | |
502 | |
503 /* in 64bits mode, use 64bits elf */ | |
504 #ifdef _ABI64 | |
505 typedef Elf64_Shdr l_Elf_Shdr; | |
506 typedef Elf64_Phdr l_Elf_Phdr; | |
507 typedef Elf64_Ehdr l_Elf_Ehdr; | |
508 typedef Elf64_Addr l_Elf_Addr; | |
509 typedef Elf64_Word l_Elf_Word; | |
510 typedef Elf64_Off l_Elf_Off; | |
511 typedef Elf64_Sym l_Elf_Sym; | |
512 #else | |
513 typedef Elf32_Shdr l_Elf_Shdr; | |
514 typedef Elf32_Phdr l_Elf_Phdr; | |
515 typedef Elf32_Ehdr l_Elf_Ehdr; | |
516 typedef Elf32_Addr l_Elf_Addr; | |
517 typedef Elf32_Word l_Elf_Word; | |
518 typedef Elf32_Off l_Elf_Off; | |
519 typedef Elf32_Sym l_Elf_Sym; | |
520 #endif | |
521 | |
495 | 522 |
496 #ifndef emacs | 523 #ifndef emacs |
497 #define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1) | 524 #define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1) |
498 #else | 525 #else |
499 extern void fatal(char *, ...); | 526 extern void fatal(char *, ...); |
502 /* Get the address of a particular section or program header entry, | 529 /* Get the address of a particular section or program header entry, |
503 * accounting for the size of the entries. | 530 * accounting for the size of the entries. |
504 */ | 531 */ |
505 | 532 |
506 #define OLD_SECTION_H(n) \ | 533 #define OLD_SECTION_H(n) \ |
507 (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) | 534 (*(l_Elf_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) |
508 #define NEW_SECTION_H(n) \ | 535 #define NEW_SECTION_H(n) \ |
509 (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) | 536 (*(l_Elf_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) |
510 #define OLD_PROGRAM_H(n) \ | 537 #define OLD_PROGRAM_H(n) \ |
511 (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) | 538 (*(l_Elf_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) |
512 #define NEW_PROGRAM_H(n) \ | 539 #define NEW_PROGRAM_H(n) \ |
513 (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) | 540 (*(l_Elf_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) |
514 | 541 |
515 #define PATCH_INDEX(n) \ | 542 #define PATCH_INDEX(n) \ |
516 do { \ | 543 do { \ |
517 if ((n) >= old_bss_index) \ | 544 if ((n) >= old_bss_index) \ |
518 (n)++; } while (0) | 545 (n)++; } while (0) |
540 static int | 567 static int |
541 find_section (name, section_names, file_name, old_file_h, old_section_h, noerror) | 568 find_section (name, section_names, file_name, old_file_h, old_section_h, noerror) |
542 char *name; | 569 char *name; |
543 char *section_names; | 570 char *section_names; |
544 char *file_name; | 571 char *file_name; |
545 Elf32_Ehdr *old_file_h; | 572 l_Elf_Ehdr *old_file_h; |
546 Elf32_Shdr *old_section_h; | 573 l_Elf_Shdr *old_section_h; |
547 int noerror; | 574 int noerror; |
548 { | 575 { |
549 int idx; | 576 int idx; |
550 | 577 |
551 for (idx = 1; idx < old_file_h->e_shnum; idx++) | 578 for (idx = 1; idx < old_file_h->e_shnum; idx++) |
579 * | 606 * |
580 */ | 607 */ |
581 void | 608 void |
582 unexec (new_name, old_name, data_start, bss_start, entry_address) | 609 unexec (new_name, old_name, data_start, bss_start, entry_address) |
583 char *new_name, *old_name; | 610 char *new_name, *old_name; |
584 unsigned data_start, bss_start, entry_address; | 611 uintptr_t data_start, bss_start, entry_address; |
585 { | 612 { |
586 extern unsigned int bss_end; | 613 extern uintptr_t bss_end; |
587 int new_file, old_file, new_file_size; | 614 int new_file, old_file, new_file_size; |
588 | 615 |
589 /* Pointers to the base of the image of the two files. */ | 616 /* Pointers to the base of the image of the two files. */ |
590 caddr_t old_base, new_base; | 617 caddr_t old_base, new_base; |
591 | 618 |
592 /* Pointers to the file, program and section headers for the old and new | 619 /* Pointers to the file, program and section headers for the old and new |
593 files. */ | 620 files. */ |
594 Elf32_Ehdr *old_file_h, *new_file_h; | 621 l_Elf_Ehdr *old_file_h, *new_file_h; |
595 Elf32_Phdr *old_program_h, *new_program_h; | 622 l_Elf_Phdr *old_program_h, *new_program_h; |
596 Elf32_Shdr *old_section_h, *new_section_h; | 623 l_Elf_Shdr *old_section_h, *new_section_h; |
597 | 624 |
598 /* Point to the section name table in the old file. */ | 625 /* Point to the section name table in the old file. */ |
599 char *old_section_names; | 626 char *old_section_names; |
600 | 627 |
601 Elf32_Addr old_bss_addr, new_bss_addr; | 628 l_Elf_Addr old_bss_addr, new_bss_addr; |
602 Elf32_Word old_bss_size, new_data2_size; | 629 l_Elf_Addr old_base_addr; |
603 Elf32_Off new_data2_offset; | 630 l_Elf_Word old_bss_size, new_data2_size; |
604 Elf32_Addr new_data2_addr; | 631 l_Elf_Off new_data2_offset, new_base_offset; |
605 Elf32_Addr new_offsets_shift; | 632 l_Elf_Addr new_data2_addr; |
633 l_Elf_Addr new_offsets_shift; | |
606 | 634 |
607 int n, nn, old_bss_index, old_data_index, new_data2_index; | 635 int n, nn, old_bss_index, old_data_index, new_data2_index; |
608 int old_mdebug_index; | 636 int old_mdebug_index, old_sbss_index; |
609 struct stat stat_buf; | 637 struct stat stat_buf; |
610 | 638 |
611 /* Open the old file & map it into the address space. */ | 639 /* Open the old file & map it into the address space. */ |
612 | 640 |
613 old_file = open (old_name, O_RDONLY); | 641 old_file = open (old_name, O_RDONLY); |
628 old_base); | 656 old_base); |
629 #endif | 657 #endif |
630 | 658 |
631 /* Get pointers to headers & section names. */ | 659 /* Get pointers to headers & section names. */ |
632 | 660 |
633 old_file_h = (Elf32_Ehdr *) old_base; | 661 old_file_h = (l_Elf_Ehdr *) old_base; |
634 old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff); | 662 old_program_h = (l_Elf_Phdr *) ((byte *) old_base + old_file_h->e_phoff); |
635 old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff); | 663 old_section_h = (l_Elf_Shdr *) ((byte *) old_base + old_file_h->e_shoff); |
636 old_section_names | 664 old_section_names |
637 = (char *) old_base + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; | 665 = (char *) old_base + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; |
638 | 666 |
639 /* Find the mdebug section, if any. */ | 667 /* Find the mdebug section, if any. */ |
640 | 668 |
641 old_mdebug_index = find_section (".mdebug", old_section_names, | 669 old_mdebug_index = find_section (".mdebug", old_section_names, |
642 old_name, old_file_h, old_section_h, 1); | 670 old_name, old_file_h, old_section_h, 1); |
643 | 671 |
672 /* Find the .sbss section, if any. */ | |
673 | |
674 old_sbss_index = find_section (".sbss", old_section_names, | |
675 old_name, old_file_h, old_section_h, 1); | |
676 | |
644 /* Find the old .bss section. */ | 677 /* Find the old .bss section. */ |
645 | 678 |
646 old_bss_index = find_section (".bss", old_section_names, | 679 old_bss_index = find_section (".bss", old_section_names, |
647 old_name, old_file_h, old_section_h, 0); | 680 old_name, old_file_h, old_section_h, 0); |
648 | 681 |
652 old_data_index = find_section (".data", old_section_names, | 685 old_data_index = find_section (".data", old_section_names, |
653 old_name, old_file_h, old_section_h, 0); | 686 old_name, old_file_h, old_section_h, 0); |
654 | 687 |
655 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; | 688 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; |
656 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; | 689 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; |
690 old_base_addr = old_sbss_index == -1 ? old_bss_addr : OLD_SECTION_H (old_sbss_index).sh_addr; | |
657 #if defined(emacs) || !defined(DEBUG) | 691 #if defined(emacs) || !defined(DEBUG) |
658 bss_end = (unsigned int) sbrk (0); | 692 bss_end = (uintptr_t) sbrk (0); |
659 new_bss_addr = (Elf32_Addr) bss_end; | 693 new_bss_addr = (l_Elf_Addr) bss_end; |
660 #else | 694 #else |
661 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; | 695 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; |
662 #endif | 696 #endif |
663 new_data2_addr = old_bss_addr; | 697 new_data2_addr = old_bss_addr; |
664 new_data2_size = new_bss_addr - old_bss_addr; | 698 new_data2_size = new_bss_addr - old_bss_addr; |
665 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset + | 699 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset + |
666 (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr); | 700 (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr); |
701 new_base_offset = OLD_SECTION_H (old_data_index).sh_offset + | |
702 (old_base_addr - OLD_SECTION_H (old_data_index).sh_addr); | |
667 new_offsets_shift = new_bss_addr - | 703 new_offsets_shift = new_bss_addr - |
668 ((old_bss_addr & ~0xfff) + ((old_bss_addr & 0xfff) ? 0x1000 : 0)); | 704 ((old_base_addr & ~0xfff) + ((old_base_addr & 0xfff) ? 0x1000 : 0)); |
669 | 705 |
670 #ifdef DEBUG | 706 #ifdef DEBUG |
671 fprintf (stderr, "old_bss_index %d\n", old_bss_index); | 707 fprintf (stderr, "old_bss_index %d\n", old_bss_index); |
672 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); | 708 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); |
673 fprintf (stderr, "old_bss_size %x\n", old_bss_size); | 709 fprintf (stderr, "old_bss_size %x\n", old_bss_size); |
710 fprintf (stderr, "old_base_addr %x\n", old_base_addr); | |
674 fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); | 711 fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); |
675 fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); | 712 fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); |
676 fprintf (stderr, "new_data2_size %x\n", new_data2_size); | 713 fprintf (stderr, "new_data2_size %x\n", new_data2_size); |
677 fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); | 714 fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); |
678 fprintf (stderr, "new_offsets_shift %x\n", new_offsets_shift); | 715 fprintf (stderr, "new_offsets_shift %x\n", new_offsets_shift); |
700 new_file, 0); | 737 new_file, 0); |
701 | 738 |
702 if (new_base == (caddr_t) -1) | 739 if (new_base == (caddr_t) -1) |
703 fatal ("Can't mmap (%s): errno %d\n", new_name, errno); | 740 fatal ("Can't mmap (%s): errno %d\n", new_name, errno); |
704 | 741 |
705 new_file_h = (Elf32_Ehdr *) new_base; | 742 new_file_h = (l_Elf_Ehdr *) new_base; |
706 new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff); | 743 new_program_h = (l_Elf_Phdr *) ((byte *) new_base + old_file_h->e_phoff); |
707 new_section_h | 744 new_section_h |
708 = (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff | 745 = (l_Elf_Shdr *) ((byte *) new_base + old_file_h->e_shoff |
709 + new_offsets_shift); | 746 + new_offsets_shift); |
710 | 747 |
711 /* Make our new file, program and section headers as copies of the | 748 /* Make our new file, program and section headers as copies of the |
712 originals. */ | 749 originals. */ |
713 | 750 |
745 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) | 782 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) |
746 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; | 783 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; |
747 | 784 |
748 /* Supposedly this condition is okay for the SGI. */ | 785 /* Supposedly this condition is okay for the SGI. */ |
749 #if 0 | 786 #if 0 |
750 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) | 787 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_base_addr) |
751 fatal ("Program segment above .bss in %s\n", old_name, 0); | 788 fatal ("Program segment above .bss in %s\n", old_name, 0); |
752 #endif | 789 #endif |
753 | 790 |
754 if (NEW_PROGRAM_H (n).p_type == PT_LOAD | 791 if (NEW_PROGRAM_H (n).p_type == PT_LOAD |
755 && (round_up ((NEW_PROGRAM_H (n)).p_vaddr | 792 && (round_up ((NEW_PROGRAM_H (n)).p_vaddr |
756 + (NEW_PROGRAM_H (n)).p_filesz, | 793 + (NEW_PROGRAM_H (n)).p_filesz, |
757 alignment) | 794 alignment) |
758 == round_up (old_bss_addr, alignment))) | 795 == round_up (old_base_addr, alignment))) |
759 break; | 796 break; |
760 } | 797 } |
761 if (n < 0) | 798 if (n < 0) |
762 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); | 799 fatal ("Couldn't find segment next to %s in %s\n", |
800 old_sbss_index == -1 ? ".sbss" : ".bss", old_name, 0); | |
763 | 801 |
764 NEW_PROGRAM_H (n).p_filesz += new_offsets_shift; | 802 NEW_PROGRAM_H (n).p_filesz += new_offsets_shift; |
765 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; | 803 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; |
766 | 804 |
767 #if 1 /* Maybe allow section after data2 - does this ever happen? */ | 805 #if 1 /* Maybe allow section after data2 - does this ever happen? */ |
841 old_file_h->e_shentsize); | 879 old_file_h->e_shentsize); |
842 | 880 |
843 /* Any section that was original placed AFTER the bss | 881 /* Any section that was original placed AFTER the bss |
844 section must now be adjusted by NEW_OFFSETS_SHIFT. */ | 882 section must now be adjusted by NEW_OFFSETS_SHIFT. */ |
845 | 883 |
846 if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) | 884 if (NEW_SECTION_H (nn).sh_offset >= new_base_offset) |
847 NEW_SECTION_H (nn).sh_offset += new_offsets_shift; | 885 NEW_SECTION_H (nn).sh_offset += new_offsets_shift; |
848 | 886 |
849 /* If any section hdr refers to the section after the new .data | 887 /* If any section hdr refers to the section after the new .data |
850 section, make it refer to next one because we have inserted | 888 section, make it refer to next one because we have inserted |
851 a new section in between. */ | 889 a new section in between. */ |
855 so don't change it. */ | 893 so don't change it. */ |
856 if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB | 894 if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB |
857 && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM) | 895 && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM) |
858 PATCH_INDEX (NEW_SECTION_H (nn).sh_info); | 896 PATCH_INDEX (NEW_SECTION_H (nn).sh_info); |
859 | 897 |
898 /* Fix the type and alignment for the .sbss section */ | |
899 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sbss")) | |
900 { | |
901 NEW_SECTION_H (nn).sh_type = SHT_PROGBITS; | |
902 NEW_SECTION_H (nn).sh_offset = round_up (NEW_SECTION_H (nn).sh_offset, | |
903 NEW_SECTION_H (nn).sh_addralign); | |
904 } | |
905 | |
860 /* Now, start to copy the content of sections. */ | 906 /* Now, start to copy the content of sections. */ |
861 if (NEW_SECTION_H (nn).sh_type == SHT_NULL | 907 if (NEW_SECTION_H (nn).sh_type == SHT_NULL |
862 || NEW_SECTION_H (nn).sh_type == SHT_NOBITS) | 908 || NEW_SECTION_H (nn).sh_type == SHT_NOBITS) |
863 continue; | 909 continue; |
864 | 910 |
865 /* Write out the sections. .data and .data1 (and data2, called | 911 /* Write out the sections. .data, .data1 and .sbss (and data2, called |
866 ".data" in the strings table) get copied from the current process | 912 ".data" in the strings table) get copied from the current process |
867 instead of the old file. */ | 913 instead of the old file. */ |
868 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") | 914 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") |
869 || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1") | 915 || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1") |
870 || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".got")) | 916 || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".got") |
917 || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sbss")) | |
871 src = (caddr_t) OLD_SECTION_H (n).sh_addr; | 918 src = (caddr_t) OLD_SECTION_H (n).sh_addr; |
872 else | 919 else |
873 src = old_base + OLD_SECTION_H (n).sh_offset; | 920 src = old_base + OLD_SECTION_H (n).sh_offset; |
874 | 921 |
875 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, | 922 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, |
930 | 977 |
931 /* If it is the symbol table, its st_shndx field needs to be patched. */ | 978 /* If it is the symbol table, its st_shndx field needs to be patched. */ |
932 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB | 979 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB |
933 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) | 980 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) |
934 { | 981 { |
935 Elf32_Shdr *spt = &NEW_SECTION_H (nn); | 982 l_Elf_Shdr *spt = &NEW_SECTION_H (nn); |
936 unsigned int num = spt->sh_size / spt->sh_entsize; | 983 unsigned int num = spt->sh_size / spt->sh_entsize; |
937 Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset | 984 l_Elf_Sym * sym = (l_Elf_Sym *) (NEW_SECTION_H (nn).sh_offset |
938 + new_base); | 985 + new_base); |
939 for (; num--; sym++) | 986 for (; num--; sym++) |
940 { | 987 { |
941 if (sym->st_shndx == SHN_UNDEF | 988 if (sym->st_shndx == SHN_UNDEF |
942 || sym->st_shndx == SHN_ABS | 989 || sym->st_shndx == SHN_ABS |