Bug 13233

Summary: --gc-sections discards .debug_types
Product: binutils Reporter: Jan Kratochvil <jan>
Component: ldAssignee: Alan Modra <amodra>
Status: RESOLVED FIXED    
Severity: normal CC: hjl.tools
Priority: P2    
Version: 2.24   
Target Milestone: ---   
Host: Target: x86_64-fedora16-linux-gnu
Build: Last reconfirmed:
Bug Depends on: 13195    
Bug Blocks:    

Description Jan Kratochvil 2011-09-28 18:40:32 UTC
echo 'class C{}c;int main(){}'|g++ -c -o 27.o -Wall -gdwarf-4 -fdebug-types-section -x c++ -;g++ -o 27 27.o -Wall -Wl,--gc-sections

.debug_info:
    <52>   DW_AT_type        : signature: 13f2b295a1b7fce5      

but there is no .debug_types.

gold works OK.
Comment 1 Jan Kratochvil 2011-09-28 18:41:44 UTC
Testing of this Bug is dependent on PR ld/13195 for --gc-sections.
Comment 2 H.J. Lu 2011-09-28 19:07:51 UTC
It is caused by

http://sourceware.org/ml/binutils/2011-06/msg00175.html
Comment 3 H.J. Lu 2011-09-28 19:16:32 UTC
Since .debug_types is in a comdat group section, it is discarded by

      /* Keep debug and special sections like .comment when they are
         not part of a group.  */
      for (isec = ibfd->sections; isec != NULL; isec = isec->next)
        if (elf_next_in_group (isec) == NULL
            && ((isec->flags & SEC_DEBUGGING) != 0
                || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0))
          isec->gc_mark = 1;
Comment 4 H.J. Lu 2011-09-28 19:22:38 UTC
This patch

---
diff --git a/bfd/elflink.c b/bfd/elflink.c
index a15ad27..42d2e97 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -11670,9 +11670,9 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
       /* Keep debug and special sections like .comment when they are
 	 not part of a group.  */
       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
-	if (elf_next_in_group (isec) == NULL
-	    && ((isec->flags & SEC_DEBUGGING) != 0
-		|| (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0))
+	if ((isec->flags & SEC_DEBUGGING) != 0
+	    || (elf_next_in_group (isec) == NULL
+		&& (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0))
 	  isec->gc_mark = 1;
     }
   return TRUE;
---

works for me.
Comment 5 H.J. Lu 2011-09-29 00:05:52 UTC
I don't see why debug and special sections shouldn't be kept when
they are part of a group:

diff --git a/bfd/elflink.c b/bfd/elflink.c
index a15ad27..6fed561 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -11667,12 +11667,10 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
       if (!some_kept)
   continue;
 
-      /* Keep debug and special sections like .comment when they are
-   not part of a group.  */
+      /* Keep debug and special sections like .comment.  */
       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
-  if (elf_next_in_group (isec) == NULL
-      && ((isec->flags & SEC_DEBUGGING) != 0
-     || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0))
+  if ((isec->flags & SEC_DEBUGGING) != 0
+      || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
     isec->gc_mark = 1;
     }
   return TRUE;
Comment 6 Alan Modra 2011-09-29 01:15:58 UTC
Huh, if .debug_types is now made part of a comdat group (when did that happen?), then are you not telling the linker that you want this section to be discarded according to the usual rules for groups?  Of course, the linker generally only marks groups as needed when seeing a reference via some relocation from another kept section.  Other references like the .debug_info one shown here are not seen.  You could call that a bug, but I certainly am not motivated to write the code to process debug sections for --gc-sections!

I'd say
a) It's a gcc bug to put .debug_types in a single member comdat group since it totally ignores current linker limitations regarding group processing.
b) HJ's patch is wrong as it disables a more reasonable use of group sections which would be to put all code, data, *and* debug info for a function into a group. I know there are problems with actually doing that..

It might be reasonable for the linker to keep single-member comdat groups containing just debug info.  Jan, does this work for you?

Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.420
diff -u -p -r1.420 elflink.c
--- bfd/elflink.c	16 Sep 2011 01:17:16 -0000	1.420
+++ bfd/elflink.c	29 Sep 2011 01:10:38 -0000
@@ -11667,9 +11667,10 @@ _bfd_elf_gc_mark_extra_sections (struct 
 	continue;
 
       /* Keep debug and special sections like .comment when they are
-	 not part of a group.  */
+	 not part of a group, or when we have single-member groups.  */
       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
-	if (elf_next_in_group (isec) == NULL
+	if ((elf_next_in_group (isec) == NULL
+	     || elf_next_in_group (isec) == isec)
 	    && ((isec->flags & SEC_DEBUGGING) != 0
 		|| (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0))
 	  isec->gc_mark = 1;
Comment 7 Jan Kratochvil 2011-09-29 04:43:26 UTC
(In reply to comment #6)
> a) It's a gcc bug to put .debug_types in a single member comdat group since it
> totally ignores current linker limitations regarding group processing.

OK, I agree:
COMDAT group section [    1] `.group' [wt.13f2b295a1b7fce5] contains 1 sections:
   [Index]    Name
   [    5]   .debug_types


> It might be reasonable for the linker to keep single-member comdat groups
> containing just debug info.  Jan, does this work for you?

It fixes the problem for me, thanks.
Comment 8 Sourceware Commits 2011-09-29 05:40:31 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	amodra@sourceware.org	2011-09-29 05:40:22

Modified files:
	bfd            : ChangeLog elflink.c 

Log message:
	PR ld/13233
	* elflink.c (_bfd_elf_gc_mark_extra_sections): Mark single member
	debug and special section groups.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.5475&r2=1.5476
http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elflink.c.diff?cvsroot=src&r1=1.421&r2=1.422
Comment 9 Sourceware Commits 2011-09-29 05:40:52 UTC
CVSROOT:	/cvs/src
Module name:	src
Branch: 	binutils-2_22-branch
Changes by:	amodra@sourceware.org	2011-09-29 05:40:45

Modified files:
	bfd            : ChangeLog elflink.c 

Log message:
	PR ld/13233
	* elflink.c (_bfd_elf_gc_mark_extra_sections): Mark single member
	debug and special section groups.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&only_with_tag=binutils-2_22-branch&r1=1.5473.2.1&r2=1.5473.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elflink.c.diff?cvsroot=src&only_with_tag=binutils-2_22-branch&r1=1.420&r2=1.420.2.1
Comment 10 Alan Modra 2011-09-29 06:43:19 UTC
patch applied