Package: emacs;
Reported by: Petr Hracek <phracek <at> redhat.com>
Date: Wed, 20 May 2015 07:59:01 UTC
Severity: important
Tags: patch
Done: Lars Ingebrigtsen <larsi <at> gnus.org>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Andreas Schwab <schwab <at> suse.de> To: YAMAMOTO Mitsuharu <mituharu <at> math.s.chiba-u.ac.jp> Cc: Petr Hracek <phracek <at> redhat.com>, Jaromir Capik <jcapik <at> redhat.com>, 20614 <at> debbugs.gnu.org, Eli Zaretskii <eliz <at> gnu.org> Subject: bug#20614: Segmentation fault when building on Power8 Little Endian Date: Sat, 10 Oct 2015 17:44:24 +0200
Please try this patch instead: diff --git a/src/unexelf.c b/src/unexelf.c index 483da6e..2e8b4c7 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -616,6 +616,32 @@ find_section (const char *name, const char *section_names, const char *file_name return -1; } +/* Find the index of the first bss (NOBITS) section, count the number + of bss sections that follow and compute the overall size of these + sections. */ +static int +find_bss_sections (const char *file_name, + ElfW(Ehdr) *old_file_h, ElfW(Shdr) *old_section_h, + ElfW (Word) *size, int *num) +{ + ptrdiff_t idx; + + for (idx = 1; idx < old_file_h->e_shnum; idx++) + if (OLD_SECTION_H (idx).sh_type == SHT_NOBITS) + { + ptrdiff_t idx2 = idx; + + while (OLD_SECTION_H (idx2 + 1).sh_type == SHT_NOBITS) + idx2++; + *size = (OLD_SECTION_H (idx2).sh_addr + OLD_SECTION_H (idx2).sh_size + - OLD_SECTION_H (idx).sh_addr); + *num = idx2 + 1 - idx; + return idx; + } + fatal ("Can't find bss section in %s", file_name); + return -1; +} + /* **************************************************************** * unexec * @@ -652,13 +678,14 @@ unexec (const char *new_name, const char *old_name) ElfW (Addr) old_bss_addr, new_bss_addr; ElfW (Word) old_bss_size, new_data2_size; + int n_bss_sections; ElfW (Off) new_data2_offset; ElfW (Addr) new_data2_addr; ElfW (Off) old_bss_offset; ElfW (Word) new_data2_incr; ptrdiff_t n, nn; - ptrdiff_t old_bss_index, old_sbss_index, old_plt_index; + ptrdiff_t old_bss_index; ptrdiff_t old_data_index, new_data2_index; #if defined _SYSTYPE_SYSV || defined __sgi ptrdiff_t old_mdebug_index; @@ -716,50 +743,12 @@ unexec (const char *new_name, const char *old_name) /* Find the old .bss section. Figure out parameters of the new data2 and bss sections. */ - old_bss_index = find_section (".bss", old_section_names, - old_name, old_file_h, old_section_h, 0); - - old_sbss_index = find_section (".sbss", old_section_names, - old_name, old_file_h, old_section_h, 1); - if (old_sbss_index != -1) - if (OLD_SECTION_H (old_sbss_index).sh_type != SHT_NOBITS) - old_sbss_index = -1; - - /* PowerPC64 has .plt in the BSS section. */ - old_plt_index = find_section (".plt", old_section_names, - old_name, old_file_h, old_section_h, 1); - if (old_plt_index != -1) - if (OLD_SECTION_H (old_plt_index).sh_type != SHT_NOBITS) - old_plt_index = -1; + old_bss_index = find_bss_sections (old_name, old_file_h, old_section_h, + &old_bss_size, &n_bss_sections); - if (old_sbss_index == -1 && old_plt_index == -1) - { - old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; - old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; - old_bss_offset = OLD_SECTION_H (old_bss_index).sh_offset; - new_data2_index = old_bss_index; - } - else if (old_plt_index != -1 - && (old_sbss_index == -1 - || (OLD_SECTION_H (old_sbss_index).sh_addr - > OLD_SECTION_H (old_plt_index).sh_addr))) - { - old_bss_addr = OLD_SECTION_H (old_plt_index).sh_addr; - old_bss_size = OLD_SECTION_H (old_bss_index).sh_size - + OLD_SECTION_H (old_plt_index).sh_size; - if (old_sbss_index != -1) - old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size; - old_bss_offset = OLD_SECTION_H (old_plt_index).sh_offset; - new_data2_index = old_plt_index; - } - else - { - old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr; - old_bss_size = OLD_SECTION_H (old_bss_index).sh_size - + OLD_SECTION_H (old_sbss_index).sh_size; - old_bss_offset = OLD_SECTION_H (old_sbss_index).sh_offset; - new_data2_index = old_sbss_index; - } + old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; + old_bss_offset = OLD_SECTION_H (old_bss_index).sh_offset; + new_data2_index = old_bss_index; /* Find the old .data section. Figure out parameters of the new data2 and bss sections. */ @@ -851,20 +840,11 @@ unexec (const char *new_name, const char *old_name) { /* Compute maximum of all requirements for alignment of section. */ ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align; - if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) + if (OLD_SECTION_H (old_bss_index).sh_addralign > alignment) alignment = OLD_SECTION_H (old_bss_index).sh_addralign; -#ifdef __sgi - /* According to r02kar <at> x4u2.desy.de (Karsten Kuenne) - and oliva <at> gnu.org (Alexandre Oliva), on IRIX 5.2, we - always get "Program segment above .bss" when dumping - when the executable doesn't have an sbss section. */ - if (old_sbss_index != -1) -#endif /* __sgi */ if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz - > (old_sbss_index == -1 - ? old_bss_addr - : round_up (old_bss_addr, alignment))) + > round_up (old_bss_addr, alignment)) fatal ("Program segment above .bss in %s", old_name); if (NEW_PROGRAM_H (n).p_type == PT_LOAD @@ -932,12 +912,10 @@ unexec (const char *new_name, const char *old_name) memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), old_file_h->e_shentsize); - if (n == old_bss_index - /* The new bss and sbss section's size is zero, and its file offset - and virtual address should be off by NEW_DATA2_SIZE. */ - || n == old_sbss_index || n == old_plt_index - ) + if (n >= old_bss_index && n < old_bss_index + n_bss_sections) { + /* The new bss section's size is zero, and its file offset + and virtual address should be off by NEW_DATA2_SIZE. */ /* NN should be `old_s?bss_index + 1' at this point. */ NEW_SECTION_H (nn).sh_offset = new_data2_offset + new_data2_size; NEW_SECTION_H (nn).sh_addr = new_data2_addr + new_data2_size; @@ -998,15 +976,6 @@ temacs: && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM) PATCH_INDEX (NEW_SECTION_H (nn).sh_info); - if (old_sbss_index != -1) - if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".sbss")) - { - NEW_SECTION_H (nn).sh_offset = - round_up (NEW_SECTION_H (nn).sh_offset, - NEW_SECTION_H (nn).sh_addralign); - NEW_SECTION_H (nn).sh_type = SHT_PROGBITS; - } - /* Now, start to copy the content of sections. */ if (NEW_SECTION_H (nn).sh_type == SHT_NULL || NEW_SECTION_H (nn).sh_type == SHT_NOBITS) @@ -1226,7 +1195,7 @@ temacs: nn = symp->st_shndx; if (nn > old_bss_index) nn--; - if (nn == old_bss_index) + if (nn >= old_bss_index && nn < old_bss_index + n_bss_sections) memset (new, 0, symp->st_size); else { -- 2.6.1 Andreas. -- Andreas Schwab, SUSE Labs, schwab <at> suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different."
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.