diff options
| author | Andreas Schwab | 2009-02-02 16:06:58 +0000 |
|---|---|---|
| committer | Andreas Schwab | 2009-02-02 16:06:58 +0000 |
| commit | 826ba17e917e1f94267d0dc135c5b157b062dcd9 (patch) | |
| tree | ae6b18b9e1c93c6b4595dd75e95e48353c4248cc /src | |
| parent | 1b7c198ad16aac7eae623980acce27eec671df46 (diff) | |
| download | emacs-826ba17e917e1f94267d0dc135c5b157b062dcd9.tar.gz emacs-826ba17e917e1f94267d0dc135c5b157b062dcd9.zip | |
(unexec): Handle unaligned bss offset.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 4 | ||||
| -rw-r--r-- | src/unexelf.c | 43 |
2 files changed, 30 insertions, 17 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 36fe949e633..6ccef6df766 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | 2009-02-02 Andreas Schwab <schwab@suse.de> | ||
| 2 | |||
| 3 | * unexelf.c (unexec): Handle unaligned bss offset. | ||
| 4 | |||
| 1 | 2009-02-01 Adrian Robert <Adrian.B.Robert@gmail.com> | 5 | 2009-02-01 Adrian Robert <Adrian.B.Robert@gmail.com> |
| 2 | 6 | ||
| 3 | * nsterm.m (ns_read_socket): Copy 2009-01-29 and 2009-01-30 | 7 | * nsterm.m (ns_read_socket): Copy 2009-01-29 and 2009-01-30 |
diff --git a/src/unexelf.c b/src/unexelf.c index 6213aaf88fd..4e1e39a3f70 100644 --- a/src/unexelf.c +++ b/src/unexelf.c | |||
| @@ -27,8 +27,8 @@ what you give them. Help stamp out software-hoarding! */ | |||
| 27 | * unexec.c - Convert a running program into an a.out file. | 27 | * unexec.c - Convert a running program into an a.out file. |
| 28 | * | 28 | * |
| 29 | * Author: Spencer W. Thomas | 29 | * Author: Spencer W. Thomas |
| 30 | * Computer Science Dept. | 30 | * Computer Science Dept. |
| 31 | * University of Utah | 31 | * University of Utah |
| 32 | * Date: Tue Mar 2 1982 | 32 | * Date: Tue Mar 2 1982 |
| 33 | * Modified heavily since then. | 33 | * Modified heavily since then. |
| 34 | * | 34 | * |
| @@ -680,6 +680,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 680 | ElfW(Word) old_bss_size, new_data2_size; | 680 | ElfW(Word) old_bss_size, new_data2_size; |
| 681 | ElfW(Off) new_data2_offset; | 681 | ElfW(Off) new_data2_offset; |
| 682 | ElfW(Addr) new_data2_addr; | 682 | ElfW(Addr) new_data2_addr; |
| 683 | ElfW(Off) old_bss_offset; | ||
| 684 | ElfW(Word) new_data2_incr; | ||
| 683 | 685 | ||
| 684 | int n, nn; | 686 | int n, nn; |
| 685 | int old_bss_index, old_sbss_index, old_plt_index; | 687 | int old_bss_index, old_sbss_index, old_plt_index; |
| @@ -754,6 +756,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 754 | { | 756 | { |
| 755 | old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; | 757 | old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; |
| 756 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; | 758 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; |
| 759 | old_bss_offset = OLD_SECTION_H (old_bss_index).sh_offset; | ||
| 757 | new_data2_index = old_bss_index; | 760 | new_data2_index = old_bss_index; |
| 758 | } | 761 | } |
| 759 | else if (old_plt_index != -1 | 762 | else if (old_plt_index != -1 |
| @@ -766,6 +769,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 766 | + OLD_SECTION_H (old_plt_index).sh_size; | 769 | + OLD_SECTION_H (old_plt_index).sh_size; |
| 767 | if (old_sbss_index != -1) | 770 | if (old_sbss_index != -1) |
| 768 | old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size; | 771 | old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size; |
| 772 | old_bss_offset = OLD_SECTION_H (old_plt_index).sh_offset; | ||
| 769 | new_data2_index = old_plt_index; | 773 | new_data2_index = old_plt_index; |
| 770 | } | 774 | } |
| 771 | else | 775 | else |
| @@ -773,6 +777,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 773 | old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr; | 777 | old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr; |
| 774 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size | 778 | old_bss_size = OLD_SECTION_H (old_bss_index).sh_size |
| 775 | + OLD_SECTION_H (old_sbss_index).sh_size; | 779 | + OLD_SECTION_H (old_sbss_index).sh_size; |
| 780 | old_bss_offset = OLD_SECTION_H (old_sbss_index).sh_offset; | ||
| 776 | new_data2_index = old_sbss_index; | 781 | new_data2_index = old_sbss_index; |
| 777 | } | 782 | } |
| 778 | 783 | ||
| @@ -789,17 +794,24 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 789 | #endif | 794 | #endif |
| 790 | new_data2_addr = old_bss_addr; | 795 | new_data2_addr = old_bss_addr; |
| 791 | new_data2_size = new_bss_addr - old_bss_addr; | 796 | new_data2_size = new_bss_addr - old_bss_addr; |
| 792 | new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset + | 797 | new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset |
| 793 | (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr); | 798 | + (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr); |
| 799 | /* This is the amount by which the sections following the bss sections | ||
| 800 | must be shifted in the image. It can differ from new_data2_size if | ||
| 801 | the end of the old .data section (and thus the offset of the .bss | ||
| 802 | section) was unaligned. */ | ||
| 803 | new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset); | ||
| 794 | 804 | ||
| 795 | #ifdef DEBUG | 805 | #ifdef DEBUG |
| 796 | fprintf (stderr, "old_bss_index %d\n", old_bss_index); | 806 | fprintf (stderr, "old_bss_index %d\n", old_bss_index); |
| 797 | fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); | 807 | fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); |
| 798 | fprintf (stderr, "old_bss_size %x\n", old_bss_size); | 808 | fprintf (stderr, "old_bss_size %x\n", old_bss_size); |
| 809 | fprintf (stderr, "old_bss_offset %x\n", old_bss_offset); | ||
| 799 | fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); | 810 | fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); |
| 800 | fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); | 811 | fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); |
| 801 | fprintf (stderr, "new_data2_size %x\n", new_data2_size); | 812 | fprintf (stderr, "new_data2_size %x\n", new_data2_size); |
| 802 | fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); | 813 | fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); |
| 814 | fprintf (stderr, "new_data2_incr %x\n", new_data2_incr); | ||
| 803 | #endif | 815 | #endif |
| 804 | 816 | ||
| 805 | if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size) | 817 | if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size) |
| @@ -813,7 +825,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 813 | if (new_file < 0) | 825 | if (new_file < 0) |
| 814 | fatal ("Can't creat (%s): errno %d\n", new_name, errno); | 826 | fatal ("Can't creat (%s): errno %d\n", new_name, errno); |
| 815 | 827 | ||
| 816 | new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size; | 828 | new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_incr; |
| 817 | 829 | ||
| 818 | if (ftruncate (new_file, new_file_size)) | 830 | if (ftruncate (new_file, new_file_size)) |
| 819 | fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); | 831 | fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); |
| @@ -826,7 +838,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 826 | new_file_h = (ElfW(Ehdr) *) new_base; | 838 | new_file_h = (ElfW(Ehdr) *) new_base; |
| 827 | new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff); | 839 | new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff); |
| 828 | new_section_h = (ElfW(Shdr) *) | 840 | new_section_h = (ElfW(Shdr) *) |
| 829 | ((byte *) new_base + old_file_h->e_shoff + new_data2_size); | 841 | ((byte *) new_base + old_file_h->e_shoff + new_data2_incr); |
| 830 | 842 | ||
| 831 | /* Make our new file, program and section headers as copies of the | 843 | /* Make our new file, program and section headers as copies of the |
| 832 | originals. */ | 844 | originals. */ |
| @@ -841,7 +853,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 841 | /* Fix up file header. We'll add one section. Section header is | 853 | /* Fix up file header. We'll add one section. Section header is |
| 842 | further away now. */ | 854 | further away now. */ |
| 843 | 855 | ||
| 844 | new_file_h->e_shoff += new_data2_size; | 856 | new_file_h->e_shoff += new_data2_incr; |
| 845 | new_file_h->e_shnum += 1; | 857 | new_file_h->e_shnum += 1; |
| 846 | 858 | ||
| 847 | #ifdef DEBUG | 859 | #ifdef DEBUG |
| @@ -901,7 +913,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 901 | NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size; | 913 | NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size; |
| 902 | 914 | ||
| 903 | if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset) | 915 | if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset) |
| 904 | NEW_PROGRAM_H (n).p_offset += new_data2_size; | 916 | NEW_PROGRAM_H (n).p_offset += new_data2_incr; |
| 905 | } | 917 | } |
| 906 | #endif | 918 | #endif |
| 907 | 919 | ||
| @@ -957,10 +969,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 957 | ) | 969 | ) |
| 958 | { | 970 | { |
| 959 | /* NN should be `old_s?bss_index + 1' at this point. */ | 971 | /* NN should be `old_s?bss_index + 1' at this point. */ |
| 960 | NEW_SECTION_H (nn).sh_offset = | 972 | NEW_SECTION_H (nn).sh_offset = new_data2_offset + new_data2_size; |
| 961 | NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size; | 973 | NEW_SECTION_H (nn).sh_addr = new_data2_addr + new_data2_size; |
| 962 | NEW_SECTION_H (nn).sh_addr = | ||
| 963 | NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size; | ||
| 964 | /* Let the new bss section address alignment be the same as the | 974 | /* Let the new bss section address alignment be the same as the |
| 965 | section address alignment followed the old bss section, so | 975 | section address alignment followed the old bss section, so |
| 966 | this section will be placed in exactly the same place. */ | 976 | this section will be placed in exactly the same place. */ |
| @@ -970,16 +980,15 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 970 | else | 980 | else |
| 971 | { | 981 | { |
| 972 | /* Any section that was originally placed after the .bss | 982 | /* Any section that was originally placed after the .bss |
| 973 | section should now be off by NEW_DATA2_SIZE. If a | 983 | section should now be off by NEW_DATA2_INCR. If a |
| 974 | section overlaps the .bss section, consider it to be | 984 | section overlaps the .bss section, consider it to be |
| 975 | placed after the .bss section. Overlap can occur if the | 985 | placed after the .bss section. Overlap can occur if the |
| 976 | section just before .bss has less-strict alignment; this | 986 | section just before .bss has less-strict alignment; this |
| 977 | was observed between .symtab and .bss on Solaris 2.5.1 | 987 | was observed between .symtab and .bss on Solaris 2.5.1 |
| 978 | (sparc) with GCC snapshot 960602. */ | 988 | (sparc) with GCC snapshot 960602. */ |
| 979 | 989 | ||
| 980 | if (NEW_SECTION_H (nn).sh_offset + NEW_SECTION_H (nn).sh_size | 990 | if (NEW_SECTION_H (nn).sh_offset >= old_bss_offset) |
| 981 | > new_data2_offset) | 991 | NEW_SECTION_H (nn).sh_offset += new_data2_incr; |
| 982 | NEW_SECTION_H (nn).sh_offset += new_data2_size; | ||
| 983 | 992 | ||
| 984 | /* Any section that was originally placed after the section | 993 | /* Any section that was originally placed after the section |
| 985 | header table should now be off by the size of one section | 994 | header table should now be off by the size of one section |
| @@ -1084,7 +1093,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 1084 | #if defined (_SYSTYPE_SYSV) | 1093 | #if defined (_SYSTYPE_SYSV) |
| 1085 | if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG | 1094 | if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG |
| 1086 | && old_mdebug_index != -1) | 1095 | && old_mdebug_index != -1) |
| 1087 | { | 1096 | { |
| 1088 | int diff = NEW_SECTION_H(nn).sh_offset | 1097 | int diff = NEW_SECTION_H(nn).sh_offset |
| 1089 | - OLD_SECTION_H(old_mdebug_index).sh_offset; | 1098 | - OLD_SECTION_H(old_mdebug_index).sh_offset; |
| 1090 | HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base); | 1099 | HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base); |