]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
unstrip: Handle debuginfo files with missing SHF_INFO_LINK section flags.
authorMark Wielaard <mjw@redhat.com>
Wed, 29 Jul 2015 15:51:27 +0000 (17:51 +0200)
committerMark Wielaard <mjw@redhat.com>
Mon, 3 Aug 2015 11:40:56 +0000 (13:40 +0200)
With GCC 5 there might be a .rela.plt section with SHF_INFO_LINK set.
Buggy binutils objdump might strip it from the section in the debug file.
Ignore such differences for relocation sections and put the flag back
if necessary.

Also improve the error message a little by only discarding the already
matched sections if there is an prelink undo section. Otherwise we will
report all sections as not matching if the file wasn't prelinked instead
of just the non-matching sections.

New testfiles generated by gcc5 and binutils objdump added.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
src/ChangeLog
src/unstrip.c
tests/ChangeLog
tests/Makefile.am
tests/run-unstrip-test3.sh [new file with mode: 0755]
tests/testfile-info-link.bz2 [new file with mode: 0755]
tests/testfile-info-link.debuginfo.bz2 [new file with mode: 0755]
tests/testfile-info-link.stripped.bz2 [new file with mode: 0755]

index 632330c9fb14e2517437fe64418ca1bd38dee2e5..a0c32fa247fb14d27d06a3ae009eef53f7bf4b0e 100644 (file)
@@ -1,3 +1,12 @@
+2015-07-29  Mark Wielaard  <mjw@redhat.com>
+
+       * unstrip.c (sections_flags_match): New function.
+       (sections_match): Use sections_flags_match.
+       (find_alloc_sections_prelink): Only clear matched sections if there
+       is an undo section.
+       (copy_elided_sections): Add SHF_INFO_LINK to shdr_mem.sh_flags if
+       necessary.
+
 2015-06-27  Pino Toscano  <toscano.pino@tiscali.it>
 
        * src/strings.c: Define MAP_POPULATE if not defined already.
index 4a8e5fa9cc0fed4a92db26a9298dde884e0cceaf..8833094607c514f36ab05829049677cfcf5e20a2 100644 (file)
@@ -867,12 +867,28 @@ compare_symbols_output (const void *a, const void *b)
 
 #undef CMP
 
+/* Return true if the flags of the sections match, ignoring the SHF_INFO_LINK
+   flag if the section contains relocation information.  */
+static bool
+sections_flags_match (Elf64_Xword sh_flags1, Elf64_Xword sh_flags2,
+                     Elf64_Word sh_type)
+{
+  if (sh_type == SHT_REL || sh_type == SHT_RELA)
+    {
+      sh_flags1 &= ~SHF_INFO_LINK;
+      sh_flags2 &= ~SHF_INFO_LINK;
+    }
+
+  return sh_flags1 == sh_flags2;
+}
+
 /* Return true iff the flags, size, and name match.  */
 static bool
 sections_match (const struct section *sections, size_t i,
                const GElf_Shdr *shdr, const char *name)
 {
-  return (sections[i].shdr.sh_flags == shdr->sh_flags
+  return (sections_flags_match (sections[i].shdr.sh_flags, shdr->sh_flags,
+                               sections[i].shdr.sh_type)
          && (sections[i].shdr.sh_size == shdr->sh_size
              || (sections[i].shdr.sh_size < shdr->sh_size
                  && section_can_shrink (&sections[i].shdr)))
@@ -930,10 +946,6 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
                             struct section *sections,
                             size_t nalloc, size_t nsections)
 {
-  /* Clear assignments that might have been bogus.  */
-  for (size_t i = 0; i < nalloc; ++i)
-    sections[i].outscn = NULL;
-
   Elf_Scn *undo = NULL;
   for (size_t i = nalloc; i < nsections; ++i)
     {
@@ -952,6 +964,10 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
   size_t undo_nalloc = 0;
   if (undo != NULL)
     {
+      /* Clear assignments that might have been bogus.  */
+      for (size_t i = 0; i < nalloc; ++i)
+       sections[i].outscn = NULL;
+
       Elf_Data *undodata = elf_rawdata (undo, NULL);
       ELF_CHECK (undodata != NULL,
                 _("cannot read '.gnu.prelink_undo' section: %s"));
@@ -1500,6 +1516,14 @@ more sections in stripped file than debug file -- arguments reversed?"));
        shdr_mem.sh_size = sec->shdr.sh_size;
        shdr_mem.sh_info = sec->shdr.sh_info;
        shdr_mem.sh_link = sec->shdr.sh_link;
+
+       /* Buggy binutils objdump might have stripped the SHF_INFO_LINK
+          put it back if necessary.  */
+       if ((sec->shdr.sh_type == SHT_REL || sec->shdr.sh_type == SHT_RELA)
+           && sec->shdr.sh_flags != shdr_mem.sh_flags
+           && (sec->shdr.sh_flags & SHF_INFO_LINK) != 0)
+         shdr_mem.sh_flags |= SHF_INFO_LINK;
+
        if (sec->shdr.sh_link != SHN_UNDEF)
          shdr_mem.sh_link = ndx_section[sec->shdr.sh_link - 1];
        if (shdr_mem.sh_flags & SHF_INFO_LINK)
index 90b9a0a1ca90530d32c7b69e977fd3b37f87542f..109a30568d4863306d704e316e88b9eeb785e5f7 100644 (file)
@@ -1,3 +1,13 @@
+2015-07-29  Mark Wielaard  <mjw@redhat.com>
+
+       * run-unstrip-test3.sh: New test.
+       * testfile-info-link.bz2: New file.
+       * testfile-info-link.debuginfo.bz2: Likewise.
+       * testfile-info-link.stripped.bz2: Likewise.
+       * Makefile.am (TESTS): Add run-unstrip-test3.sh.
+       (EXTRA_DIST): Add run-unstrip-test3.sh, testfile-info-link.bz2,
+       testfile-info-link.debuginfo.bz2, testfile-info-link.stripped.bz2.
+
 2015-06-27  Pino Toscano  <toscano.pino@tiscali.it>
 
        * tests/run-deleted.sh: Skip when detecting a not implemented
index 55241c7d18ac3075373fa3bb994a578069819215..62e7b7c484a47a5994d0c4aac7f9c1918daed742 100644 (file)
@@ -78,7 +78,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
        run-strip-test6.sh run-strip-test7.sh run-strip-test8.sh \
        run-strip-test9.sh run-strip-test10.sh \
        run-strip-groups.sh run-strip-reloc.sh \
-       run-unstrip-test.sh run-unstrip-test2.sh run-unstrip-M.sh \
+       run-unstrip-test.sh run-unstrip-test2.sh \
+       run-unstrip-test3.sh run-unstrip-M.sh \
        run-ecp-test.sh run-ecp-test2.sh run-alldts.sh \
        run-elflint-test.sh run-elflint-self.sh run-ranlib-test.sh \
        run-ranlib-test2.sh run-ranlib-test3.sh run-ranlib-test4.sh \
@@ -161,7 +162,10 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
             run-strip-test9.sh run-strip-test10.sh \
             run-strip-reloc.sh hello_i386.ko.bz2 hello_x86_64.ko.bz2 \
             hello_ppc64.ko.bz2 hello_s390.ko.bz2 hello_aarch64.ko.bz2 \
-            run-unstrip-test.sh run-unstrip-test2.sh run-unstrip-M.sh\
+            run-unstrip-test.sh run-unstrip-test2.sh \
+            testfile-info-link.bz2 testfile-info-link.debuginfo.bz2 \
+            testfile-info-link.stripped.bz2 run-unstrip-test3.sh \
+            run-unstrip-M.sh \
             run-elflint-self.sh run-ranlib-test.sh run-ranlib-test2.sh \
             run-ranlib-test3.sh run-ranlib-test4.sh \
             run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
diff --git a/tests/run-unstrip-test3.sh b/tests/run-unstrip-test3.sh
new file mode 100755 (executable)
index 0000000..5459e72
--- /dev/null
@@ -0,0 +1,17 @@
+# Buggy binutils objdump might strip SHF_INFO_LINK from relocation sections.
+# With gcc5 we might have a .rela.plt section with that flag set.
+#
+# int main() 
+# {
+#     return 0;
+# }
+#
+# gcc -o testfile-info-link -g testprog.c
+# objcopy --only-keep-debug testfile-info-link testfile-info-link.debuginfo
+# eu-strip --strip-debug -o testfile-info-link.stripped testfile-info-link
+
+original=testfile-info-link
+stripped=testfile-info-link.stripped
+debugfile=testfile-info-link.debuginfo
+
+. $srcdir/run-unstrip-test.sh
diff --git a/tests/testfile-info-link.bz2 b/tests/testfile-info-link.bz2
new file mode 100755 (executable)
index 0000000..073b761
Binary files /dev/null and b/tests/testfile-info-link.bz2 differ
diff --git a/tests/testfile-info-link.debuginfo.bz2 b/tests/testfile-info-link.debuginfo.bz2
new file mode 100755 (executable)
index 0000000..3225d19
Binary files /dev/null and b/tests/testfile-info-link.debuginfo.bz2 differ
diff --git a/tests/testfile-info-link.stripped.bz2 b/tests/testfile-info-link.stripped.bz2
new file mode 100755 (executable)
index 0000000..dcbc9a2
Binary files /dev/null and b/tests/testfile-info-link.stripped.bz2 differ