Blob Blame History Raw
From 14e5f5be6a45f6d238a47b117d9dc9e3eb36a380 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sun, 8 Nov 2015 09:28:59 -0800
Subject: [PATCH 04/11] ELF unexec: Merge Alpha and MIPS COFF debug handling

* unexelf.c (unexec): Merge Alpha and MIPS COFF debug handling.
Don't find .mdebug section index, find the section in the loop.
Allow for unlikely possibility that .mdebug is located at sh_offset
before bss segment, by calculating move from difference in
sh_offset rather than just assuming new_data2_size.  Simplify
cbLineOffset handling.
---
 src/unexelf.c | 96 ++++++++++++++++++-----------------------------------------
 1 file changed, 29 insertions(+), 67 deletions(-)

diff --git a/src/unexelf.c b/src/unexelf.c
index d6c6648..0065491 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -660,9 +660,6 @@ unexec (const char *new_name, const char *old_name)
   ptrdiff_t n, nn;
   ptrdiff_t old_bss_index, old_sbss_index, old_plt_index;
   ptrdiff_t old_data_index, new_data2_index;
-#if defined _SYSTYPE_SYSV || defined __sgi
-  ptrdiff_t old_mdebug_index;
-#endif
   struct stat stat_buf;
   off_t old_file_size;
 
@@ -706,13 +703,6 @@ unexec (const char *new_name, const char *old_name)
   old_section_names = (char *) old_base
     + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
 
-  /* Find the mdebug section, if any.  */
-
-#if defined _SYSTYPE_SYSV || defined __sgi
-  old_mdebug_index = find_section (".mdebug", old_section_names,
-				   old_name, old_file_h, old_section_h, 1);
-#endif
-
   /* Find the old .bss section.  Figure out parameters of the new
      data2 and bss sections.  */
 
@@ -1055,51 +1045,31 @@ temacs:
 
       memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
 
-#if defined __alpha__ && !defined __OpenBSD__
-      /* Update Alpha COFF symbol table: */
-      if (strcmp (old_section_names + old_shdr->sh_name, ".mdebug") == 0)
-	{
-	  pHDRR symhdr = (pHDRR) (new_shdr->sh_offset + new_base);
-
-	  symhdr->cbLineOffset += new_data2_size;
-	  symhdr->cbDnOffset += new_data2_size;
-	  symhdr->cbPdOffset += new_data2_size;
-	  symhdr->cbSymOffset += new_data2_size;
-	  symhdr->cbOptOffset += new_data2_size;
-	  symhdr->cbAuxOffset += new_data2_size;
-	  symhdr->cbSsOffset += new_data2_size;
-	  symhdr->cbSsExtOffset += new_data2_size;
-	  symhdr->cbFdOffset += new_data2_size;
-	  symhdr->cbRfdOffset += new_data2_size;
-	  symhdr->cbExtOffset += new_data2_size;
-	}
-#endif /* __alpha__ && !__OpenBSD__ */
-
-#if defined (_SYSTYPE_SYSV)
-      if (new_shdr->sh_type == SHT_MIPS_DEBUG
-	  && old_mdebug_index != -1)
+#if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
+      /* Update Alpha and MIPS COFF debug symbol table.  */
+      if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
+	  && new_shdr->sh_offset - old_shdr->sh_offset != 0
+#if defined _SYSTYPE_SYSV
+	  && new_shdr->sh_type == SHT_MIPS_DEBUG
+#endif
+	  )
 	{
-	  ptrdiff_t new_offset = new_shdr->sh_offset;
-	  ptrdiff_t old_offset = OLD_SECTION_H (old_mdebug_index).sh_offset;
-	  ptrdiff_t diff = new_offset - old_offset;
+	  ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
 	  HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
 
-	  if (diff)
-	    {
-	      phdr->cbLineOffset += diff;
-	      phdr->cbDnOffset   += diff;
-	      phdr->cbPdOffset   += diff;
-	      phdr->cbSymOffset  += diff;
-	      phdr->cbOptOffset  += diff;
-	      phdr->cbAuxOffset  += diff;
-	      phdr->cbSsOffset   += diff;
-	      phdr->cbSsExtOffset += diff;
-	      phdr->cbFdOffset   += diff;
-	      phdr->cbRfdOffset  += diff;
-	      phdr->cbExtOffset  += diff;
-	    }
+	  phdr->cbLineOffset += diff;
+	  phdr->cbDnOffset += diff;
+	  phdr->cbPdOffset += diff;
+	  phdr->cbSymOffset += diff;
+	  phdr->cbOptOffset += diff;
+	  phdr->cbAuxOffset += diff;
+	  phdr->cbSsOffset += diff;
+	  phdr->cbSsExtOffset += diff;
+	  phdr->cbFdOffset += diff;
+	  phdr->cbRfdOffset += diff;
+	  phdr->cbExtOffset += diff;
 	}
-#endif /* _SYSTYPE_SYSV */
+#endif /* __alpha__ || _SYSTYPE_SYSV */
 
 #if __sgi
       /* Adjust  the HDRR offsets in .mdebug and copy the
@@ -1110,7 +1080,8 @@ temacs:
 	 the ld bug that gets the line table in a hole in the
 	 elf file rather than in the .mdebug section proper.
 	 David Anderson. davea@sgi.com  Jan 16,1994.  */
-      if (n == old_mdebug_index)
+      if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
+	  && new_shdr->sh_offset - old_shdr->sh_offset != 0)
 	{
 #define MDEBUGADJUST(__ct,__fileaddr)		\
   if (n_phdrr->__ct > 0)			\
@@ -1120,7 +1091,7 @@ temacs:
 
 	  HDRR *o_phdrr = (HDRR *) ((byte *) old_base + old_shdr->sh_offset);
 	  HDRR *n_phdrr = (HDRR *) ((byte *) new_base + new_shdr->sh_offset);
-	  unsigned movement = new_data2_size;
+	  ptrdiff_t movement = new_shdr->sh_offset - old_shdr->sh_offset;
 
 	  MDEBUGADJUST (idnMax, cbDnOffset);
 	  MDEBUGADJUST (ipdMax, cbPdOffset);
@@ -1136,22 +1107,13 @@ temacs:
 	     requires special handling.  */
 	  if (n_phdrr->cbLine > 0)
 	    {
+	      n_phdrr->cbLineOffset += movement;
+
 	      if (o_phdrr->cbLineOffset > (old_shdr->sh_offset
 					   + old_shdr->sh_size))
-		{
-		  /* line data is in a hole in elf. do special copy and adjust
-		     for this ld mistake.
-		     */
-		  n_phdrr->cbLineOffset += movement;
-
-		  memcpy (n_phdrr->cbLineOffset + new_base,
-			  o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
-		}
-	      else
-		{
-		  /* somehow line data is in .mdebug as it is supposed to be.  */
-		  MDEBUGADJUST (cbLine, cbLineOffset);
-		}
+		/* If not covered by section, it hasn't yet been copied.  */
+		memcpy (n_phdrr->cbLineOffset + new_base,
+			o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
 	    }
 	}
 #endif /* __sgi */
-- 
2.7.4