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