diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/unexelf.c | 290 |
1 files changed, 77 insertions, 213 deletions
diff --git a/src/unexelf.c b/src/unexelf.c index 15a4cdedfc9..4e9c50d5352 100644 --- a/src/unexelf.c +++ b/src/unexelf.c | |||
| @@ -535,29 +535,6 @@ verify ((! TYPE_SIGNED (ElfW (Half)) | |||
| 535 | /* Get the address of a particular section or program header entry, | 535 | /* Get the address of a particular section or program header entry, |
| 536 | * accounting for the size of the entries. | 536 | * accounting for the size of the entries. |
| 537 | */ | 537 | */ |
| 538 | /* | ||
| 539 | On PPC Reference Platform running Solaris 2.5.1 | ||
| 540 | the plt section is also of type NOBI like the bss section. | ||
| 541 | (not really stored) and therefore sections after the bss | ||
| 542 | section start at the plt offset. The plt section is always | ||
| 543 | the one just before the bss section. | ||
| 544 | Thus, we modify the test from | ||
| 545 | if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) | ||
| 546 | to | ||
| 547 | if (NEW_SECTION_H (nn).sh_offset >= | ||
| 548 | OLD_SECTION_H (old_bss_index-1).sh_offset) | ||
| 549 | This is just a hack. We should put the new data section | ||
| 550 | before the .plt section. | ||
| 551 | And we should not have this routine at all but use | ||
| 552 | the libelf library to read the old file and create the new | ||
| 553 | file. | ||
| 554 | The changed code is minimal and depends on prep set in m/prep.h | ||
| 555 | Erik Deumens | ||
| 556 | Quantum Theory Project | ||
| 557 | University of Florida | ||
| 558 | deumens@qtp.ufl.edu | ||
| 559 | Apr 23, 1996 | ||
| 560 | */ | ||
| 561 | 538 | ||
| 562 | static void * | 539 | static void * |
| 563 | entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize) | 540 | entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize) |
| @@ -570,23 +547,14 @@ entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize) | |||
| 570 | (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize)) | 547 | (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize)) |
| 571 | #define NEW_SECTION_H(n) \ | 548 | #define NEW_SECTION_H(n) \ |
| 572 | (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize)) | 549 | (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize)) |
| 550 | #define OLD_PROGRAM_H(n) \ | ||
| 551 | (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize)) | ||
| 573 | #define NEW_PROGRAM_H(n) \ | 552 | #define NEW_PROGRAM_H(n) \ |
| 574 | (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize)) | 553 | (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize)) |
| 575 | 554 | ||
| 576 | #define PATCH_INDEX(n) ((n) += old_bss_index <= (n)) | 555 | #define PATCH_INDEX(n) ((n) += old_bss_index <= (n)) |
| 577 | typedef unsigned char byte; | 556 | typedef unsigned char byte; |
| 578 | 557 | ||
| 579 | /* Round X up to a multiple of Y. */ | ||
| 580 | |||
| 581 | static ElfW (Addr) | ||
| 582 | round_up (ElfW (Addr) x, ElfW (Addr) y) | ||
| 583 | { | ||
| 584 | ElfW (Addr) rem = x % y; | ||
| 585 | if (rem == 0) | ||
| 586 | return x; | ||
| 587 | return x - rem + y; | ||
| 588 | } | ||
| 589 | |||
| 590 | /* Return the index of the section named NAME. | 558 | /* Return the index of the section named NAME. |
| 591 | SECTION_NAMES, FILE_NAME and FILE_H give information | 559 | SECTION_NAMES, FILE_NAME and FILE_H give information |
| 592 | about the file we are looking in. | 560 | about the file we are looking in. |
| @@ -650,16 +618,15 @@ unexec (const char *new_name, const char *old_name) | |||
| 650 | /* Point to the section name table in the old file. */ | 618 | /* Point to the section name table in the old file. */ |
| 651 | char *old_section_names; | 619 | char *old_section_names; |
| 652 | 620 | ||
| 621 | ElfW (Phdr) *old_bss_seg, *new_bss_seg; | ||
| 653 | ElfW (Addr) old_bss_addr, new_bss_addr; | 622 | ElfW (Addr) old_bss_addr, new_bss_addr; |
| 654 | ElfW (Word) old_bss_size, new_data2_size; | 623 | ElfW (Word) old_bss_size, new_data2_size; |
| 655 | ElfW (Off) new_data2_offset; | 624 | ElfW (Off) new_data2_offset; |
| 656 | ElfW (Addr) new_data2_addr; | 625 | ElfW (Addr) new_data2_addr; |
| 657 | ElfW (Off) old_bss_offset; | 626 | ElfW (Off) old_bss_offset; |
| 658 | ElfW (Word) new_data2_incr; | ||
| 659 | 627 | ||
| 660 | ptrdiff_t n, nn; | 628 | ptrdiff_t n, nn; |
| 661 | ptrdiff_t old_bss_index, old_sbss_index, old_plt_index; | 629 | ptrdiff_t old_bss_index, old_data_index; |
| 662 | ptrdiff_t old_data_index, new_data2_index; | ||
| 663 | struct stat stat_buf; | 630 | struct stat stat_buf; |
| 664 | off_t old_file_size; | 631 | off_t old_file_size; |
| 665 | 632 | ||
| @@ -703,54 +670,40 @@ unexec (const char *new_name, const char *old_name) | |||
| 703 | old_section_names = (char *) old_base | 670 | old_section_names = (char *) old_base |
| 704 | + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; | 671 | + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; |
| 705 | 672 | ||
| 706 | /* Find the old .bss section. Figure out parameters of the new | 673 | /* Find the PT_LOAD header covering the highest address. This |
| 707 | data2 and bss sections. */ | 674 | segment will be where bss sections are located, past p_filesz. */ |
| 708 | 675 | old_bss_seg = 0; | |
| 709 | old_bss_index = find_section (".bss", old_section_names, | 676 | for (n = old_file_h->e_phnum; --n >= 0; ) |
| 710 | old_name, old_file_h, old_section_h, 0); | ||
| 711 | |||
| 712 | old_sbss_index = find_section (".sbss", old_section_names, | ||
| 713 | old_name, old_file_h, old_section_h, 1); | ||
| 714 | if (old_sbss_index != -1) | ||
| 715 | if (OLD_SECTION_H (old_sbss_index).sh_type != SHT_NOBITS) | ||
| 716 | old_sbss_index = -1; | ||
| 717 | |||
| 718 | /* PowerPC64 has .plt in the BSS section. */ | ||
| 719 | old_plt_index = find_section (".plt", old_section_names, | ||
| 720 | old_name, old_file_h, old_section_h, 1); | ||
| 721 | if (old_plt_index != -1) | ||
| 722 | if (OLD_SECTION_H (old_plt_index).sh_type != SHT_NOBITS) | ||
| 723 | old_plt_index = -1; | ||
| 724 | |||
| 725 | if (old_sbss_index == -1 && old_plt_index == -1) | ||
| 726 | { | ||
| 727 | old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; | ||
| 728 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; | ||
| 729 | old_bss_offset = OLD_SECTION_H (old_bss_index).sh_offset; | ||
| 730 | new_data2_index = old_bss_index; | ||
| 731 | } | ||
| 732 | else if (old_plt_index != -1 | ||
| 733 | && (old_sbss_index == -1 | ||
| 734 | || (OLD_SECTION_H (old_sbss_index).sh_addr | ||
| 735 | > OLD_SECTION_H (old_plt_index).sh_addr))) | ||
| 736 | { | 677 | { |
| 737 | old_bss_addr = OLD_SECTION_H (old_plt_index).sh_addr; | 678 | ElfW (Phdr) *seg = &OLD_PROGRAM_H (n); |
| 738 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size | 679 | if (seg->p_type == PT_LOAD |
| 739 | + OLD_SECTION_H (old_plt_index).sh_size; | 680 | && (old_bss_seg == 0 |
| 740 | if (old_sbss_index != -1) | 681 | || seg->p_vaddr > old_bss_seg->p_vaddr)) |
| 741 | old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size; | 682 | old_bss_seg = seg; |
| 742 | old_bss_offset = OLD_SECTION_H (old_plt_index).sh_offset; | ||
| 743 | new_data2_index = old_plt_index; | ||
| 744 | } | 683 | } |
| 745 | else | 684 | |
| 685 | /* Note that old_bss_addr may be lower than the first bss section | ||
| 686 | address, since the section may need aligning. */ | ||
| 687 | old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz; | ||
| 688 | old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz; | ||
| 689 | old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz; | ||
| 690 | |||
| 691 | /* Find the first bss style section in the bss segment range. */ | ||
| 692 | old_bss_index = -1; | ||
| 693 | for (n = old_file_h->e_shnum; --n > 0; ) | ||
| 746 | { | 694 | { |
| 747 | old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr; | 695 | ElfW (Shdr) *shdr = &OLD_SECTION_H (n); |
| 748 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size | 696 | if (shdr->sh_type == SHT_NOBITS |
| 749 | + OLD_SECTION_H (old_sbss_index).sh_size; | 697 | && shdr->sh_addr >= old_bss_addr |
| 750 | old_bss_offset = OLD_SECTION_H (old_sbss_index).sh_offset; | 698 | && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size |
| 751 | new_data2_index = old_sbss_index; | 699 | && (old_bss_index == -1 |
| 700 | || OLD_SECTION_H (old_bss_index).sh_addr > shdr->sh_addr)) | ||
| 701 | old_bss_index = n; | ||
| 752 | } | 702 | } |
| 753 | 703 | ||
| 704 | if (old_bss_index == -1) | ||
| 705 | fatal ("no bss section found"); | ||
| 706 | |||
| 754 | /* Find the old .data section. Figure out parameters of | 707 | /* Find the old .data section. Figure out parameters of |
| 755 | the new data2 and bss sections. */ | 708 | the new data2 and bss sections. */ |
| 756 | 709 | ||
| @@ -761,13 +714,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 761 | new_bss_addr = (ElfW (Addr)) new_break; | 714 | new_bss_addr = (ElfW (Addr)) new_break; |
| 762 | new_data2_addr = old_bss_addr; | 715 | new_data2_addr = old_bss_addr; |
| 763 | new_data2_size = new_bss_addr - old_bss_addr; | 716 | new_data2_size = new_bss_addr - old_bss_addr; |
| 764 | new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset | 717 | new_data2_offset = old_bss_offset; |
| 765 | + (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr); | ||
| 766 | /* This is the amount by which the sections following the bss sections | ||
| 767 | must be shifted in the image. It can differ from new_data2_size if | ||
| 768 | the end of the old .data section (and thus the offset of the .bss | ||
| 769 | section) was unaligned. */ | ||
| 770 | new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset); | ||
| 771 | 718 | ||
| 772 | #ifdef UNEXELF_DEBUG | 719 | #ifdef UNEXELF_DEBUG |
| 773 | fprintf (stderr, "old_bss_index %td\n", old_bss_index); | 720 | fprintf (stderr, "old_bss_index %td\n", old_bss_index); |
| @@ -778,7 +725,6 @@ unexec (const char *new_name, const char *old_name) | |||
| 778 | DEBUG_LOG (new_data2_addr); | 725 | DEBUG_LOG (new_data2_addr); |
| 779 | DEBUG_LOG (new_data2_size); | 726 | DEBUG_LOG (new_data2_size); |
| 780 | DEBUG_LOG (new_data2_offset); | 727 | DEBUG_LOG (new_data2_offset); |
| 781 | DEBUG_LOG (new_data2_incr); | ||
| 782 | #endif | 728 | #endif |
| 783 | 729 | ||
| 784 | if (new_bss_addr < old_bss_addr + old_bss_size) | 730 | if (new_bss_addr < old_bss_addr + old_bss_size) |
| @@ -792,7 +738,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 792 | if (new_file < 0) | 738 | if (new_file < 0) |
| 793 | fatal ("Can't creat (%s): %s", new_name, strerror (errno)); | 739 | fatal ("Can't creat (%s): %s", new_name, strerror (errno)); |
| 794 | 740 | ||
| 795 | new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_incr; | 741 | new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_size; |
| 796 | 742 | ||
| 797 | if (ftruncate (new_file, new_file_size)) | 743 | if (ftruncate (new_file, new_file_size)) |
| 798 | fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno)); | 744 | fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno)); |
| @@ -811,15 +757,15 @@ unexec (const char *new_name, const char *old_name) | |||
| 811 | /* Fix up file header. We'll add one section. Section header is | 757 | /* Fix up file header. We'll add one section. Section header is |
| 812 | further away now. */ | 758 | further away now. */ |
| 813 | 759 | ||
| 814 | new_file_h->e_shoff += new_data2_incr; | 760 | if (new_file_h->e_shoff >= old_bss_offset) |
| 761 | new_file_h->e_shoff += new_data2_size; | ||
| 815 | new_file_h->e_shnum += 1; | 762 | new_file_h->e_shnum += 1; |
| 816 | 763 | ||
| 817 | /* Modify the e_shstrndx if necessary. */ | 764 | /* Modify the e_shstrndx if necessary. */ |
| 818 | PATCH_INDEX (new_file_h->e_shstrndx); | 765 | PATCH_INDEX (new_file_h->e_shstrndx); |
| 819 | 766 | ||
| 820 | new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff); | 767 | new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff); |
| 821 | new_section_h = (ElfW (Shdr) *) | 768 | new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff); |
| 822 | ((byte *) new_base + old_file_h->e_shoff + new_data2_incr); | ||
| 823 | 769 | ||
| 824 | memcpy (new_program_h, old_program_h, | 770 | memcpy (new_program_h, old_program_h, |
| 825 | old_file_h->e_phnum * old_file_h->e_phentsize); | 771 | old_file_h->e_phnum * old_file_h->e_phentsize); |
| @@ -831,65 +777,21 @@ unexec (const char *new_name, const char *old_name) | |||
| 831 | fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum); | 777 | fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum); |
| 832 | #endif | 778 | #endif |
| 833 | 779 | ||
| 834 | /* Fix up a new program header. Extend the writable data segment so | 780 | /* Fix up program header. Extend the writable data segment so |
| 835 | that the bss area is covered too. Find that segment by looking | 781 | that the bss area is covered too. */ |
| 836 | for a segment that ends just before the .bss area. Make sure | ||
| 837 | that no segments are above the new .data2. Put a loop at the end | ||
| 838 | to adjust the offset and address of any segment that is above | ||
| 839 | data2, just in case we decide to allow this later. */ | ||
| 840 | 782 | ||
| 841 | for (n = new_file_h->e_phnum; --n >= 0; ) | 783 | new_bss_seg = new_program_h + (old_bss_seg - old_program_h); |
| 842 | { | 784 | new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr; |
| 843 | /* Compute maximum of all requirements for alignment of section. */ | 785 | new_bss_seg->p_memsz = new_bss_seg->p_filesz; |
| 844 | ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align; | ||
| 845 | if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) | ||
| 846 | alignment = OLD_SECTION_H (old_bss_index).sh_addralign; | ||
| 847 | |||
| 848 | #ifdef __sgi | ||
| 849 | /* According to r02kar@x4u2.desy.de (Karsten Kuenne) | ||
| 850 | and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we | ||
| 851 | always get "Program segment above .bss" when dumping | ||
| 852 | when the executable doesn't have an sbss section. */ | ||
| 853 | if (old_sbss_index != -1) | ||
| 854 | #endif /* __sgi */ | ||
| 855 | if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz | ||
| 856 | > (old_sbss_index == -1 | ||
| 857 | ? old_bss_addr | ||
| 858 | : round_up (old_bss_addr, alignment))) | ||
| 859 | fatal ("Program segment above .bss in %s", old_name); | ||
| 860 | |||
| 861 | if (NEW_PROGRAM_H (n).p_type == PT_LOAD | ||
| 862 | && (round_up ((NEW_PROGRAM_H (n)).p_vaddr | ||
| 863 | + (NEW_PROGRAM_H (n)).p_filesz, | ||
| 864 | alignment) | ||
| 865 | == round_up (old_bss_addr, alignment))) | ||
| 866 | break; | ||
| 867 | } | ||
| 868 | if (n < 0) | ||
| 869 | fatal ("Couldn't find segment next to .bss in %s", old_name); | ||
| 870 | |||
| 871 | /* Make sure that the size includes any padding before the old .bss | ||
| 872 | section. */ | ||
| 873 | NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr; | ||
| 874 | NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; | ||
| 875 | |||
| 876 | #if 0 /* Maybe allow section after data2 - does this ever happen? */ | ||
| 877 | for (n = new_file_h->e_phnum; --n >= 0; ) | ||
| 878 | { | ||
| 879 | if (NEW_PROGRAM_H (n).p_vaddr | ||
| 880 | && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr) | ||
| 881 | NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size; | ||
| 882 | 786 | ||
| 883 | if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset) | 787 | /* Copy over what we have in memory now for the bss area. */ |
| 884 | NEW_PROGRAM_H (n).p_offset += new_data2_incr; | 788 | memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr, new_data2_size); |
| 885 | } | ||
| 886 | #endif | ||
| 887 | 789 | ||
| 888 | /* Fix up section headers based on new .data2 section. Any section | 790 | /* Fix up section headers based on new .data2 section. Any section |
| 889 | whose offset or virtual address is after the new .data2 section | 791 | whose offset or virtual address is after the new .data2 section |
| 890 | gets its value adjusted. .bss size becomes zero and new address | 792 | gets its value adjusted. .bss size becomes zero. data2 section |
| 891 | is set. data2 section header gets added by copying the existing | 793 | header gets added by copying the existing .data header and |
| 892 | .data header and modifying the offset, address and size. */ | 794 | modifying the offset, address and size. */ |
| 893 | 795 | ||
| 894 | /* Walk through all section headers, insert the new data2 section right | 796 | /* Walk through all section headers, insert the new data2 section right |
| 895 | before the new bss section. */ | 797 | before the new bss section. */ |
| @@ -900,9 +802,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 900 | ElfW (Shdr) *new_shdr = &NEW_SECTION_H (nn); | 802 | ElfW (Shdr) *new_shdr = &NEW_SECTION_H (nn); |
| 901 | 803 | ||
| 902 | /* If it is (s)bss section, insert the new data2 section before it. */ | 804 | /* If it is (s)bss section, insert the new data2 section before it. */ |
| 903 | /* new_data2_index is the index of either old_sbss or old_bss, that was | 805 | if (n == old_bss_index) |
| 904 | chosen as a section for new_data2. */ | ||
| 905 | if (n == new_data2_index) | ||
| 906 | { | 806 | { |
| 907 | /* Steal the data section header for this data2 section. */ | 807 | /* Steal the data section header for this data2 section. */ |
| 908 | memcpy (new_shdr, &OLD_SECTION_H (old_data_index), | 808 | memcpy (new_shdr, &OLD_SECTION_H (old_data_index), |
| @@ -911,68 +811,43 @@ unexec (const char *new_name, const char *old_name) | |||
| 911 | new_shdr->sh_addr = new_data2_addr; | 811 | new_shdr->sh_addr = new_data2_addr; |
| 912 | new_shdr->sh_offset = new_data2_offset; | 812 | new_shdr->sh_offset = new_data2_offset; |
| 913 | new_shdr->sh_size = new_data2_size; | 813 | new_shdr->sh_size = new_data2_size; |
| 914 | /* Use the bss section's alignment. This will assure that the | 814 | new_shdr->sh_addralign = 1; |
| 915 | new data2 section always be placed in the same spot as the old | ||
| 916 | bss section by any other application. */ | ||
| 917 | new_shdr->sh_addralign = old_shdr->sh_addralign; | ||
| 918 | |||
| 919 | /* Now copy over what we have in the memory now. */ | ||
| 920 | memcpy (new_shdr->sh_offset + new_base, | ||
| 921 | (caddr_t) old_shdr->sh_addr, | ||
| 922 | new_data2_size); | ||
| 923 | nn++; | 815 | nn++; |
| 924 | new_shdr++; | 816 | new_shdr++; |
| 925 | } | 817 | } |
| 926 | 818 | ||
| 927 | memcpy (new_shdr, old_shdr, old_file_h->e_shentsize); | 819 | memcpy (new_shdr, old_shdr, old_file_h->e_shentsize); |
| 928 | 820 | ||
| 929 | if (n == old_bss_index | 821 | if (new_shdr->sh_type == SHT_NOBITS |
| 930 | /* The new bss and sbss section's size is zero, and its file offset | 822 | && new_shdr->sh_addr >= old_bss_addr |
| 931 | and virtual address should be off by NEW_DATA2_SIZE. */ | 823 | && (new_shdr->sh_addr + new_shdr->sh_size |
| 932 | || n == old_sbss_index || n == old_plt_index | 824 | <= old_bss_addr + old_bss_size)) |
| 933 | ) | ||
| 934 | { | 825 | { |
| 935 | /* NN should be `old_s?bss_index + 1' at this point. */ | 826 | /* SHT_NOBITS sections do not need a valid sh_offset, so it |
| 936 | new_shdr->sh_offset = new_data2_offset + new_data2_size; | 827 | might be incorrect. Write the correct value. */ |
| 937 | new_shdr->sh_addr = new_data2_addr + new_data2_size; | 828 | new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr |
| 938 | /* Let the new bss section address alignment be the same as the | 829 | + new_bss_seg->p_offset); |
| 939 | section address alignment followed the old bss section, so | 830 | |
| 940 | this section will be placed in exactly the same place. */ | 831 | /* If this is was a SHT_NOBITS .plt section, then it is |
| 941 | new_shdr->sh_addralign = OLD_SECTION_H (nn).sh_addralign; | 832 | probably a PowerPC PLT. If it is PowerPC64 ELFv1 then |
| 833 | glibc ld.so doesn't initialize the toc pointer word. A | ||
| 834 | non-zero toc pointer word can defeat Power7 thread safety | ||
| 835 | during lazy update of a PLT entry. This only matters if | ||
| 836 | emacs becomes multi-threaded. */ | ||
| 837 | if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0) | ||
| 838 | memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size); | ||
| 839 | |||
| 840 | /* Set the new bss and sbss section's size to zero, because | ||
| 841 | we've already covered this address range by .data2. */ | ||
| 942 | new_shdr->sh_size = 0; | 842 | new_shdr->sh_size = 0; |
| 943 | } | 843 | } |
| 944 | else | 844 | else |
| 945 | { | 845 | { |
| 946 | /* Any section that was originally placed after the .bss | 846 | /* Any section that was originally placed after the .bss |
| 947 | section should now be off by NEW_DATA2_INCR. If a | 847 | section should now be off by NEW_DATA2_SIZE. */ |
| 948 | section overlaps the .bss section, consider it to be | ||
| 949 | placed after the .bss section. Overlap can occur if the | ||
| 950 | section just before .bss has less-strict alignment; this | ||
| 951 | was observed between .symtab and .bss on Solaris 2.5.1 | ||
| 952 | (sparc) with GCC snapshot 960602. | ||
| 953 | 848 | ||
| 954 | > dump -h temacs | 849 | if (new_shdr->sh_offset >= old_bss_offset) |
| 955 | 850 | new_shdr->sh_offset += new_data2_size; | |
| 956 | temacs: | ||
| 957 | |||
| 958 | **** SECTION HEADER TABLE **** | ||
| 959 | [No] Type Flags Addr Offset Size Name | ||
| 960 | Link Info Adralgn Entsize | ||
| 961 | |||
| 962 | [22] 1 3 0x335150 0x315150 0x4 .data.rel.local | ||
| 963 | 0 0 0x4 0 | ||
| 964 | |||
| 965 | [23] 8 3 0x335158 0x315158 0x42720 .bss | ||
| 966 | 0 0 0x8 0 | ||
| 967 | |||
| 968 | [24] 2 0 0 0x315154 0x1c9d0 .symtab | ||
| 969 | 25 1709 0x4 0x10 | ||
| 970 | */ | ||
| 971 | |||
| 972 | if (new_shdr->sh_offset >= old_bss_offset | ||
| 973 | || (new_shdr->sh_offset + new_shdr->sh_size | ||
| 974 | > new_data2_offset)) | ||
| 975 | new_shdr->sh_offset += new_data2_incr; | ||
| 976 | 851 | ||
| 977 | /* Any section that was originally placed after the section | 852 | /* Any section that was originally placed after the section |
| 978 | header table should now be off by the size of one section | 853 | header table should now be off by the size of one section |
| @@ -992,23 +867,13 @@ temacs: | |||
| 992 | && new_shdr->sh_type != SHT_DYNSYM) | 867 | && new_shdr->sh_type != SHT_DYNSYM) |
| 993 | PATCH_INDEX (new_shdr->sh_info); | 868 | PATCH_INDEX (new_shdr->sh_info); |
| 994 | 869 | ||
| 995 | if (old_sbss_index != -1) | ||
| 996 | if (!strcmp (old_section_names + new_shdr->sh_name, ".sbss")) | ||
| 997 | { | ||
| 998 | new_shdr->sh_offset = | ||
| 999 | round_up (new_shdr->sh_offset, | ||
| 1000 | new_shdr->sh_addralign); | ||
| 1001 | new_shdr->sh_type = SHT_PROGBITS; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | /* Now, start to copy the content of sections. */ | 870 | /* Now, start to copy the content of sections. */ |
| 1005 | if (new_shdr->sh_type == SHT_NULL | 871 | if (new_shdr->sh_type == SHT_NULL |
| 1006 | || new_shdr->sh_type == SHT_NOBITS) | 872 | || new_shdr->sh_type == SHT_NOBITS) |
| 1007 | continue; | 873 | continue; |
| 1008 | 874 | ||
| 1009 | /* Write out the sections. .data and .data1 (and data2, called | 875 | /* Some sections are copied from the current process instead of |
| 1010 | ".data" in the strings table) get copied from the current process | 876 | the old file. */ |
| 1011 | instead of the old file. */ | ||
| 1012 | if (!strcmp (old_section_names + new_shdr->sh_name, ".data") | 877 | if (!strcmp (old_section_names + new_shdr->sh_name, ".data") |
| 1013 | || !strcmp (old_section_names + new_shdr->sh_name, ".sdata") | 878 | || !strcmp (old_section_names + new_shdr->sh_name, ".sdata") |
| 1014 | || !strcmp (old_section_names + new_shdr->sh_name, ".lit4") | 879 | || !strcmp (old_section_names + new_shdr->sh_name, ".lit4") |
| @@ -1037,8 +902,7 @@ temacs: | |||
| 1037 | || !strcmp (old_section_names + new_shdr->sh_name, ".got") | 902 | || !strcmp (old_section_names + new_shdr->sh_name, ".got") |
| 1038 | #endif | 903 | #endif |
| 1039 | || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1") | 904 | || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1") |
| 1040 | || !strcmp (old_section_names + new_shdr->sh_name, ".data1") | 905 | || !strcmp (old_section_names + new_shdr->sh_name, ".data1")) |
| 1041 | || !strcmp (old_section_names + new_shdr->sh_name, ".sbss")) | ||
| 1042 | src = (caddr_t) old_shdr->sh_addr; | 906 | src = (caddr_t) old_shdr->sh_addr; |
| 1043 | else | 907 | else |
| 1044 | src = old_base + old_shdr->sh_offset; | 908 | src = old_base + old_shdr->sh_offset; |