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

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