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