Blame SOURCES/emacs-0008-ELF-unexec-Drive-from-PT_LOAD-header-rather-than-sec.patch

1db854
From a2085a540975a1e6660dbc3b0c092789f002703e Mon Sep 17 00:00:00 2001
1db854
From: Alan Modra <amodra@gmail.com>
1db854
Date: Sun, 8 Nov 2015 09:29:00 -0800
1db854
Subject: [PATCH 08/11] ELF unexec: Drive from PT_LOAD header rather than
1db854
 sections
1db854
1db854
This rewrites bss handling in the ELF unexec code.  Finding bss
1db854
sections by name results in complicated code that
1db854
- does not account for all names of possible bss sections,
1db854
- assumes specific ordering of bss sections,
1db854
- can wrongly choose a SHT_NOBITS section not in the bss segment,
1db854
- incorrectly calculates bss size (no accounting for alignment gaps),
1db854
- assumes .data and .bss are in the same segment.
1db854
1db854
All of these problems and more are solved by finding the bss segment
1db854
in PT_LOAD headers, ie. the address range included in p_memsz but not
1db854
p_filesz of the last PT_LOAD header, then matching SHT_NOBITS sections
1db854
in that address range.
1db854
1db854
* unexelf.c: Delete old ppc comment.
1db854
(OLD_PROGRAM_H): Define.
1db854
(round_up): Delete.
1db854
(unexec): Don't search for bss style sections by name.  Instead,
1db854
use the last PT_LOAD header address range covered by p_memsz
1db854
but not p_filesz and match any SHT_NOBITS section in that
1db854
address range.  Simplify initialisation of section header vars.
1db854
Don't assume that section headers are above bss segment.  Move
1db854
copying of bss area out of section loop.  Align .data2 section
1db854
to 1, since it now covers the entire bss area.  For SHT_NOBITS
1db854
sections in the bss segment, leave sh_addr and sh_addralign
1db854
unchanged, but correct sh_offset.  Clear memory corresponding
1db854
to SHT_NOBITS .plt section.  Delete comment and hacks for
1db854
sections partly overlapping bss range now that the full range
1db854
is properly calculated.  Delete now dead .sbss code.
1db854
(Bug#20614)
1db854
---
1db854
 src/unexelf.c | 290 ++++++++++++++++------------------------------------------
1db854
 1 file changed, 77 insertions(+), 213 deletions(-)
1db854
1db854
diff --git a/src/unexelf.c b/src/unexelf.c
1db854
index 15a4cde..4e9c50d 100644
1db854
--- a/src/unexelf.c
1db854
+++ b/src/unexelf.c
1db854
@@ -535,29 +535,6 @@ verify ((! TYPE_SIGNED (ElfW (Half))
1db854
 /* Get the address of a particular section or program header entry,
1db854
  * accounting for the size of the entries.
1db854
  */
1db854
-/*
1db854
-   On PPC Reference Platform running Solaris 2.5.1
1db854
-   the plt section is also of type NOBI like the bss section.
1db854
-   (not really stored) and therefore sections after the bss
1db854
-   section start at the plt offset. The plt section is always
1db854
-   the one just before the bss section.
1db854
-   Thus, we modify the test from
1db854
-      if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
1db854
-   to
1db854
-      if (NEW_SECTION_H (nn).sh_offset >=
1db854
-               OLD_SECTION_H (old_bss_index-1).sh_offset)
1db854
-   This is just a hack. We should put the new data section
1db854
-   before the .plt section.
1db854
-   And we should not have this routine at all but use
1db854
-   the libelf library to read the old file and create the new
1db854
-   file.
1db854
-   The changed code is minimal and depends on prep set in m/prep.h
1db854
-   Erik Deumens
1db854
-   Quantum Theory Project
1db854
-   University of Florida
1db854
-   deumens@qtp.ufl.edu
1db854
-   Apr 23, 1996
1db854
-   */
1db854
 
1db854
 static void *
1db854
 entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
1db854
@@ -570,23 +547,14 @@ entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
1db854
   (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
1db854
 #define NEW_SECTION_H(n) \
1db854
   (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
1db854
+#define OLD_PROGRAM_H(n) \
1db854
+  (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
1db854
 #define NEW_PROGRAM_H(n) \
1db854
   (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize))
1db854
 
1db854
 #define PATCH_INDEX(n) ((n) += old_bss_index <= (n))
1db854
 typedef unsigned char byte;
1db854
 
1db854
-/* Round X up to a multiple of Y.  */
1db854
-
1db854
-static ElfW (Addr)
1db854
-round_up (ElfW (Addr) x, ElfW (Addr) y)
1db854
-{
1db854
-  ElfW (Addr) rem = x % y;
1db854
-  if (rem == 0)
1db854
-    return x;
1db854
-  return x - rem + y;
1db854
-}
1db854
-
1db854
 /* Return the index of the section named NAME.
1db854
    SECTION_NAMES, FILE_NAME and FILE_H give information
1db854
    about the file we are looking in.
1db854
@@ -650,16 +618,15 @@ unexec (const char *new_name, const char *old_name)
1db854
   /* Point to the section name table in the old file.  */
1db854
   char *old_section_names;
1db854
 
1db854
+  ElfW (Phdr) *old_bss_seg, *new_bss_seg;
1db854
   ElfW (Addr) old_bss_addr, new_bss_addr;
1db854
   ElfW (Word) old_bss_size, new_data2_size;
1db854
   ElfW (Off)  new_data2_offset;
1db854
   ElfW (Addr) new_data2_addr;
1db854
   ElfW (Off)  old_bss_offset;
1db854
-  ElfW (Word) new_data2_incr;
1db854
 
1db854
   ptrdiff_t n, nn;
1db854
-  ptrdiff_t old_bss_index, old_sbss_index, old_plt_index;
1db854
-  ptrdiff_t old_data_index, new_data2_index;
1db854
+  ptrdiff_t old_bss_index, old_data_index;
1db854
   struct stat stat_buf;
1db854
   off_t old_file_size;
1db854
 
1db854
@@ -703,54 +670,40 @@ unexec (const char *new_name, const char *old_name)
1db854
   old_section_names = (char *) old_base
1db854
     + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
1db854
 
1db854
-  /* Find the old .bss section.  Figure out parameters of the new
1db854
-     data2 and bss sections.  */
1db854
-
1db854
-  old_bss_index = find_section (".bss", old_section_names,
1db854
-				old_name, old_file_h, old_section_h, 0);
1db854
-
1db854
-  old_sbss_index = find_section (".sbss", old_section_names,
1db854
-				 old_name, old_file_h, old_section_h, 1);
1db854
-  if (old_sbss_index != -1)
1db854
-    if (OLD_SECTION_H (old_sbss_index).sh_type != SHT_NOBITS)
1db854
-      old_sbss_index = -1;
1db854
-
1db854
-  /* PowerPC64 has .plt in the BSS section.  */
1db854
-  old_plt_index = find_section (".plt", old_section_names,
1db854
-				old_name, old_file_h, old_section_h, 1);
1db854
-  if (old_plt_index != -1)
1db854
-    if (OLD_SECTION_H (old_plt_index).sh_type != SHT_NOBITS)
1db854
-      old_plt_index = -1;
1db854
-
1db854
-  if (old_sbss_index == -1 && old_plt_index == -1)
1db854
-    {
1db854
-      old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
1db854
-      old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
1db854
-      old_bss_offset = OLD_SECTION_H (old_bss_index).sh_offset;
1db854
-      new_data2_index = old_bss_index;
1db854
-    }
1db854
-  else if (old_plt_index != -1
1db854
-	   && (old_sbss_index == -1
1db854
-	       || (OLD_SECTION_H (old_sbss_index).sh_addr
1db854
-		   > OLD_SECTION_H (old_plt_index).sh_addr)))
1db854
+  /* Find the PT_LOAD header covering the highest address.  This
1db854
+     segment will be where bss sections are located, past p_filesz.  */
1db854
+  old_bss_seg = 0;
1db854
+  for (n = old_file_h->e_phnum; --n >= 0; )
1db854
     {
1db854
-      old_bss_addr = OLD_SECTION_H (old_plt_index).sh_addr;
1db854
-      old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
1db854
-	+ OLD_SECTION_H (old_plt_index).sh_size;
1db854
-      if (old_sbss_index != -1)
1db854
-	old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size;
1db854
-      old_bss_offset = OLD_SECTION_H (old_plt_index).sh_offset;
1db854
-      new_data2_index = old_plt_index;
1db854
+      ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
1db854
+      if (seg->p_type == PT_LOAD
1db854
+	  && (old_bss_seg == 0
1db854
+	      || seg->p_vaddr > old_bss_seg->p_vaddr))
1db854
+	old_bss_seg = seg;
1db854
     }
1db854
-  else
1db854
+
1db854
+  /* Note that old_bss_addr may be lower than the first bss section
1db854
+     address, since the section may need aligning.  */
1db854
+  old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
1db854
+  old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
1db854
+  old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
1db854
+
1db854
+  /* Find the first bss style section in the bss segment range.  */
1db854
+  old_bss_index = -1;
1db854
+  for (n = old_file_h->e_shnum; --n > 0; )
1db854
     {
1db854
-      old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
1db854
-      old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
1db854
-	+ OLD_SECTION_H (old_sbss_index).sh_size;
1db854
-      old_bss_offset = OLD_SECTION_H (old_sbss_index).sh_offset;
1db854
-      new_data2_index = old_sbss_index;
1db854
+      ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
1db854
+      if (shdr->sh_type == SHT_NOBITS
1db854
+	  && shdr->sh_addr >= old_bss_addr
1db854
+	  && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
1db854
+	  && (old_bss_index == -1
1db854
+	      || OLD_SECTION_H (old_bss_index).sh_addr > shdr->sh_addr))
1db854
+	old_bss_index = n;
1db854
     }
1db854
 
1db854
+  if (old_bss_index == -1)
1db854
+    fatal ("no bss section found");
1db854
+
1db854
   /* Find the old .data section.  Figure out parameters of
1db854
      the new data2 and bss sections.  */
1db854
 
1db854
@@ -761,13 +714,7 @@ unexec (const char *new_name, const char *old_name)
1db854
   new_bss_addr = (ElfW (Addr)) new_break;
1db854
   new_data2_addr = old_bss_addr;
1db854
   new_data2_size = new_bss_addr - old_bss_addr;
1db854
-  new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset
1db854
-    + (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
1db854
-  /* This is the amount by which the sections following the bss sections
1db854
-     must be shifted in the image.  It can differ from new_data2_size if
1db854
-     the end of the old .data section (and thus the offset of the .bss
1db854
-     section) was unaligned.  */
1db854
-  new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset);
1db854
+  new_data2_offset = old_bss_offset;
1db854
 
1db854
 #ifdef UNEXELF_DEBUG
1db854
   fprintf (stderr, "old_bss_index %td\n", old_bss_index);
1db854
@@ -778,7 +725,6 @@ unexec (const char *new_name, const char *old_name)
1db854
   DEBUG_LOG (new_data2_addr);
1db854
   DEBUG_LOG (new_data2_size);
1db854
   DEBUG_LOG (new_data2_offset);
1db854
-  DEBUG_LOG (new_data2_incr);
1db854
 #endif
1db854
 
1db854
   if (new_bss_addr < old_bss_addr + old_bss_size)
1db854
@@ -792,7 +738,7 @@ unexec (const char *new_name, const char *old_name)
1db854
   if (new_file < 0)
1db854
     fatal ("Can't creat (%s): %s", new_name, strerror (errno));
1db854
 
1db854
-  new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_incr;
1db854
+  new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_size;
1db854
 
1db854
   if (ftruncate (new_file, new_file_size))
1db854
     fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
1db854
@@ -811,15 +757,15 @@ unexec (const char *new_name, const char *old_name)
1db854
   /* Fix up file header.  We'll add one section.  Section header is
1db854
      further away now.  */
1db854
 
1db854
-  new_file_h->e_shoff += new_data2_incr;
1db854
+  if (new_file_h->e_shoff >= old_bss_offset)
1db854
+    new_file_h->e_shoff += new_data2_size;
1db854
   new_file_h->e_shnum += 1;
1db854
 
1db854
   /* Modify the e_shstrndx if necessary. */
1db854
   PATCH_INDEX (new_file_h->e_shstrndx);
1db854
 
1db854
-  new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
1db854
-  new_section_h = (ElfW (Shdr) *)
1db854
-    ((byte *) new_base + old_file_h->e_shoff + new_data2_incr);
1db854
+  new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
1db854
+  new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
1db854
 
1db854
   memcpy (new_program_h, old_program_h,
1db854
 	  old_file_h->e_phnum * old_file_h->e_phentsize);
1db854
@@ -831,65 +777,21 @@ unexec (const char *new_name, const char *old_name)
1db854
   fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
1db854
 #endif
1db854
 
1db854
-  /* Fix up a new program header.  Extend the writable data segment so
1db854
-     that the bss area is covered too. Find that segment by looking
1db854
-     for a segment that ends just before the .bss area.  Make sure
1db854
-     that no segments are above the new .data2.  Put a loop at the end
1db854
-     to adjust the offset and address of any segment that is above
1db854
-     data2, just in case we decide to allow this later.  */
1db854
+  /* Fix up program header.  Extend the writable data segment so
1db854
+     that the bss area is covered too.  */
1db854
 
1db854
-  for (n = new_file_h->e_phnum; --n >= 0; )
1db854
-    {
1db854
-      /* Compute maximum of all requirements for alignment of section.  */
1db854
-      ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align;
1db854
-      if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
1db854
-	alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
1db854
-
1db854
-#ifdef __sgi
1db854
-	  /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
1db854
-	     and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
1db854
-	     always get "Program segment above .bss" when dumping
1db854
-	     when the executable doesn't have an sbss section.  */
1db854
-      if (old_sbss_index != -1)
1db854
-#endif /* __sgi */
1db854
-      if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
1db854
-	  > (old_sbss_index == -1
1db854
-	     ? old_bss_addr
1db854
-	     : round_up (old_bss_addr, alignment)))
1db854
-	  fatal ("Program segment above .bss in %s", old_name);
1db854
-
1db854
-      if (NEW_PROGRAM_H (n).p_type == PT_LOAD
1db854
-	  && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
1db854
-			+ (NEW_PROGRAM_H (n)).p_filesz,
1db854
-			alignment)
1db854
-	      == round_up (old_bss_addr, alignment)))
1db854
-	break;
1db854
-    }
1db854
-  if (n < 0)
1db854
-    fatal ("Couldn't find segment next to .bss in %s", old_name);
1db854
-
1db854
-  /* Make sure that the size includes any padding before the old .bss
1db854
-     section.  */
1db854
-  NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr;
1db854
-  NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
1db854
-
1db854
-#if 0 /* Maybe allow section after data2 - does this ever happen? */
1db854
-  for (n = new_file_h->e_phnum; --n >= 0; )
1db854
-    {
1db854
-      if (NEW_PROGRAM_H (n).p_vaddr
1db854
-	  && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
1db854
-	NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
1db854
+  new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
1db854
+  new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
1db854
+  new_bss_seg->p_memsz = new_bss_seg->p_filesz;
1db854
 
1db854
-      if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
1db854
-	NEW_PROGRAM_H (n).p_offset += new_data2_incr;
1db854
-    }
1db854
-#endif
1db854
+  /* Copy over what we have in memory now for the bss area. */
1db854
+  memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr, new_data2_size);
1db854
 
1db854
   /* Fix up section headers based on new .data2 section.  Any section
1db854
      whose offset or virtual address is after the new .data2 section
1db854
-     gets its value adjusted.  .bss size becomes zero and new address
1db854
-     is set.  data2 section header gets added by copying the existing
1db854
-     .data header and modifying the offset, address and size.  */
1db854
+     gets its value adjusted.  .bss size becomes zero.  data2 section
1db854
+     header gets added by copying the existing .data header and
1db854
+     modifying the offset, address and size.  */
1db854
 
1db854
   /* Walk through all section headers, insert the new data2 section right
1db854
      before the new bss section. */
1db854
@@ -900,9 +802,7 @@ unexec (const char *new_name, const char *old_name)
1db854
       ElfW (Shdr) *new_shdr = &NEW_SECTION_H (nn);
1db854
 
1db854
       /* If it is (s)bss section, insert the new data2 section before it.  */
1db854
-      /* new_data2_index is the index of either old_sbss or old_bss, that was
1db854
-	 chosen as a section for new_data2.   */
1db854
-      if (n == new_data2_index)
1db854
+      if (n == old_bss_index)
1db854
 	{
1db854
 	  /* Steal the data section header for this data2 section. */
1db854
 	  memcpy (new_shdr, &OLD_SECTION_H (old_data_index),
1db854
@@ -911,68 +811,43 @@ unexec (const char *new_name, const char *old_name)
1db854
 	  new_shdr->sh_addr = new_data2_addr;
1db854
 	  new_shdr->sh_offset = new_data2_offset;
1db854
 	  new_shdr->sh_size = new_data2_size;
1db854
-	  /* Use the bss section's alignment. This will assure that the
1db854
-	     new data2 section always be placed in the same spot as the old
1db854
-	     bss section by any other application. */
1db854
-	  new_shdr->sh_addralign = old_shdr->sh_addralign;
1db854
-
1db854
-	  /* Now copy over what we have in the memory now. */
1db854
-	  memcpy (new_shdr->sh_offset + new_base,
1db854
-		  (caddr_t) old_shdr->sh_addr,
1db854
-		  new_data2_size);
1db854
+	  new_shdr->sh_addralign = 1;
1db854
 	  nn++;
1db854
 	  new_shdr++;
1db854
 	}
1db854
 
1db854
       memcpy (new_shdr, old_shdr, old_file_h->e_shentsize);
1db854
 
1db854
-      if (n == old_bss_index
1db854
-	  /* The new bss and sbss section's size is zero, and its file offset
1db854
-	     and virtual address should be off by NEW_DATA2_SIZE.  */
1db854
-	  || n == old_sbss_index || n == old_plt_index
1db854
-	  )
1db854
+      if (new_shdr->sh_type == SHT_NOBITS
1db854
+	  && new_shdr->sh_addr >= old_bss_addr
1db854
+	  && (new_shdr->sh_addr + new_shdr->sh_size
1db854
+	      <= old_bss_addr + old_bss_size))
1db854
 	{
1db854
-	  /* NN should be `old_s?bss_index + 1' at this point. */
1db854
-	  new_shdr->sh_offset = new_data2_offset + new_data2_size;
1db854
-	  new_shdr->sh_addr = new_data2_addr + new_data2_size;
1db854
-	  /* Let the new bss section address alignment be the same as the
1db854
-	     section address alignment followed the old bss section, so
1db854
-	     this section will be placed in exactly the same place. */
1db854
-	  new_shdr->sh_addralign = OLD_SECTION_H (nn).sh_addralign;
1db854
+	  /* SHT_NOBITS sections do not need a valid sh_offset, so it
1db854
+	     might be incorrect.  Write the correct value.  */
1db854
+	  new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
1db854
+				 + new_bss_seg->p_offset);
1db854
+
1db854
+	  /* If this is was a SHT_NOBITS .plt section, then it is
1db854
+	     probably a PowerPC PLT.  If it is PowerPC64 ELFv1 then
1db854
+	     glibc ld.so doesn't initialize the toc pointer word.  A
1db854
+	     non-zero toc pointer word can defeat Power7 thread safety
1db854
+	     during lazy update of a PLT entry.  This only matters if
1db854
+	     emacs becomes multi-threaded.  */
1db854
+	  if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
1db854
+	    memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
1db854
+
1db854
+	  /* Set the new bss and sbss section's size to zero, because
1db854
+	     we've already covered this address range by .data2.  */
1db854
 	  new_shdr->sh_size = 0;
1db854
 	}
1db854
       else
1db854
 	{
1db854
 	  /* Any section that was originally placed after the .bss
1db854
-	     section should now be off by NEW_DATA2_INCR.  If a
1db854
-	     section overlaps the .bss section, consider it to be
1db854
-	     placed after the .bss section.  Overlap can occur if the
1db854
-	     section just before .bss has less-strict alignment; this
1db854
-	     was observed between .symtab and .bss on Solaris 2.5.1
1db854
-	     (sparc) with GCC snapshot 960602.
1db854
+	     section should now be off by NEW_DATA2_SIZE.  */
1db854
 
1db854
-> dump -h temacs
1db854
-
1db854
-temacs:
1db854
-
1db854
-	   **** SECTION HEADER TABLE ****
1db854
-[No]	Type	Flags	Addr         Offset       Size        	Name
1db854
-	Link	Info	Adralgn      Entsize
1db854
-
1db854
-[22]	1	3	0x335150     0x315150     0x4          	.data.rel.local
1db854
-	0	0	0x4          0
1db854
-
1db854
-[23]	8	3	0x335158     0x315158     0x42720      	.bss
1db854
-	0	0	0x8          0
1db854
-
1db854
-[24]	2	0	0            0x315154     0x1c9d0      	.symtab
1db854
-	25	1709	0x4          0x10
1db854
-	  */
1db854
-
1db854
-	  if (new_shdr->sh_offset >= old_bss_offset
1db854
-	      || (new_shdr->sh_offset + new_shdr->sh_size
1db854
-		  > new_data2_offset))
1db854
-	    new_shdr->sh_offset += new_data2_incr;
1db854
+	  if (new_shdr->sh_offset >= old_bss_offset)
1db854
+	    new_shdr->sh_offset += new_data2_size;
1db854
 
1db854
 	  /* Any section that was originally placed after the section
1db854
 	     header table should now be off by the size of one section
1db854
@@ -992,23 +867,13 @@ temacs:
1db854
 	  && new_shdr->sh_type != SHT_DYNSYM)
1db854
 	PATCH_INDEX (new_shdr->sh_info);
1db854
 
1db854
-      if (old_sbss_index != -1)
1db854
-	if (!strcmp (old_section_names + new_shdr->sh_name, ".sbss"))
1db854
-	  {
1db854
-	    new_shdr->sh_offset =
1db854
-	      round_up (new_shdr->sh_offset,
1db854
-			new_shdr->sh_addralign);
1db854
-	    new_shdr->sh_type = SHT_PROGBITS;
1db854
-	  }
1db854
-
1db854
       /* Now, start to copy the content of sections.  */
1db854
       if (new_shdr->sh_type == SHT_NULL
1db854
 	  || new_shdr->sh_type == SHT_NOBITS)
1db854
 	continue;
1db854
 
1db854
-      /* Write out the sections. .data and .data1 (and data2, called
1db854
-	 ".data" in the strings table) get copied from the current process
1db854
-	 instead of the old file.  */
1db854
+      /* Some sections are copied from the current process instead of
1db854
+	 the old file.  */
1db854
       if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
1db854
 	  || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
1db854
 	  || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
1db854
@@ -1037,8 +902,7 @@ temacs:
1db854
 	  || !strcmp (old_section_names + new_shdr->sh_name, ".got")
1db854
 #endif
1db854
 	  || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
1db854
-	  || !strcmp (old_section_names + new_shdr->sh_name, ".data1")
1db854
-	  || !strcmp (old_section_names + new_shdr->sh_name, ".sbss"))
1db854
+	  || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
1db854
 	src = (caddr_t) old_shdr->sh_addr;
1db854
       else
1db854
 	src = old_base + old_shdr->sh_offset;
1db854
-- 
1db854
2.7.4
1db854