Mark debug sections referenced by kept debug sections
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 17 May 2017 14:57:15 +0000 (07:57 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 17 May 2017 14:57:26 +0000 (07:57 -0700)
If a debug section is referenced by a kept debug section, it should
also be kept.

Some targets, like mips, keep input files when there are some special
sections, like .gnu.attributes, even if input file is unused otherwise.
In this case, all debug sections are kept.  The new test will fail on
such targets.  We can either fix those targets or XFAIL the test.

bfd/

PR ld/20882
* elflink.c (elf_gc_mark_debug_section): New function.
(_bfd_elf_gc_mark_extra_sections): Mark any debug sections
referenced by kept debug sections.

ld/

PR ld/20882
* testsuite/ld-gc/gc.exp: Run pr20882.
* testsuite/ld-gc/pr20882.d: New file.
* testsuite/ld-gc/pr20882a.s: Likewise.
* testsuite/ld-gc/pr20882b.s: Likewise.
* testsuite/ld-gc/pr20882c.s: Likewise.

bfd/ChangeLog
bfd/elflink.c
ld/ChangeLog
ld/testsuite/ld-gc/gc.exp
ld/testsuite/ld-gc/pr20882.d [new file with mode: 0644]
ld/testsuite/ld-gc/pr20882a.s [new file with mode: 0644]
ld/testsuite/ld-gc/pr20882b.s [new file with mode: 0644]
ld/testsuite/ld-gc/pr20882c.s [new file with mode: 0644]

index 532ba0c65c9ab2cf9b5382aee70276fc1a034e37..31b398216c60dab6a771f30d7202e723ffda918a 100644 (file)
@@ -1,3 +1,10 @@
+2017-05-17  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/20882
+       * elflink.c (elf_gc_mark_debug_section): New function.
+       (_bfd_elf_gc_mark_extra_sections): Mark any debug sections
+       referenced by kept debug sections.
+
 2017-05-16  Alan Modra  <amodra@gmail.com>
 
        * elf-m10300.c: Rename occurrences of non_ir_ref.
index 60e0a322943ffbd64e21ae7e8faa3e157cba1773..bc1042839f79b6e07229378c91471e72cc66d1a6 100644 (file)
@@ -12669,6 +12669,24 @@ _bfd_elf_gc_mark_hook (asection *sec,
   return NULL;
 }
 
+/* Return the global debug definition section.  */
+
+static asection *
+elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
+                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                          Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
+                          struct elf_link_hash_entry *h,
+                          Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
+{
+  if (h != NULL
+      && (h->root.type == bfd_link_hash_defined
+         || h->root.type == bfd_link_hash_defweak)
+      && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
+    return h->root.u.def.section;
+
+  return NULL;
+}
+
 /* For undefined __start_<name> and __stop_<name> symbols, return the
    first input section matching <name>.  Return NULL otherwise.  */
 
@@ -12930,6 +12948,7 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
       asection *isec;
       bfd_boolean some_kept;
       bfd_boolean debug_frag_seen;
+      bfd_boolean has_kept_debug_info;
 
       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
        continue;
@@ -12937,7 +12956,7 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
       /* Ensure all linker created sections are kept,
         see if any other section is already marked,
         and note if we have any fragmented debug sections.  */
-      debug_frag_seen = some_kept = FALSE;
+      debug_frag_seen = some_kept = has_kept_debug_info = FALSE;
       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
        {
          if ((isec->flags & SEC_LINKER_CREATED) != 0)
@@ -12967,45 +12986,52 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
                    || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
                   && elf_next_in_group (isec) == NULL)
            isec->gc_mark = 1;
+         if (isec->gc_mark && (isec->flags & SEC_DEBUGGING) != 0)
+           has_kept_debug_info = TRUE;
        }
 
-      if (! debug_frag_seen)
-       continue;
-
       /* Look for CODE sections which are going to be discarded,
         and find and discard any fragmented debug sections which
         are associated with that code section.  */
-      for (isec = ibfd->sections; isec != NULL; isec = isec->next)
-       if ((isec->flags & SEC_CODE) != 0
-           && isec->gc_mark == 0)
-         {
-           unsigned int ilen;
-           asection *dsec;
+      if (debug_frag_seen)
+       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+         if ((isec->flags & SEC_CODE) != 0
+             && isec->gc_mark == 0)
+           {
+             unsigned int ilen;
+             asection *dsec;
 
-           ilen = strlen (isec->name);
+             ilen = strlen (isec->name);
 
-           /* Association is determined by the name of the debug section
-              containing the name of the code section as a suffix.  For
-              example .debug_line.text.foo is a debug section associated
-              with .text.foo.  */
-           for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
-             {
-               unsigned int dlen;
+             /* Association is determined by the name of the debug
+                section containing the name of the code section as
+                a suffix.  For example .debug_line.text.foo is a
+                debug section associated with .text.foo.  */
+             for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
+               {
+                 unsigned int dlen;
 
-               if (dsec->gc_mark == 0
-                   || (dsec->flags & SEC_DEBUGGING) == 0)
-                 continue;
+                 if (dsec->gc_mark == 0
+                     || (dsec->flags & SEC_DEBUGGING) == 0)
+                   continue;
 
-               dlen = strlen (dsec->name);
+                 dlen = strlen (dsec->name);
 
-               if (dlen > ilen
-                   && strncmp (dsec->name + (dlen - ilen),
-                               isec->name, ilen) == 0)
-                 {
+                 if (dlen > ilen
+                     && strncmp (dsec->name + (dlen - ilen),
+                                 isec->name, ilen) == 0)
                    dsec->gc_mark = 0;
-                 }
-             }
+               }
          }
+
+      /* Mark debug sections referenced by kept debug sections.  */
+      if (has_kept_debug_info)
+       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+         if (isec->gc_mark
+             && (isec->flags & SEC_DEBUGGING) != 0)
+           if (!_bfd_elf_gc_mark (info, isec,
+                                  elf_gc_mark_debug_section))
+             return FALSE;
     }
   return TRUE;
 }
index 2034a1a690e3f7af2cde8ebbc414560bd0bc7aed..b71bc16273cc78a69edd380929b131c6fec6d8ad 100644 (file)
@@ -1,3 +1,12 @@
+2017-05-17  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/20882
+       * testsuite/ld-gc/gc.exp: Run pr20882.
+       * testsuite/ld-gc/pr20882.d: New file.
+       * testsuite/ld-gc/pr20882a.s: Likewise.
+       * testsuite/ld-gc/pr20882b.s: Likewise.
+       * testsuite/ld-gc/pr20882c.s: Likewise.
+
 2017-05-16  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/21481
index ba4f70b6228f40cf321eefeae6384816d90139d1..ba5c46b64f82f3752c8e116b9a69e2ddcdd9dda8 100644 (file)
@@ -104,6 +104,7 @@ run_dump_test "start"
 run_dump_test "pr19167"
 if { [is_elf_format] } then {
     run_dump_test "all-debug-sections"
+    run_dump_test "pr20882"
 }
 
 if { [is_elf_format] && [check_shared_lib_support] } then {
diff --git a/ld/testsuite/ld-gc/pr20882.d b/ld/testsuite/ld-gc/pr20882.d
new file mode 100644 (file)
index 0000000..55fa141
--- /dev/null
@@ -0,0 +1,10 @@
+#name: --gc-sections with relocations in debug section
+#source: pr20882a.s
+#source: pr20882b.s
+#source: pr20882c.s
+#as: -gdwarf-sections
+#ld: --gc-sections -e main
+#readelf: -x .debug_info
+
+#...
+ +0x0+ [0-9a-f ]+ 28 +.+\(
diff --git a/ld/testsuite/ld-gc/pr20882a.s b/ld/testsuite/ld-gc/pr20882a.s
new file mode 100644 (file)
index 0000000..3348ba9
--- /dev/null
@@ -0,0 +1,11 @@
+       .text
+       .globl  main
+       .type   main, %function
+main:
+       .byte 0
+
+       .section .debug_info,"",%progbits
+       .dc.a  t.c.4903c230+2
+
+       .section .debug_line,"",%progbits
+       .byte 0
diff --git a/ld/testsuite/ld-gc/pr20882b.s b/ld/testsuite/ld-gc/pr20882b.s
new file mode 100644 (file)
index 0000000..fed521c
--- /dev/null
@@ -0,0 +1,8 @@
+       .section .debug_info,"",%progbits
+       .hidden t.c.4903c230
+       .globl t.c.4903c230
+t.c.4903c230:
+       .byte 0x28
+
+       .section .debug_line,"",%progbits
+       .byte 0
diff --git a/ld/testsuite/ld-gc/pr20882c.s b/ld/testsuite/ld-gc/pr20882c.s
new file mode 100644 (file)
index 0000000..a77edad
--- /dev/null
@@ -0,0 +1,8 @@
+       .section .debug_info,"",%progbits
+       .hidden t.c.4903c231
+       .globl t.c.4903c231
+t.c.4903c231:
+       .byte   0x29
+
+       .section .debug_line,"",%progbits
+       .byte 0