bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


From: Andreas Schwab
Subject: bug#20614: Segmentation fault when building on Power8 Little Endian
Date: Sat, 10 Oct 2015 17:44:24 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux)

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@x4u2.desy.de (Karsten Kuenne)
-            and oliva@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@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."





reply via email to

[Prev in Thread] Current Thread [Next in Thread]