Subject: bug#20614: Segmentation fault when building on Power8 Little Endian

From: Petr Hracek <[email-masked]>
Date: Tue, 13 Oct 2015 09:30:14 +0200

On 10/10/2015 05:44 PM, Andreas Schwab wrote:
> 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 [email-masked] (Karsten Kuenne)
> -	     and [email-masked] (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
>   		{
Well, with this patch emacs failed again with message like:
Dumping under the name emacs
emacs: Program segment above .bss in 
/home/phracek/rpmbuild/BUILD/emacs-24.3/src/temacs
make[2]: *** [bootstrap-emacs] Error 1
make[2]: Leaving directory `/home/phracek/rpmbuild/BUILD/emacs-24.3/src'
make[1]: *** [src] Error 2

Well:
Header seems to be fine:
ELF Header:
   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
   Class:                             ELF64
   Data:                              2's complement, little endian
   Ident Version:                     1 (current)
   OS/ABI:                            UNIX - System V
   ABI Version:                       0
   Type:                              EXEC (Executable file)
   Machine:                           PowerPC 64-bit
   Version:                           1 (current)
   Entry point address:               0x100184f0
   Start of program headers:          64 (bytes into file)
   Start of section headers:          14281064 (bytes into file)
   Flags:                             0x2
   Size of this header:               64 (bytes)
   Size of program header entries:    56 (bytes)
   Number of program headers entries: 9
   Size of section header entries:    64 (bytes)
   Number of section headers entries: 34
   Section header string table index: 31

Section Headers:
[Nr] Name                 Type         Addr             Off Size     ES 
Flags Lk Inf Al
[ 0]                      NULL         0000000000000000 00000000 
00000000  0        0   0  0
[ 1] .interp              PROGBITS     0000000010000238 00000238 
00000011  0 A      0   0  1
[ 2] .note.ABI-tag        NOTE         000000001000024c 0000024c 
00000020  0 A      0   0  4
[ 3] .note.gnu.build-id   NOTE         000000001000026c 0000026c 
00000024  0 A      0   0  4
[ 4] .gnu.hash            GNU_HASH     0000000010000290 00000290 
000000dc  0 A      5   0  8
[ 5] .dynsym              DYNSYM       0000000010000370 00000370 
000063f0 24 A      6   1  8
[ 6] .dynstr              STRTAB       0000000010006760 00006760 
00004ae9  0 A      0   0  1
[ 7] .gnu.version         GNU_versym   000000001000b24a 0000b24a 
00000854  2 A      5   0  2
[ 8] .gnu.version_r       GNU_verneed  000000001000baa0 0000baa0 
00000160  0 A      6  10  8
[ 9] .rela.toc            RELA         000000001000bc00 0000bc00 
00000330 24 A      5   0  8
[10] .rela.plt            RELA         000000001000bf30 0000bf30 
000060d8 24 A      5  20  8
[11] .init                PROGBITS     0000000010012020 00012020 
0000004c  0 AX     0   0 32
[12] .text                PROGBITS     0000000010012080 00012080 
00236f60  0 AX     0   0 32
[13] .fini                PROGBITS     0000000010248fe0 00248fe0 
00000024  0 AX     0   0  4
[14] .rodata              PROGBITS     0000000010249008 00249008 
0001fde0  0 A      0   0  8
[15] .eh_frame_hdr        PROGBITS     0000000010268de8 00268de8 
000073c4  0 A      0   0  4
[16] .eh_frame            PROGBITS     00000000102701b0 002701b0 
0002e2d8  0 A      0   0  8
[17] .data.rel.ro         PROGBITS     00000000102af640 0029f640 
00000430  0 WA     0   0  8
[18] .dynamic             DYNAMIC      00000000102afa70 0029fa70 
00000440 16 WA     6   0  8
[19] .got                 PROGBITS     00000000102afeb0 0029feb0 
00000150  8 WA     0   0  8
[20] .plt                 NOBITS       00000000102b0000 002a0000 
00002058  8 WA     0   0  8
[21] .data                PROGBITS     00000000102b2058 002a2058 
002c6d36  0 WA     0   0  8
[22] .bss                 NOBITS       0000000010578d90 00568d8e 
00087740  0 WA     0   0 16
[23] .comment             PROGBITS     0000000000000000 00568d8e 
00000058  1 MS     0   0  1
[24] .debug_aranges       PROGBITS     0000000000000000 00568de6 
00001350  0        0   0  1
[25] .debug_info          PROGBITS     0000000000000000 0056a136 
003aea05  0        0   0  1
[26] .debug_abbrev        PROGBITS     0000000000000000 00918b3b 
00021af4  0        0   0  1
[27] .debug_line          PROGBITS     0000000000000000 0093a62f 
0007c2d9  0        0   0  1
[28] .debug_str           PROGBITS     0000000000000000 009b6908 
00047fb3  1 MS     0   0  1
[29] .debug_loc           PROGBITS     0000000000000000 009fe8bb 
00327db2  0        0   0  1
[30] .debug_ranges        PROGBITS     0000000000000000 00d2666d 
000781b0  0        0   0  1
[31] .shstrtab            STRTAB       0000000000000000 00d9e81d 
00000148  0        0   0  1
[32] .symtab              SYMTAB       0000000000000000 00d9f1e8 
00037ba8 24       33 5414  8
[33] .strtab              STRTAB       0000000000000000 00dd6d90 
0002e227  0        0   0  1

What debug information do you need?

-- 
Petr Hracek
Software Engineer
Developer Experience
Red Hat, Inc
Mob: +420777056169
email: [email-masked]