Mercurial > hg > xemacs-beta
comparison src/unexelf.c @ 371:cc15677e0335 r21-2b1
Import from CVS: tag r21-2b1
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:03:08 +0200 |
parents | 1d62742628b6 |
children | 6240c7796c7a |
comparison
equal
deleted
inserted
replaced
370:bd866891f083 | 371:cc15677e0335 |
---|---|
16 You should have received a copy of the GNU General Public License | 16 You should have received a copy of the GNU General Public License |
17 along with XEmacs; see the file COPYING. If not, write to | 17 along with XEmacs; see the file COPYING. If not, write to |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 Boston, MA 02111-1307, USA. */ | 19 Boston, MA 02111-1307, USA. */ |
20 | 20 |
21 /* Synched up with: FSF 20.4. */ | 21 /* Synched up with: FSF 20.2. */ |
22 | 22 |
23 /* | 23 /* |
24 * unexec.c - Convert a running program into an a.out file. | 24 * unexec.c - Convert a running program into an a.out file. |
25 * | 25 * |
26 * Author: Spencer W. Thomas | 26 * Author: Spencer W. Thomas |
422 #include <memory.h> | 422 #include <memory.h> |
423 #include <string.h> | 423 #include <string.h> |
424 #include <errno.h> | 424 #include <errno.h> |
425 #include <unistd.h> | 425 #include <unistd.h> |
426 #include <fcntl.h> | 426 #include <fcntl.h> |
427 #if !defined (__OpenBSD__) | |
428 #include <elf.h> | 427 #include <elf.h> |
429 #endif | |
430 #include <sys/mman.h> | 428 #include <sys/mman.h> |
431 #if defined (__sony_news) && defined (_SYSTYPE_SYSV) | 429 |
432 #include <sys/elf_mips.h> | 430 #if __GLIBC__ - 0 >= 2 |
433 #include <sym.h> | |
434 #endif /* __sony_news && _SYSTYPE_SYSV */ | |
435 #ifdef __sgi | |
436 #include <syms.h> /* for HDRR declaration */ | |
437 #endif /* __sgi */ | |
438 | |
439 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__) | |
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 | |
442 5.0 and presumably in any other glibc 2.x based distribution. */ | |
443 typedef struct { | |
444 short magic; | |
445 short vstamp; | |
446 int ilineMax; | |
447 int idnMax; | |
448 int ipdMax; | |
449 int isymMax; | |
450 int ioptMax; | |
451 int iauxMax; | |
452 int issMax; | |
453 int issExtMax; | |
454 int ifdMax; | |
455 int crfd; | |
456 int iextMax; | |
457 long cbLine; | |
458 long cbLineOffset; | |
459 long cbDnOffset; | |
460 long cbPdOffset; | |
461 long cbSymOffset; | |
462 long cbOptOffset; | |
463 long cbAuxOffset; | |
464 long cbSsOffset; | |
465 long cbSsExtOffset; | |
466 long cbFdOffset; | |
467 long cbRfdOffset; | |
468 long cbExtOffset; | |
469 } HDRR, *pHDRR; | |
470 #define cbHDRR sizeof(HDRR) | |
471 #define hdrNil ((pHDRR)0) | |
472 #endif | |
473 | |
474 #ifdef __OpenBSD__ | |
475 # include <sys/exec_elf.h> | |
476 #endif | |
477 | |
478 #if __GNU_LIBRARY__ - 0 >= 6 | |
479 # include <link.h> /* get ElfW etc */ | 431 # include <link.h> /* get ElfW etc */ |
480 #endif | 432 #endif |
481 | 433 |
482 #ifndef ElfW | 434 #ifndef ElfW |
483 # ifdef __STDC__ | 435 # ifdef __STDC__ |
533 (n)++; } while (0) | 485 (n)++; } while (0) |
534 typedef unsigned char byte; | 486 typedef unsigned char byte; |
535 | 487 |
536 /* Round X up to a multiple of Y. */ | 488 /* Round X up to a multiple of Y. */ |
537 | 489 |
538 static ElfW(Addr) | 490 static int |
539 round_up (ElfW(Addr) x, ElfW(Addr) y) | 491 round_up (int x, int y) |
540 { | 492 { |
541 int rem = x % y; | 493 int rem = x % y; |
542 if (rem == 0) | 494 if (rem == 0) |
543 return x; | 495 return x; |
544 return x - rem + y; | 496 return x - rem + y; |
545 } | |
546 | |
547 /* Return the index of the section named NAME. | |
548 SECTION_NAMES, FILE_NAME and FILE_H give information | |
549 about the file we are looking in. | |
550 | |
551 If we don't find the section NAME, that is a fatal error | |
552 if NOERROR is 0; we return -1 if NOERROR is nonzero. */ | |
553 | |
554 static int | |
555 find_section (name, section_names, file_name, old_file_h, old_section_h, noerror) | |
556 char *name; | |
557 char *section_names; | |
558 char *file_name; | |
559 ElfW(Ehdr) *old_file_h; | |
560 ElfW(Shdr) *old_section_h; | |
561 int noerror; | |
562 { | |
563 int idx; | |
564 | |
565 for (idx = 1; idx < old_file_h->e_shnum; idx++) | |
566 { | |
567 #ifdef DEBUG | |
568 fprintf (stderr, "Looking for %s - found %s\n", name, | |
569 section_names + OLD_SECTION_H (idx).sh_name); | |
570 #endif | |
571 if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name, | |
572 name)) | |
573 break; | |
574 } | |
575 if (idx == old_file_h->e_shnum) | |
576 { | |
577 if (noerror) | |
578 return -1; | |
579 else | |
580 fatal ("Can't find %s in %s.\n", name, file_name, 0); | |
581 } | |
582 | |
583 return idx; | |
584 } | 497 } |
585 | 498 |
586 /* **************************************************************** | 499 /* **************************************************************** |
587 * unexec | 500 * unexec |
588 * | 501 * |
616 ElfW(Addr) old_bss_addr, new_bss_addr; | 529 ElfW(Addr) old_bss_addr, new_bss_addr; |
617 ElfW(Word) old_bss_size, new_data2_size; | 530 ElfW(Word) old_bss_size, new_data2_size; |
618 ElfW(Off) new_data2_offset; | 531 ElfW(Off) new_data2_offset; |
619 ElfW(Addr) new_data2_addr; | 532 ElfW(Addr) new_data2_addr; |
620 | 533 |
621 int n, nn; | 534 int n, nn, old_bss_index, old_data_index; |
622 int old_bss_index, old_sbss_index; | |
623 int old_data_index, new_data2_index; | |
624 int old_mdebug_index; | |
625 struct stat stat_buf; | 535 struct stat stat_buf; |
626 | 536 |
627 /* Open the old file & map it into the address space. */ | 537 /* Open the old file & map it into the address space. */ |
628 | 538 |
629 old_file = open (old_name, O_RDONLY); | 539 old_file = open (old_name, O_RDONLY); |
650 old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff); | 560 old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff); |
651 old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff); | 561 old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff); |
652 old_section_names = (char *) old_base | 562 old_section_names = (char *) old_base |
653 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; | 563 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; |
654 | 564 |
655 /* Find the mdebug section, if any. */ | |
656 | |
657 old_mdebug_index = find_section (".mdebug", old_section_names, | |
658 old_name, old_file_h, old_section_h, 1); | |
659 | |
660 /* Find the old .bss section. Figure out parameters of the new | 565 /* Find the old .bss section. Figure out parameters of the new |
661 * data2 and bss sections. | 566 * data2 and bss sections. |
662 */ | 567 */ |
663 | 568 |
664 old_bss_index = find_section (".bss", old_section_names, | 569 for (old_bss_index = 1; old_bss_index < (int) old_file_h->e_shnum; |
665 old_name, old_file_h, old_section_h, 0); | 570 old_bss_index++) |
666 | |
667 old_sbss_index = find_section (".sbss", old_section_names, | |
668 old_name, old_file_h, old_section_h, 1); | |
669 | |
670 if (old_sbss_index == -1) | |
671 { | 571 { |
672 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; | 572 #ifdef DEBUG |
673 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; | 573 fprintf (stderr, "Looking for .bss - found %s\n", |
674 new_data2_index = old_bss_index; | 574 old_section_names + OLD_SECTION_H (old_bss_index).sh_name); |
575 #endif | |
576 if (!strcmp (old_section_names + OLD_SECTION_H (old_bss_index).sh_name, | |
577 ELF_BSS_SECTION_NAME)) | |
578 break; | |
675 } | 579 } |
676 else | 580 if (old_bss_index == old_file_h->e_shnum) |
677 { | 581 fatal ("Can't find .bss in %s.\n", old_name, 0); |
678 old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr; | 582 |
679 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size | 583 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; |
680 + OLD_SECTION_H (old_sbss_index).sh_size; | 584 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; |
681 new_data2_index = old_sbss_index; | |
682 } | |
683 | |
684 /* Find the old .data section. Figure out parameters of | |
685 the new data2 and bss sections. */ | |
686 | |
687 old_data_index = find_section (".data", old_section_names, | |
688 old_name, old_file_h, old_section_h, 0); | |
689 | |
690 #if defined (emacs) || !defined (DEBUG) | 585 #if defined (emacs) || !defined (DEBUG) |
691 new_bss_addr = (ElfW(Addr)) sbrk (0); | 586 new_bss_addr = (ElfW(Addr)) sbrk (0); |
692 #else | 587 #else |
693 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; | 588 new_bss_addr = old_bss_addr + old_bss_size + 0x1234; |
694 #endif | 589 #endif |
695 new_data2_addr = old_bss_addr; | 590 new_data2_addr = old_bss_addr; |
696 new_data2_size = new_bss_addr - old_bss_addr; | 591 new_data2_size = new_bss_addr - old_bss_addr; |
697 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset + | 592 new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; |
698 (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr); | |
699 | 593 |
700 #ifdef DEBUG | 594 #ifdef DEBUG |
701 fprintf (stderr, "old_bss_index %d\n", old_bss_index); | 595 fprintf (stderr, "old_bss_index %d\n", old_bss_index); |
702 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); | 596 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); |
703 fprintf (stderr, "old_bss_size %x\n", old_bss_size); | 597 fprintf (stderr, "old_bss_size %x\n", old_bss_size); |
778 /* Compute maximum of all requirements for alignment of section. */ | 672 /* Compute maximum of all requirements for alignment of section. */ |
779 ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align; | 673 ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align; |
780 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) | 674 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) |
781 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; | 675 alignment = OLD_SECTION_H (old_bss_index).sh_addralign; |
782 | 676 |
783 #ifdef __sgi | 677 #ifndef __mips /* ifndef added by jwz at suggestion of |
784 /* According to r02kar@x4u2.desy.de (Karsten Kuenne) | 678 r02kar@x4u2.desy.de (Karsten Kuenne) to avoid |
785 and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we | 679 "Program segment above .bss" when dumping. |
786 always get "Program segment above .bss" when dumping | 680 */ |
787 when the executable doesn't have an sbss section. */ | 681 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) |
788 if (old_sbss_index != -1) | 682 fatal ("Program segment above .bss in %s\n", old_name, 0); |
789 #endif /* __sgi */ | 683 #endif /* __mips */ |
790 if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz | |
791 > (old_sbss_index == -1 | |
792 ? old_bss_addr | |
793 : round_up (old_bss_addr, alignment))) | |
794 fatal ("Program segment above .bss in %s\n", old_name, 0); | |
795 | 684 |
796 if (NEW_PROGRAM_H (n).p_type == PT_LOAD | 685 if (NEW_PROGRAM_H (n).p_type == PT_LOAD |
797 && (round_up ((NEW_PROGRAM_H (n)).p_vaddr | 686 && (round_up ((int) ((NEW_PROGRAM_H (n)).p_vaddr |
798 + (NEW_PROGRAM_H (n)).p_filesz, | 687 + (NEW_PROGRAM_H (n)).p_filesz), |
799 alignment) | 688 alignment) |
800 == round_up (old_bss_addr, alignment))) | 689 == round_up ((int) old_bss_addr, alignment))) |
801 break; | 690 break; |
802 } | 691 } |
803 if (n < 0) | 692 if (n < 0) |
804 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); | 693 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); |
805 | 694 |
806 /* Make sure that the size includes any padding before the old .bss | |
807 section. */ | |
808 NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr; | 695 NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr; |
809 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; | 696 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; |
810 | 697 |
811 #if 0 /* Maybe allow section after data2 - does this ever happen? */ | 698 #if 0 /* Maybe allow section after data2 - does this ever happen? */ |
812 for (n = new_file_h->e_phnum - 1; n >= 0; n--) | 699 for (n = new_file_h->e_phnum - 1; n >= 0; n--) |
837 /* Walk through all section headers, insert the new data2 section right | 724 /* Walk through all section headers, insert the new data2 section right |
838 before the new bss section. */ | 725 before the new bss section. */ |
839 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) | 726 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) |
840 { | 727 { |
841 caddr_t src; | 728 caddr_t src; |
842 /* If it is (s)bss section, insert the new data2 section before it. */ | 729 /* If it is bss section, insert the new data2 section before it. */ |
843 /* new_data2_index is the index of either old_sbss or old_bss, that was | 730 if (n == old_bss_index) |
844 chosen as a section for new_data2. */ | |
845 if (n == new_data2_index) | |
846 { | 731 { |
847 /* Steal the data section header for this data2 section. */ | 732 /* Steal the data section header for this data2 section. */ |
848 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), | 733 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), |
849 new_file_h->e_shentsize); | 734 new_file_h->e_shentsize); |
850 | 735 |
857 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign; | 742 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign; |
858 | 743 |
859 /* Now copy over what we have in the memory now. */ | 744 /* Now copy over what we have in the memory now. */ |
860 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, | 745 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, |
861 (caddr_t) OLD_SECTION_H (n).sh_addr, | 746 (caddr_t) OLD_SECTION_H (n).sh_addr, |
747 /* #### mrb: should be old_bss_size instead? */ | |
862 new_data2_size); | 748 new_data2_size); |
863 nn++; | 749 nn++; |
864 } | 750 } |
865 | 751 |
866 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), | 752 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), |
867 old_file_h->e_shentsize); | 753 old_file_h->e_shentsize); |
868 | 754 |
869 if (n == old_bss_index | 755 /* The new bss section's size is zero, and its file offset and virtual |
870 /* The new bss and sbss section's size is zero, and its file offset | 756 address should be off by NEW_DATA2_SIZE. */ |
871 and virtual address should be off by NEW_DATA2_SIZE. */ | 757 if (n == old_bss_index) |
872 || n == old_sbss_index | |
873 ) | |
874 { | 758 { |
875 /* NN should be `old_s?bss_index + 1' at this point. */ | 759 /* NN should be `old_bss_index + 1' at this point. */ |
876 NEW_SECTION_H (nn).sh_offset = | 760 NEW_SECTION_H (nn).sh_offset += new_data2_size; |
877 NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size; | 761 NEW_SECTION_H (nn).sh_addr += new_data2_size; |
878 NEW_SECTION_H (nn).sh_addr = | |
879 NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size; | |
880 /* Let the new bss section address alignment be the same as the | 762 /* Let the new bss section address alignment be the same as the |
881 section address alignment followed the old bss section, so | 763 section address alignment followed the old bss section, so |
882 this section will be placed in exactly the same place. */ | 764 this section will be placed in exactly the same place. */ |
883 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; | 765 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; |
884 NEW_SECTION_H (nn).sh_size = 0; | 766 NEW_SECTION_H (nn).sh_size = 0; |
898 Erik Deumens, deumens@qtp.ufl.edu. */ | 780 Erik Deumens, deumens@qtp.ufl.edu. */ |
899 if (NEW_SECTION_H (nn).sh_offset | 781 if (NEW_SECTION_H (nn).sh_offset |
900 >= OLD_SECTION_H (old_bss_index-1).sh_offset) | 782 >= OLD_SECTION_H (old_bss_index-1).sh_offset) |
901 NEW_SECTION_H (nn).sh_offset += new_data2_size; | 783 NEW_SECTION_H (nn).sh_offset += new_data2_size; |
902 #else | 784 #else |
903 if (round_up (NEW_SECTION_H (nn).sh_offset, | 785 if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) |
904 OLD_SECTION_H (old_bss_index).sh_addralign) | |
905 >= new_data2_offset) | |
906 NEW_SECTION_H (nn).sh_offset += new_data2_size; | 786 NEW_SECTION_H (nn).sh_offset += new_data2_size; |
907 #endif | 787 #endif |
908 /* Any section that was originally placed after the section | 788 /* Any section that was originally placed after the section |
909 header table should now be off by the size of one section | 789 header table should now be off by the size of one section |
910 header table entry. */ | 790 header table entry. */ |
929 continue; | 809 continue; |
930 | 810 |
931 /* Write out the sections. .data and .data1 (and data2, called | 811 /* Write out the sections. .data and .data1 (and data2, called |
932 ".data" in the strings table) get copied from the current process | 812 ".data" in the strings table) get copied from the current process |
933 instead of the old file. */ | 813 instead of the old file. */ |
814 #ifdef __powerpc__ | |
815 /* The PowerPC has additional 'data' segments which need to be saved */ | |
816 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") || | |
817 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1") || | |
818 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata") || | |
819 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata1")) | |
820 #else | |
934 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") | 821 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") |
935 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | 822 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), |
936 ".sdata") | |
937 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
938 ".lit4") | |
939 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
940 ".lit8") | |
941 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
942 ".sdata1") | |
943 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), | |
944 ".data1")) | 823 ".data1")) |
824 #endif | |
945 src = (caddr_t) OLD_SECTION_H (n).sh_addr; | 825 src = (caddr_t) OLD_SECTION_H (n).sh_addr; |
946 else | 826 else |
947 src = old_base + OLD_SECTION_H (n).sh_offset; | 827 src = old_base + OLD_SECTION_H (n).sh_offset; |
948 | 828 |
949 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, | 829 memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, |
950 NEW_SECTION_H (nn).sh_size); | 830 NEW_SECTION_H (nn).sh_size); |
951 | |
952 #ifdef __alpha__ | |
953 /* Update Alpha COFF symbol table: */ | |
954 if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug") | |
955 == 0) | |
956 { | |
957 pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base); | |
958 | |
959 symhdr->cbLineOffset += new_data2_size; | |
960 symhdr->cbDnOffset += new_data2_size; | |
961 symhdr->cbPdOffset += new_data2_size; | |
962 symhdr->cbSymOffset += new_data2_size; | |
963 symhdr->cbOptOffset += new_data2_size; | |
964 symhdr->cbAuxOffset += new_data2_size; | |
965 symhdr->cbSsOffset += new_data2_size; | |
966 symhdr->cbSsExtOffset += new_data2_size; | |
967 symhdr->cbFdOffset += new_data2_size; | |
968 symhdr->cbRfdOffset += new_data2_size; | |
969 symhdr->cbExtOffset += new_data2_size; | |
970 } | |
971 #endif /* __alpha__ */ | |
972 | |
973 #if defined (__sony_news) && defined (_SYSTYPE_SYSV) | |
974 if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG | |
975 && old_mdebug_index != -1) | |
976 { | |
977 int diff = NEW_SECTION_H(nn).sh_offset | |
978 - OLD_SECTION_H(old_mdebug_index).sh_offset; | |
979 HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base); | |
980 | |
981 if (diff) | |
982 { | |
983 phdr->cbLineOffset += diff; | |
984 phdr->cbDnOffset += diff; | |
985 phdr->cbPdOffset += diff; | |
986 phdr->cbSymOffset += diff; | |
987 phdr->cbOptOffset += diff; | |
988 phdr->cbAuxOffset += diff; | |
989 phdr->cbSsOffset += diff; | |
990 phdr->cbSsExtOffset += diff; | |
991 phdr->cbFdOffset += diff; | |
992 phdr->cbRfdOffset += diff; | |
993 phdr->cbExtOffset += diff; | |
994 } | |
995 } | |
996 #endif /* __sony_news && _SYSTYPE_SYSV */ | |
997 | |
998 #ifdef __sgi | |
999 /* Adjust the HDRR offsets in .mdebug and copy the | |
1000 line data if it's in its usual 'hole' in the object. | |
1001 Makes the new file debuggable with dbx. | |
1002 patches up two problems: the absolute file offsets | |
1003 in the HDRR record of .mdebug (see /usr/include/syms.h), and | |
1004 the ld bug that gets the line table in a hole in the | |
1005 elf file rather than in the .mdebug section proper. | |
1006 David Anderson. davea@sgi.com Jan 16,1994. */ | |
1007 if (n == old_mdebug_index) | |
1008 { | |
1009 #define MDEBUGADJUST(__ct,__fileaddr) \ | |
1010 if (n_phdrr->__ct > 0) \ | |
1011 { \ | |
1012 n_phdrr->__fileaddr += movement; \ | |
1013 } | |
1014 | |
1015 HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset); | |
1016 HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset); | |
1017 unsigned movement = new_data2_size; | |
1018 | |
1019 MDEBUGADJUST (idnMax, cbDnOffset); | |
1020 MDEBUGADJUST (ipdMax, cbPdOffset); | |
1021 MDEBUGADJUST (isymMax, cbSymOffset); | |
1022 MDEBUGADJUST (ioptMax, cbOptOffset); | |
1023 MDEBUGADJUST (iauxMax, cbAuxOffset); | |
1024 MDEBUGADJUST (issMax, cbSsOffset); | |
1025 MDEBUGADJUST (issExtMax, cbSsExtOffset); | |
1026 MDEBUGADJUST (ifdMax, cbFdOffset); | |
1027 MDEBUGADJUST (crfd, cbRfdOffset); | |
1028 MDEBUGADJUST (iextMax, cbExtOffset); | |
1029 /* The Line Section, being possible off in a hole of the object, | |
1030 requires special handling. */ | |
1031 if (n_phdrr->cbLine > 0) | |
1032 { | |
1033 if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset | |
1034 + OLD_SECTION_H (n).sh_size)) | |
1035 { | |
1036 /* line data is in a hole in elf. do special copy and adjust | |
1037 for this ld mistake. | |
1038 */ | |
1039 n_phdrr->cbLineOffset += movement; | |
1040 | |
1041 memcpy (n_phdrr->cbLineOffset + new_base, | |
1042 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine); | |
1043 } | |
1044 else | |
1045 { | |
1046 /* somehow line data is in .mdebug as it is supposed to be. */ | |
1047 MDEBUGADJUST (cbLine, cbLineOffset); | |
1048 } | |
1049 } | |
1050 } | |
1051 #endif /* __sgi */ | |
1052 | 831 |
1053 /* If it is the symbol table, its st_shndx field needs to be patched. */ | 832 /* If it is the symbol table, its st_shndx field needs to be patched. */ |
1054 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB | 833 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB |
1055 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) | 834 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) |
1056 { | 835 { |
1085 symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base); | 864 symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base); |
1086 symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size); | 865 symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size); |
1087 | 866 |
1088 for (; symp < symendp; symp ++) | 867 for (; symp < symendp; symp ++) |
1089 if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0 | 868 if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0 |
1090 || strcmp ((char *) (symnames + symp->st_name), "end") == 0 | 869 || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0) |
1091 || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0 | |
1092 || strcmp ((char *) (symnames + symp->st_name), "edata") == 0) | |
1093 memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr)); | 870 memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr)); |
1094 } | 871 } |
1095 | 872 |
1096 /* This loop seeks out relocation sections for the data section, so | 873 /* This loop seeks out relocation sections for the data section, so |
1097 that it can undo relocations performed by the runtime linker. */ | 874 that it can undo relocations performed by the runtime linker. */ |
1105 case SHT_RELA: | 882 case SHT_RELA: |
1106 /* This code handles two different size structs, but there should | 883 /* This code handles two different size structs, but there should |
1107 be no harm in that provided that r_offset is always the first | 884 be no harm in that provided that r_offset is always the first |
1108 member. */ | 885 member. */ |
1109 nn = section.sh_info; | 886 nn = section.sh_info; |
887 #ifdef __powerpc__ | |
888 /* The PowerPC has additional 'data' segments which need to be saved */ | |
889 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") || | |
890 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1") || | |
891 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata") || | |
892 !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata1")) | |
893 #else | |
1110 if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") | 894 if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") |
1111 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | 895 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), |
1112 ".sdata") | |
1113 #ifdef __sgi | |
1114 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1115 ".lit4") | |
1116 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1117 ".lit8") | |
1118 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1119 ".got") | |
1120 #endif | |
1121 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1122 ".sdata1") | |
1123 || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), | |
1124 ".data1")) | 896 ".data1")) |
897 #endif | |
1125 { | 898 { |
1126 ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - | 899 ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - |
1127 NEW_SECTION_H (nn).sh_offset; | 900 NEW_SECTION_H (nn).sh_offset; |
1128 caddr_t reloc = old_base + section.sh_offset, end; | 901 caddr_t reloc = old_base + section.sh_offset, end; |
1129 for (end = reloc + section.sh_size; reloc < end; | 902 for (end = reloc + section.sh_size; reloc < end; |
1130 reloc += section.sh_entsize) | 903 reloc += section.sh_entsize) |
1131 { | 904 { |
1132 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset; | 905 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset; |
1133 #ifdef __alpha__ | |
1134 /* The Alpha ELF binutils currently have a bug that | |
1135 sometimes results in relocs that contain all | |
1136 zeroes. Work around this for now... */ | |
1137 if (((ElfW(Rel) *) reloc)->r_offset == 0) | |
1138 continue; | |
1139 #endif | |
1140 memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr))); | 906 memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr))); |
1141 } | 907 } |
1142 } | 908 } |
1143 break; | 909 break; |
1144 } | 910 } |