diff options
| author | Richard M. Stallman | 1995-10-15 00:59:48 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1995-10-15 00:59:48 +0000 |
| commit | f5abdb044bc3b2f11e948af96d005ed74eca2a4f (patch) | |
| tree | 8b749d1ac7f37fdc9e835cd7610b63f0d43b5eed /src | |
| parent | 26fb39b5ef70defc0559f5f6b06b457afbf2cee7 (diff) | |
| download | emacs-f5abdb044bc3b2f11e948af96d005ed74eca2a4f.tar.gz emacs-f5abdb044bc3b2f11e948af96d005ed74eca2a4f.zip | |
(unexec): Find the old data section.
New variable new_offsets_shift used instead of new_data2_size
since they are not always the same. Simplify logic for copying
the headers and inserting new ones.
Diffstat (limited to 'src')
| -rw-r--r-- | src/unexsgi.c | 166 |
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 |