comparison src/unexelf.c @ 359:8e84bee8ddd0 r21-1-9

Import from CVS: tag r21-1-9
author cvs
date Mon, 13 Aug 2007 10:57:55 +0200
parents 4711e16a8e49
children 1d62742628b6
comparison
equal deleted inserted replaced
358:fed6e0f6a03a 359:8e84bee8ddd0
431 #if defined (__sony_news) && defined (_SYSTYPE_SYSV) 431 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
432 #include <sys/elf_mips.h> 432 #include <sys/elf_mips.h>
433 #include <sym.h> 433 #include <sym.h>
434 #endif /* __sony_news && _SYSTYPE_SYSV */ 434 #endif /* __sony_news && _SYSTYPE_SYSV */
435 #ifdef __sgi 435 #ifdef __sgi
436 #include <sym.h> /* for HDRR declaration */ 436 #include <syms.h> /* for HDRR declaration */
437 #endif /* __sgi */ 437 #endif /* __sgi */
438 438
439 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__) 439 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
440 /* Declare COFF debugging symbol table. This used to be in 440 /* Declare COFF debugging symbol table. This used to be in
441 /usr/include/sym.h, but this file is no longer included in Red Hat 441 /usr/include/sym.h, but this file is no longer included in Red Hat
492 492
493 # define SHN_UNDEF Elf_eshn_undefined 493 # define SHN_UNDEF Elf_eshn_undefined
494 # define SHN_ABS Elf_eshn_absolute 494 # define SHN_ABS Elf_eshn_absolute
495 # define SHN_COMMON Elf_eshn_common 495 # define SHN_COMMON Elf_eshn_common
496 496
497 /*
498 * The magic of picking the right size types is handled by the ELFSIZE
499 * definition above.
500 */
501 # ifdef __STDC__
502 # define ElfW(type) Elf_##type
503 # else
504 # define ElfW(type) Elf_/**/type
505 # endif
506
507 # ifdef __alpha__ 497 # ifdef __alpha__
508 # include <sys/exec_ecoff.h> 498 # include <sys/exec_ecoff.h>
509 # define HDRR struct ecoff_symhdr 499 # define HDRR struct ecoff_symhdr
510 # define pHDRR HDRR * 500 # define pHDRR HDRR *
511 # endif 501 # endif
582 if (rem == 0) 572 if (rem == 0)
583 return x; 573 return x;
584 return x - rem + y; 574 return x - rem + y;
585 } 575 }
586 576
577 /* Return the index of the section named NAME.
578 SECTION_NAMES, FILE_NAME and FILE_H give information
579 about the file we are looking in.
580
581 If we don't find the section NAME, that is a fatal error
582 if NOERROR is 0; we return -1 if NOERROR is nonzero. */
583
584 static int
585 find_section (name, section_names, file_name, old_file_h, old_section_h, noerror)
586 char *name;
587 char *section_names;
588 char *file_name;
589 ElfW(Ehdr) *old_file_h;
590 ElfW(Shdr) *old_section_h;
591 int noerror;
592 {
593 int idx;
594
595 for (idx = 1; idx < old_file_h->e_shnum; idx++)
596 {
597 #ifdef DEBUG
598 fprintf (stderr, "Looking for %s - found %s\n", name,
599 section_names + OLD_SECTION_H (idx).sh_name);
600 #endif
601 if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name,
602 name))
603 break;
604 }
605 if (idx == old_file_h->e_shnum)
606 {
607 if (noerror)
608 return -1;
609 else
610 fatal ("Can't find %s in %s.\n", name, file_name, 0);
611 }
612
613 return idx;
614 }
615
587 /* **************************************************************** 616 /* ****************************************************************
588 * unexec 617 * unexec
589 * 618 *
590 * driving logic. 619 * driving logic.
591 * 620 *
617 ElfW(Addr) old_bss_addr, new_bss_addr; 646 ElfW(Addr) old_bss_addr, new_bss_addr;
618 ElfW(Word) old_bss_size, new_data2_size; 647 ElfW(Word) old_bss_size, new_data2_size;
619 ElfW(Off) new_data2_offset; 648 ElfW(Off) new_data2_offset;
620 ElfW(Addr) new_data2_addr; 649 ElfW(Addr) new_data2_addr;
621 650
622 int n, nn, old_bss_index, old_data_index, new_data2_index; 651 int n, nn;
623 int old_sbss_index, old_mdebug_index; 652 int old_bss_index, old_sbss_index;
653 int old_data_index, new_data2_index;
654 int old_mdebug_index;
624 struct stat stat_buf; 655 struct stat stat_buf;
625 656
626 /* Open the old file & map it into the address space. */ 657 /* Open the old file & map it into the address space. */
627 658
628 old_file = open (old_name, O_RDONLY); 659 old_file = open (old_name, O_RDONLY);
649 old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff); 680 old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
650 old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff); 681 old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
651 old_section_names = (char *) old_base 682 old_section_names = (char *) old_base
652 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; 683 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
653 684
685 /* Find the mdebug section, if any. */
686
687 old_mdebug_index = find_section (".mdebug", old_section_names,
688 old_name, old_file_h, old_section_h, 1);
689
654 /* Find the old .bss section. Figure out parameters of the new 690 /* Find the old .bss section. Figure out parameters of the new
655 * data2 and bss sections. 691 * data2 and bss sections.
656 */ 692 */
657 693
658 for (old_bss_index = 1; old_bss_index < (int) old_file_h->e_shnum; 694 old_bss_index = find_section (".bss", old_section_names,
659 old_bss_index++) 695 old_name, old_file_h, old_section_h, 0);
696
697 old_sbss_index = find_section (".sbss", old_section_names,
698 old_name, old_file_h, old_section_h, 1);
699
700 if (old_sbss_index == -1)
660 { 701 {
661 #ifdef DEBUG 702 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
662 fprintf (stderr, "Looking for .bss - found %s\n", 703 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
663 old_section_names + OLD_SECTION_H (old_bss_index).sh_name);
664 #endif
665 if (!strcmp (old_section_names + OLD_SECTION_H (old_bss_index).sh_name,
666 ELF_BSS_SECTION_NAME))
667 break;
668 }
669 if (old_bss_index == old_file_h->e_shnum)
670 fatal ("Can't find .bss in %s.\n", old_name, 0);
671
672 for (old_sbss_index = 1; old_sbss_index < (int) old_file_h->e_shnum;
673 old_sbss_index++)
674 {
675 #ifdef DEBUG
676 fprintf (stderr, "Looking for .sbss - found %s\n",
677 old_section_names + OLD_SECTION_H (old_sbss_index).sh_name);
678 #endif
679 if (!strcmp (old_section_names + OLD_SECTION_H (old_sbss_index).sh_name,
680 ".sbss"))
681 break;
682 }
683 if (old_sbss_index == old_file_h->e_shnum)
684 {
685 old_sbss_index = -1;
686 old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
687 old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
688 new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;
689 new_data2_index = old_bss_index; 704 new_data2_index = old_bss_index;
690 } 705 }
691 else 706 else
692 { 707 {
693 old_bss_addr = OLD_SECTION_H(old_sbss_index).sh_addr; 708 old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
694 old_bss_size = OLD_SECTION_H(old_bss_index).sh_size 709 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
695 + OLD_SECTION_H(old_sbss_index).sh_size; 710 + OLD_SECTION_H (old_sbss_index).sh_size;
696 new_data2_offset = OLD_SECTION_H(old_sbss_index).sh_offset;
697 new_data2_index = old_sbss_index; 711 new_data2_index = old_sbss_index;
698 } 712 }
699 713
700 for (old_mdebug_index = 1; old_mdebug_index < (int) old_file_h->e_shnum; 714 /* Find the old .data section. Figure out parameters of
701 old_mdebug_index++) 715 the new data2 and bss sections. */
702 { 716
703 #ifdef DEBUG 717 old_data_index = find_section (".data", old_section_names,
704 fprintf (stderr, "Looking for .mdebug - found %s\n", 718 old_name, old_file_h, old_section_h, 0);
705 old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name);
706 #endif
707 if (!strcmp (old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name,
708 ".mdebug"))
709 break;
710 }
711 if (old_mdebug_index == old_file_h->e_shnum)
712 old_mdebug_index = 0;
713 719
714 #if defined (emacs) || !defined (DEBUG) 720 #if defined (emacs) || !defined (DEBUG)
715 new_bss_addr = (ElfW(Addr)) sbrk (0); 721 new_bss_addr = (ElfW(Addr)) sbrk (0);
716 #else 722 #else
717 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; 723 new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
718 #endif 724 #endif
719 new_data2_addr = old_bss_addr; 725 new_data2_addr = old_bss_addr;
720 new_data2_size = new_bss_addr - old_bss_addr; 726 new_data2_size = new_bss_addr - old_bss_addr;
727 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset +
728 (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
721 729
722 #ifdef DEBUG 730 #ifdef DEBUG
723 fprintf (stderr, "old_bss_index %d\n", old_bss_index); 731 fprintf (stderr, "old_bss_index %d\n", old_bss_index);
724 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); 732 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
725 fprintf (stderr, "old_bss_size %x\n", old_bss_size); 733 fprintf (stderr, "old_bss_size %x\n", old_bss_size);
800 /* Compute maximum of all requirements for alignment of section. */ 808 /* Compute maximum of all requirements for alignment of section. */
801 ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align; 809 ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align;
802 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) 810 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
803 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; 811 alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
804 812
805 #ifdef __mips 813 #ifdef __sgi
806 /* According to r02kar@x4u2.desy.de (Karsten Kuenne) 814 /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
807 and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we 815 and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
808 always get "Program segment above .bss" when dumping 816 always get "Program segment above .bss" when dumping
809 when the executable doesn't have an sbss section. */ 817 when the executable doesn't have an sbss section. */
810 if (old_sbss_index != -1) 818 if (old_sbss_index != -1)
811 #endif /* __mips */ 819 #endif /* __sgi */
812 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz 820 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
813 > (old_sbss_index == -1 821 > (old_sbss_index == -1
814 ? old_bss_addr 822 ? old_bss_addr
815 : round_up (old_bss_addr, alignment))) 823 : round_up (old_bss_addr, alignment)))
816 fatal ("Program segment above .bss in %s\n", old_name, 0); 824 fatal ("Program segment above .bss in %s\n", old_name, 0);
954 ".data" in the strings table) get copied from the current process 962 ".data" in the strings table) get copied from the current process
955 instead of the old file. */ 963 instead of the old file. */
956 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") 964 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
957 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), 965 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
958 ".sdata") 966 ".sdata")
959 /* Taking these sections from the current process, breaks
960 Linux in a subtle way. Binaries only run on the
961 architecture (e.g. i586 vs i686) of the dumping machine */
962 #ifdef __sgi
963 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), 967 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
964 ".lit4") 968 ".lit4")
965 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), 969 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
966 ".lit8") 970 ".lit8")
967 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
968 ".got")
969 #endif
970 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), 971 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
971 ".sdata1") 972 ".sdata1")
972 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), 973 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
973 ".data1")) 974 ".data1"))
974 src = (caddr_t) OLD_SECTION_H (n).sh_addr; 975 src = (caddr_t) OLD_SECTION_H (n).sh_addr;
998 symhdr->cbExtOffset += new_data2_size; 999 symhdr->cbExtOffset += new_data2_size;
999 } 1000 }
1000 #endif /* __alpha__ */ 1001 #endif /* __alpha__ */
1001 1002
1002 #if defined (__sony_news) && defined (_SYSTYPE_SYSV) 1003 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
1003 if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG && old_mdebug_index) 1004 if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
1005 && old_mdebug_index != -1)
1004 { 1006 {
1005 int diff = NEW_SECTION_H(nn).sh_offset 1007 int diff = NEW_SECTION_H(nn).sh_offset
1006 - OLD_SECTION_H(old_mdebug_index).sh_offset; 1008 - OLD_SECTION_H(old_mdebug_index).sh_offset;
1007 HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base); 1009 HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base);
1008 1010