Mark Wielaard 73d540
commit f9fc50c3eced243c0648fb0fbfe2c9877c25e1e4
Mark Wielaard 73d540
Author: Mark Wielaard <mjw@redhat.com>
Mark Wielaard 73d540
Date:   Wed Jul 29 17:51:27 2015 +0200
Mark Wielaard 73d540
Mark Wielaard 73d540
    unstrip: Handle debuginfo files with missing SHF_INFO_LINK section flags.
Mark Wielaard 73d540
    
Mark Wielaard 73d540
    With GCC 5 there might be a .rela.plt section with SHF_INFO_LINK set.
Mark Wielaard 73d540
    Buggy binutils objdump might strip it from the section in the debug file.
Mark Wielaard 73d540
    Ignore such differences for relocation sections and put the flag back
Mark Wielaard 73d540
    if necessary.
Mark Wielaard 73d540
    
Mark Wielaard 73d540
    Also improve the error message a little by only discarding the already
Mark Wielaard 73d540
    matched sections if there is an prelink undo section. Otherwise we will
Mark Wielaard 73d540
    report all sections as not matching if the file wasn't prelinked instead
Mark Wielaard 73d540
    of just the non-matching sections.
Mark Wielaard 73d540
    
Mark Wielaard 73d540
    New testfiles generated by gcc5 and binutils objdump added.
Mark Wielaard 73d540
    
Mark Wielaard 73d540
    Signed-off-by: Mark Wielaard <mjw@redhat.com>
Mark Wielaard 73d540
Mark Wielaard 73d540
diff --git a/src/unstrip.c b/src/unstrip.c
Mark Wielaard 73d540
index 4a8e5fa..8833094 100644
Mark Wielaard 73d540
--- a/src/unstrip.c
Mark Wielaard 73d540
+++ b/src/unstrip.c
Mark Wielaard 73d540
@@ -867,12 +867,28 @@ compare_symbols_output (const void *a, const void *b)
Mark Wielaard 73d540
 
Mark Wielaard 73d540
 #undef CMP
Mark Wielaard 73d540
 
Mark Wielaard 73d540
+/* Return true if the flags of the sections match, ignoring the SHF_INFO_LINK
Mark Wielaard 73d540
+   flag if the section contains relocation information.  */
Mark Wielaard 73d540
+static bool
Mark Wielaard 73d540
+sections_flags_match (Elf64_Xword sh_flags1, Elf64_Xword sh_flags2,
Mark Wielaard 73d540
+		      Elf64_Word sh_type)
Mark Wielaard 73d540
+{
Mark Wielaard 73d540
+  if (sh_type == SHT_REL || sh_type == SHT_RELA)
Mark Wielaard 73d540
+    {
Mark Wielaard 73d540
+      sh_flags1 &= ~SHF_INFO_LINK;
Mark Wielaard 73d540
+      sh_flags2 &= ~SHF_INFO_LINK;
Mark Wielaard 73d540
+    }
Mark Wielaard 73d540
+
Mark Wielaard 73d540
+  return sh_flags1 == sh_flags2;
Mark Wielaard 73d540
+}
Mark Wielaard 73d540
+
Mark Wielaard 73d540
 /* Return true iff the flags, size, and name match.  */
Mark Wielaard 73d540
 static bool
Mark Wielaard 73d540
 sections_match (const struct section *sections, size_t i,
Mark Wielaard 73d540
 		const GElf_Shdr *shdr, const char *name)
Mark Wielaard 73d540
 {
Mark Wielaard 73d540
-  return (sections[i].shdr.sh_flags == shdr->sh_flags
Mark Wielaard 73d540
+  return (sections_flags_match (sections[i].shdr.sh_flags, shdr->sh_flags,
Mark Wielaard 73d540
+				sections[i].shdr.sh_type)
Mark Wielaard 73d540
 	  && (sections[i].shdr.sh_size == shdr->sh_size
Mark Wielaard 73d540
 	      || (sections[i].shdr.sh_size < shdr->sh_size
Mark Wielaard 73d540
 		  && section_can_shrink (&sections[i].shdr)))
Mark Wielaard 73d540
@@ -930,10 +946,6 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
Mark Wielaard 73d540
 			     struct section *sections,
Mark Wielaard 73d540
 			     size_t nalloc, size_t nsections)
Mark Wielaard 73d540
 {
Mark Wielaard 73d540
-  /* Clear assignments that might have been bogus.  */
Mark Wielaard 73d540
-  for (size_t i = 0; i < nalloc; ++i)
Mark Wielaard 73d540
-    sections[i].outscn = NULL;
Mark Wielaard 73d540
-
Mark Wielaard 73d540
   Elf_Scn *undo = NULL;
Mark Wielaard 73d540
   for (size_t i = nalloc; i < nsections; ++i)
Mark Wielaard 73d540
     {
Mark Wielaard 73d540
@@ -952,6 +964,10 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
Mark Wielaard 73d540
   size_t undo_nalloc = 0;
Mark Wielaard 73d540
   if (undo != NULL)
Mark Wielaard 73d540
     {
Mark Wielaard 73d540
+      /* Clear assignments that might have been bogus.  */
Mark Wielaard 73d540
+      for (size_t i = 0; i < nalloc; ++i)
Mark Wielaard 73d540
+	sections[i].outscn = NULL;
Mark Wielaard 73d540
+
Mark Wielaard 73d540
       Elf_Data *undodata = elf_rawdata (undo, NULL);
Mark Wielaard 73d540
       ELF_CHECK (undodata != NULL,
Mark Wielaard 73d540
 		 _("cannot read '.gnu.prelink_undo' section: %s"));
Mark Wielaard 73d540
@@ -1500,6 +1516,14 @@ more sections in stripped file than debug file -- arguments reversed?"));
Mark Wielaard 73d540
 	shdr_mem.sh_size = sec->shdr.sh_size;
Mark Wielaard 73d540
 	shdr_mem.sh_info = sec->shdr.sh_info;
Mark Wielaard 73d540
 	shdr_mem.sh_link = sec->shdr.sh_link;
Mark Wielaard 73d540
+
Mark Wielaard 73d540
+	/* Buggy binutils objdump might have stripped the SHF_INFO_LINK
Mark Wielaard 73d540
+	   put it back if necessary.  */
Mark Wielaard 73d540
+	if ((sec->shdr.sh_type == SHT_REL || sec->shdr.sh_type == SHT_RELA)
Mark Wielaard 73d540
+	    && sec->shdr.sh_flags != shdr_mem.sh_flags
Mark Wielaard 73d540
+	    && (sec->shdr.sh_flags & SHF_INFO_LINK) != 0)
Mark Wielaard 73d540
+	  shdr_mem.sh_flags |= SHF_INFO_LINK;
Mark Wielaard 73d540
+
Mark Wielaard 73d540
 	if (sec->shdr.sh_link != SHN_UNDEF)
Mark Wielaard 73d540
 	  shdr_mem.sh_link = ndx_section[sec->shdr.sh_link - 1];
Mark Wielaard 73d540
 	if (shdr_mem.sh_flags & SHF_INFO_LINK)