[PATCH] Remove the stripped group section from linker output

H.J. Lu hongjiu.lu@intel.com
Mon Feb 12 18:13:00 GMT 2018


GCC 7 and above generates .debug_macro section in COMDAT group with
-g3.  But ld fails to recognize that a group section shouldn't be in
output when all of its members are stripped.  Update ld to remove the
stripped group section from linker output when all members are removed
by moving the stripped group section logic from objcopy.c to bfd.c so
that "ld -r -S" behaves the same as "strip -g".

OK for master?

H.J.
--
bfd/

	PR ld/22836
	* bfd.c (bfd_stripped_group_section_p): New function.
	* elflink.c (bfd_elf_final_link): Remove the stripped group
	section from linker output.
	* bfd-in2.h: Regenerated.

binutils/

	PR ld/22836
	* objcopy.c (strip_group_signature_p): New function.
	(is_strip_section): Call bfd_stripped_group_section_p.

ld/

	PR ld/22836
	* testsuite/ld-elf/pr22836-1.s: New file.
	* testsuite/ld-elf/pr22836-1a.d: Likewise.
	* testsuite/ld-elf/pr22836-1b.d: Likewise.
---
 bfd/bfd-in2.h                    |  6 ++++
 bfd/bfd.c                        | 59 ++++++++++++++++++++++++++++++++++++++
 bfd/elflink.c                    |  6 ++++
 binutils/objcopy.c               | 62 +++++++++++++++++-----------------------
 ld/testsuite/ld-elf/pr22836-1.s  |  4 +++
 ld/testsuite/ld-elf/pr22836-1a.d | 15 ++++++++++
 ld/testsuite/ld-elf/pr22836-1b.d | 15 ++++++++++
 7 files changed, 132 insertions(+), 35 deletions(-)
 create mode 100644 ld/testsuite/ld-elf/pr22836-1.s
 create mode 100644 ld/testsuite/ld-elf/pr22836-1a.d
 create mode 100644 ld/testsuite/ld-elf/pr22836-1b.d

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 42991e7848..85d4a3e195 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -7282,6 +7282,12 @@ bfd_boolean bfd_convert_section_contents
    (bfd *ibfd, asection *isec, bfd *obfd,
     bfd_byte **ptr, bfd_size_type *ptr_size);
 
+bfd_boolean bfd_stripped_group_section_p
+   (bfd *abfd, asection *sec,
+    bfd_boolean relocatable_link,
+    bfd_boolean (*strip_group_section_p) (bfd *, asection *),
+    bfd_boolean (*strip_section_p) (bfd *, asection *));
+
 /* Extracted from archive.c.  */
 symindex bfd_get_next_mapent
    (bfd *abfd, symindex previous, carsym **sym);
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 985c825c69..9603868fee 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -2613,3 +2613,62 @@ bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd,
   *ptr_size = size;
   return TRUE;
 }
+
+/*
+FUNCTION
+	bfd_stripped_group_section_p
+
+SYNOPSIS
+	bfd_boolean bfd_stripped_group_section_p
+	  (bfd *abfd, asection *sec,
+	   bfd_boolean relocatable_link,
+	   bfd_boolean (*strip_group_section_p) (bfd *, asection *),
+	   bfd_boolean (*strip_section_p) (bfd *, asection *));
+
+DESCRIPTION
+	Return TRUE if the section @var{sec} in BFD @var{abfd} is a
+	group section and should be stripped.  The group section is
+	stripped when all members are removed.  For non-relocatable
+	link, when @var{relocatable_link} is FALSE, the group section
+	is stripped if @var{strip_group_section_p} returns TRUE and a
+	group member is removed if @var{strip_section_p} returns TRUE.
+*/
+
+bfd_boolean
+bfd_stripped_group_section_p
+  (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
+   bfd_boolean relocatable_link,
+   bfd_boolean (*strip_group_section_p) (bfd *, asection *),
+   bfd_boolean (*strip_section_p) (bfd *, asection *))
+{
+  if ((bfd_get_section_flags (abfd, sec) & SEC_GROUP) != 0)
+    {
+      asection *elt, *first;
+
+      /* PR binutils/3181
+	 If we are going to strip the group signature symbol, then
+	 strip the group section too.  */
+      if (!relocatable_link && strip_group_section_p (abfd, sec))
+	return TRUE;
+
+      /* Remove the group section if all members are removed.  */
+      first = elt = elf_next_in_group (sec);
+      while (elt != NULL)
+	{
+	  if (relocatable_link)
+	    {
+	      if (!discarded_section (elt))
+		return FALSE;
+	    }
+	  else if (!strip_section_p (abfd, elt))
+	    return FALSE;
+	  elt = elf_next_in_group (elt);
+	  if (elt == first)
+	    break;
+	}
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index d1eb82020c..5e85e25c92 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -11618,6 +11618,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 	  else
 	    o->flags |= SEC_EXCLUDE;
 	}
+      else if (bfd_stripped_group_section_p (abfd, o, TRUE, NULL, NULL))
+	{
+	  /* Remove the stripped group section from linker output.  */
+	  bfd_section_list_remove (abfd, o);
+	  abfd->section_count--;
+	}
     }
 
   /* Count up the number of relocations we will output for each output
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 8cdf27a87e..59f9d50b17 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -1330,48 +1330,40 @@ is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
   return FALSE;
 }
 
-/* See if a section is being removed.  */
+/* Return TRUE if the group signature should be stripped.  */
 
 static bfd_boolean
-is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
+strip_group_signature_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
 {
-  if (is_strip_section_1 (abfd, sec))
+  asymbol *gsym;
+  const char *gname;
+
+  /* PR binutils/3181
+     If we are going to strip the group signature symbol, then
+     strip the group section too.  */
+  gsym = group_signature (sec);
+  if (gsym != NULL)
+    gname = gsym->name;
+  else
+    gname = sec->name;
+  if ((strip_symbols == STRIP_ALL
+       && !is_specified_symbol (gname, keep_specific_htab))
+      || is_specified_symbol (gname, strip_specific_htab))
     return TRUE;
 
-  if ((bfd_get_section_flags (abfd, sec) & SEC_GROUP) != 0)
-    {
-      asymbol *gsym;
-      const char *gname;
-      asection *elt, *first;
-
-      /* PR binutils/3181
-	 If we are going to strip the group signature symbol, then
-	 strip the group section too.  */
-      gsym = group_signature (sec);
-      if (gsym != NULL)
-	gname = gsym->name;
-      else
-	gname = sec->name;
-      if ((strip_symbols == STRIP_ALL
-	   && !is_specified_symbol (gname, keep_specific_htab))
-	  || is_specified_symbol (gname, strip_specific_htab))
-	return TRUE;
-
-      /* Remove the group section if all members are removed.  */
-      first = elt = elf_next_in_group (sec);
-      while (elt != NULL)
-	{
-	  if (!is_strip_section_1 (abfd, elt))
-	    return FALSE;
-	  elt = elf_next_in_group (elt);
-	  if (elt == first)
-	    break;
-	}
+  return FALSE;
+}
 
-      return TRUE;
-    }
+/* See if a section is being removed.  */
 
-  return FALSE;
+static bfd_boolean
+is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
+{
+  if (is_strip_section_1 (abfd, sec))
+    return TRUE;
+  return bfd_stripped_group_section_p (abfd, sec, FALSE,
+				       strip_group_signature_p,
+				       is_strip_section_1);
 }
 
 static bfd_boolean
diff --git a/ld/testsuite/ld-elf/pr22836-1.s b/ld/testsuite/ld-elf/pr22836-1.s
new file mode 100644
index 0000000000..8be549ecca
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr22836-1.s
@@ -0,0 +1,4 @@
+	.section	.debug_macro,"G",%progbits,foo,comdat
+	.long	.LASF0
+.LASF0:
+	.string	"__STDC__ 1"
diff --git a/ld/testsuite/ld-elf/pr22836-1a.d b/ld/testsuite/ld-elf/pr22836-1a.d
new file mode 100644
index 0000000000..5f8461f48e
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr22836-1a.d
@@ -0,0 +1,15 @@
+#source: pr22836-1.s
+#ld: -r -s
+#readelf: -S --wide
+#notarget: alpha-*-* cr16-*-* crx-*-* d30v-*-* dlx-*-* i960-*-* pj*-*-*
+# Disabled on alpha because alpha has a different .set directive.
+# cr16 and crx use non-standard scripts with memory regions, which don't
+# play well with comdat group sections under ld -r.  Generic linker
+# targets don't support comdat group sections.
+
+#failif
+#...
+  \[[ 0-9]+\] \.debug_.* +.*
+#...
+COMDAT group section .*
+#...
diff --git a/ld/testsuite/ld-elf/pr22836-1b.d b/ld/testsuite/ld-elf/pr22836-1b.d
new file mode 100644
index 0000000000..20adc3a1f3
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr22836-1b.d
@@ -0,0 +1,15 @@
+#source: pr22836-1.s
+#ld: -r -S
+#readelf: -S --wide
+#notarget: alpha-*-* cr16-*-* crx-*-* d30v-*-* dlx-*-* i960-*-* pj*-*-*
+# Disabled on alpha because alpha has a different .set directive.
+# cr16 and crx use non-standard scripts with memory regions, which don't
+# play well with comdat group sections under ld -r.  Generic linker
+# targets don't support comdat group sections.
+
+#failif
+#...
+  \[[ 0-9]+\] \.debug_.* +.*
+#...
+COMDAT group section .*
+#...
-- 
2.14.3



More information about the Binutils mailing list