aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/unexsgi.c166
1 files changed, 100 insertions, 66 deletions
diff --git a/src/unexsgi.c b/src/unexsgi.c
index b375ee5a8a1..41df908d5a4 100644
--- a/src/unexsgi.c
+++ b/src/unexsgi.c
@@ -491,6 +491,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
491 Elf32_Word old_bss_size, new_data2_size; 491 Elf32_Word old_bss_size, new_data2_size;
492 Elf32_Off new_data2_offset; 492 Elf32_Off new_data2_offset;
493 Elf32_Addr new_data2_addr; 493 Elf32_Addr new_data2_addr;
494 Elf32_Addr new_offsets_shift;
494 495
495 int n, nn, old_bss_index, old_data_index, new_data2_index; 496 int n, nn, old_bss_index, old_data_index, new_data2_index;
496 int old_mdebug_index; 497 int old_mdebug_index;
@@ -536,10 +537,9 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
536 break; 537 break;
537 } 538 }
538 if (old_mdebug_index == old_file_h->e_shnum) 539 if (old_mdebug_index == old_file_h->e_shnum)
539 old_mdebug_index = -1; /* just means no such section was present */ 540 old_mdebug_index = -1; /* just means no such section was present */
540 541
541 /* Find the old .bss section. Figure out parameters of the new 542 /* Find the old .bss section. */
542 data2 and bss sections. */
543 543
544 for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++) 544 for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
545 { 545 {
@@ -554,6 +554,24 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
554 if (old_bss_index == old_file_h->e_shnum) 554 if (old_bss_index == old_file_h->e_shnum)
555 fatal ("Can't find .bss in %s.\n", old_name, 0); 555 fatal ("Can't find .bss in %s.\n", old_name, 0);
556 556
557 /* Find the old .data section. Figure out parameters of
558 the new data2 and bss sections. */
559
560 for (old_data_index = 1;
561 old_data_index < old_file_h->e_shnum;
562 old_data_index++)
563 {
564#ifdef DEBUG
565 fprintf (stderr, "Looking for .data - found %s\n",
566 old_section_names + OLD_SECTION_H(old_data_index).sh_name);
567#endif
568 if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,
569 ".data"))
570 break;
571 }
572 if (old_data_index == old_file_h->e_shnum)
573 fatal ("Can't find .data in %s.\n", old_name, 0);
574
557 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; 575 old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
558 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; 576 old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
559#if defined(emacs) || !defined(DEBUG) 577#if defined(emacs) || !defined(DEBUG)
@@ -564,7 +582,10 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
564#endif 582#endif
565 new_data2_addr = old_bss_addr; 583 new_data2_addr = old_bss_addr;
566 new_data2_size = new_bss_addr - old_bss_addr; 584 new_data2_size = new_bss_addr - old_bss_addr;
567 new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; 585 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset +
586 (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
587 new_offsets_shift = new_bss_addr -
588 ((old_bss_addr & ~0xfff) + ((old_bss_addr & 0xfff) ? 0x1000 : 0));
568 589
569#ifdef DEBUG 590#ifdef DEBUG
570 fprintf (stderr, "old_bss_index %d\n", old_bss_index); 591 fprintf (stderr, "old_bss_index %d\n", old_bss_index);
@@ -574,6 +595,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
574 fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); 595 fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
575 fprintf (stderr, "new_data2_size %x\n", new_data2_size); 596 fprintf (stderr, "new_data2_size %x\n", new_data2_size);
576 fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); 597 fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
598 fprintf (stderr, "new_offsets_shift %x\n", new_offsets_shift);
577#endif 599#endif
578 600
579 if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size) 601 if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
@@ -587,7 +609,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
587 if (new_file < 0) 609 if (new_file < 0)
588 fatal ("Can't creat (%s): errno %d\n", new_name, errno); 610 fatal ("Can't creat (%s): errno %d\n", new_name, errno);
589 611
590 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size; 612 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_offsets_shift;
591 613
592 if (ftruncate (new_file, new_file_size)) 614 if (ftruncate (new_file, new_file_size))
593 fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); 615 fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
@@ -602,7 +624,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
602 new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff); 624 new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
603 new_section_h 625 new_section_h
604 = (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff 626 = (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff
605 + new_data2_size); 627 + new_offsets_shift);
606 628
607 /* Make our new file, program and section headers as copies of the 629 /* Make our new file, program and section headers as copies of the
608 originals. */ 630 originals. */
@@ -617,7 +639,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
617 /* Fix up file header. We'll add one section. Section header is 639 /* Fix up file header. We'll add one section. Section header is
618 further away now. */ 640 further away now. */
619 641
620 new_file_h->e_shoff += new_data2_size; 642 new_file_h->e_shoff += new_offsets_shift;
621 new_file_h->e_shnum += 1; 643 new_file_h->e_shnum += 1;
622 644
623#ifdef DEBUG 645#ifdef DEBUG
@@ -657,18 +679,18 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
657 if (n < 0) 679 if (n < 0)
658 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); 680 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
659 681
660 NEW_PROGRAM_H (n).p_filesz += new_data2_size; 682 NEW_PROGRAM_H (n).p_filesz += new_offsets_shift;
661 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; 683 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
662 684
663#if 1 /* Maybe allow section after data2 - does this ever happen? */ 685#if 1 /* Maybe allow section after data2 - does this ever happen? */
664 for (n = new_file_h->e_phnum - 1; n >= 0; n--) 686 for (n = new_file_h->e_phnum - 1; n >= 0; n--)
665 { 687 {
666 if (NEW_PROGRAM_H (n).p_vaddr 688 if (NEW_PROGRAM_H (n).p_vaddr
667 && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr) 689 && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
668 NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size; 690 NEW_PROGRAM_H (n).p_vaddr += new_offsets_shift - old_bss_size;
669 691
670 if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset) 692 if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
671 NEW_PROGRAM_H (n).p_offset += new_data2_size; 693 NEW_PROGRAM_H (n).p_offset += new_offsets_shift;
672 } 694 }
673#endif 695#endif
674 696
@@ -690,9 +712,17 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
690 for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++) 712 for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
691 { 713 {
692 caddr_t src; 714 caddr_t src;
693 /* If it is bss section, insert the new data2 section before it. */ 715
694 if (n == old_bss_index) 716 if (n < old_bss_index)
717 {
718 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
719 old_file_h->e_shentsize);
720
721 }
722 else if (n == old_bss_index)
695 { 723 {
724
725 /* If it is bss section, insert the new data2 section before it. */
696 /* Steal the data section header for this data2 section. */ 726 /* Steal the data section header for this data2 section. */
697 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), 727 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
698 new_file_h->e_shentsize); 728 new_file_h->e_shentsize);
@@ -710,28 +740,32 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
710 (caddr_t) OLD_SECTION_H (n).sh_addr, 740 (caddr_t) OLD_SECTION_H (n).sh_addr,
711 new_data2_size); 741 new_data2_size);
712 nn++; 742 nn++;
713 } 743 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
744 old_file_h->e_shentsize);
714 745
715 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), 746 /* The new bss section's size is zero, and its file offset and virtual
716 old_file_h->e_shentsize); 747 address should be off by NEW_OFFSETS_SHIFT. */
717 748 NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
718 /* The new bss section's size is zero, and its file offset and virtual 749 NEW_SECTION_H (nn).sh_addr = new_bss_addr;
719 address should be off by NEW_DATA2_SIZE. */
720 if (n == old_bss_index)
721 {
722 /* NN should be `old_bss_index + 1' at this point. */
723 NEW_SECTION_H (nn).sh_offset += new_data2_size;
724 NEW_SECTION_H (nn).sh_addr += new_data2_size;
725 /* Let the new bss section address alignment be the same as the 750 /* Let the new bss section address alignment be the same as the
726 section address alignment followed the old bss section, so 751 section address alignment followed the old bss section, so
727 this section will be placed in exactly the same place. */ 752 this section will be placed in exactly the same place. */
728 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; 753 NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
729 NEW_SECTION_H (nn).sh_size = 0; 754 NEW_SECTION_H (nn).sh_size = 0;
730 } 755 }
731 /* Any section that was original placed AFTER the bss section should now 756 else /* n > old_bss_index */
732 be off by NEW_DATA2_SIZE. */ 757 {
733 else if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) 758
734 NEW_SECTION_H (nn).sh_offset += new_data2_size; 759 memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
760 old_file_h->e_shentsize);
761
762 }
763
764 /* Any section that was original placed AFTER the bss
765 section must now be adjusted by NEW_OFFSETS_SHIFT. */
766
767 if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
768 NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
735 769
736 /* If any section hdr refers to the section after the new .data 770 /* If any section hdr refers to the section after the new .data
737 section, make it refer to next one because we have inserted 771 section, make it refer to next one because we have inserted
@@ -753,8 +787,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
753 ".data" in the strings table) get copied from the current process 787 ".data" in the strings table) get copied from the current process
754 instead of the old file. */ 788 instead of the old file. */
755 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") 789 if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
756 || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), 790 || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1")
757 ".data1")) 791 || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".got"))
758 src = (caddr_t) OLD_SECTION_H (n).sh_addr; 792 src = (caddr_t) OLD_SECTION_H (n).sh_addr;
759 else 793 else
760 src = old_base + OLD_SECTION_H (n).sh_offset; 794 src = old_base + OLD_SECTION_H (n).sh_offset;
@@ -778,42 +812,42 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
778 n_phdrr->__fileaddr += movement; \ 812 n_phdrr->__fileaddr += movement; \
779 } 813 }
780 814
781 HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset); 815 HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
782 HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset); 816 HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
783 unsigned movement = new_data2_size; 817 unsigned movement = new_offsets_shift;
784 818
785 MDEBUGADJUST (idnMax, cbDnOffset); 819 MDEBUGADJUST (idnMax, cbDnOffset);
786 MDEBUGADJUST (ipdMax, cbPdOffset); 820 MDEBUGADJUST (ipdMax, cbPdOffset);
787 MDEBUGADJUST (isymMax, cbSymOffset); 821 MDEBUGADJUST (isymMax, cbSymOffset);
788 MDEBUGADJUST (ioptMax, cbOptOffset); 822 MDEBUGADJUST (ioptMax, cbOptOffset);
789 MDEBUGADJUST (iauxMax, cbAuxOffset); 823 MDEBUGADJUST (iauxMax, cbAuxOffset);
790 MDEBUGADJUST (issMax, cbSsOffset); 824 MDEBUGADJUST (issMax, cbSsOffset);
791 MDEBUGADJUST (issExtMax, cbSsExtOffset); 825 MDEBUGADJUST (issExtMax, cbSsExtOffset);
792 MDEBUGADJUST (ifdMax, cbFdOffset); 826 MDEBUGADJUST (ifdMax, cbFdOffset);
793 MDEBUGADJUST (crfd, cbRfdOffset); 827 MDEBUGADJUST (crfd, cbRfdOffset);
794 MDEBUGADJUST (iextMax, cbExtOffset); 828 MDEBUGADJUST (iextMax, cbExtOffset);
795 /* The Line Section, being possible off in a hole of the object, 829 /* The Line Section, being possible off in a hole of the object,
796 requires special handling. */ 830 requires special handling. */
797 if (n_phdrr->cbLine > 0) 831 if (n_phdrr->cbLine > 0)
798 { 832 {
799 if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset 833 if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
800 + OLD_SECTION_H (n).sh_size)) 834 + OLD_SECTION_H (n).sh_size))
801 { 835 {
802 /* line data is in a hole in elf. do special copy and adjust 836 /* line data is in a hole in elf. do special copy and adjust
803 for this ld mistake. 837 for this ld mistake.
804 */ 838 */
805 n_phdrr->cbLineOffset += movement; 839 n_phdrr->cbLineOffset += movement;
806 840
807 memcpy (n_phdrr->cbLineOffset + new_base, 841 memcpy (n_phdrr->cbLineOffset + new_base,
808 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine); 842 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
809 } 843 }
810 else 844 else
811 { 845 {
812 /* somehow line data is in .mdebug as it is supposed to be. */ 846 /* somehow line data is in .mdebug as it is supposed to be. */
813 MDEBUGADJUST (cbLine, cbLineOffset); 847 MDEBUGADJUST (cbLine, cbLineOffset);
814 } 848 }
815 } 849 }
816 } 850 }
817 851
818 /* If it is the symbol table, its st_shndx field needs to be patched. */ 852 /* If it is the symbol table, its st_shndx field needs to be patched. */
819 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB 853 if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB