On Tue, Feb 16, 2021 at 8:45 AM Jakub Jelinek <ja...@redhat.com> wrote:
>
> On Mon, Feb 15, 2021 at 02:35:07PM -0800, H.J. Lu via Gcc-patches wrote:
> > When building Linux kernel, ld in bninutils 2.36 with GCC 11 generates
> > thousands of
> >
> > ld: warning: orphan section `.data.event_initcall_finish' from 
> > `init/main.o' being placed in section `.data.event_initcall_finish'
> > ld: warning: orphan section `.data.event_initcall_start' from `init/main.o' 
> > being placed in section `.data.event_initcall_start'
> > ld: warning: orphan section `.data.event_initcall_level' from `init/main.o' 
> > being placed in section `.data.event_initcall_level'
> >
> > Since these sections are marked with SHF_GNU_RETAIN, they are placed in
> > separate sections.  They become orphan sections since they aren't expected
> > in the Linux kernel linker script. But orphan sections normally don't work
> > well with the Linux kernel linker script and the resulting kernel crashed.
> >
> > Add -fgnu-retain to disable SHF_GNU_RETAIN for Linux kernel build with
> > -fno-gnu-retain.
>
> I'd say this shows that the changing of meaning of "used" attribute wasn't
> really a good idea, the Linux kernel certainly won't be the only problem
> and people use "used" attribute for many reasons and don't necessarily want
> the different sections or different behavior of those sections if they use
> it.
>
> So, can't we instead:
> 1) restore the old behavior of "used" by default
> 2) add "retain" attribute that implies the SHF_GNU_RETAIN stuff and fails
>    if the configured assembler/linker doesn't support those
> 3) add a non-default option through which one could opt in for "used"
>    attribute to imply retain attribute too for projects that want that?
>
>         Jakub
>

Here is the updated patch to #1 and #3.  I will leave #2 to Jozef.

-- 
H.J.
From 1775ec951577325871b624d57a3341a983260cac Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.to...@gmail.com>
Date: Mon, 15 Feb 2021 11:31:12 -0800
Subject: [PATCH v2] Add -fgnu-retain to place used symbols in SHF_GNU_RETAIN
 section

When building Linux kernel, ld in bninutils 2.36 with GCC 11 generates
thousands of

ld: warning: orphan section `.data.event_initcall_finish' from `init/main.o' being placed in section `.data.event_initcall_finish'
ld: warning: orphan section `.data.event_initcall_start' from `init/main.o' being placed in section `.data.event_initcall_start'
ld: warning: orphan section `.data.event_initcall_level' from `init/main.o' being placed in section `.data.event_initcall_level'

Since these sections are marked with SHF_GNU_RETAIN, they are placed in
separate sections.  They become orphan sections since they aren't expected
in the Linux kernel linker script. But orphan sections normally don't work
well with the Linux kernel linker script and the resulting kernel crashed.

Add -fgnu-retain to place used symbols in SHF_GNU_RETAIN section and
issue a warning if SHF_GNU_RETAIN is not supported.

gcc/

	PR target/99113
	* common.opt: Add -fgnu-retain.
	* toplev.c (process_options): Issue a warning for -fgnu-retain
	without SUPPORTS_SHF_GNU_RETAIN.
	* varasm.c (get_section): Replace SUPPORTS_SHF_GNU_RETAIN with
	flag_gnu_retain.
	(resolve_unique_section): Likewise.
	(get_variable_section): Likewise.
	(switch_to_section): Likewise.
	* doc/invoke.texi: Document -fgnu-retain/-fno-gnu-retain.

gcc/testsuite/

	* c-c++-common/attr-used.c: Pass -fgnu-retain if supported.
	* c-c++-common/attr-used-2.c: Likewise.
	* c-c++-common/attr-used-3.c: Likewise.
	* c-c++-common/attr-used-4.c: Likewise.
	* c-c++-common/attr-used-5.c: Likewise.
	* c-c++-common/attr-used-6.c: Likewise.
	* c-c++-common/attr-used-7.c: Likewise.
	* c-c++-common/attr-used-8.c: Likewise.
	* c-c++-common/attr-used-9.c: Likewise.
	* gcc.c-torture/compile/attr-used-retain-1.c: Pass -fgnu-retain.
	* gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
	* c-c++-common/pr99113.c: New test.
---
 gcc/common.opt                                           | 4 ++++
 gcc/doc/invoke.texi                                      | 5 +++++
 gcc/testsuite/c-c++-common/attr-used-2.c                 | 1 +
 gcc/testsuite/c-c++-common/attr-used-3.c                 | 1 +
 gcc/testsuite/c-c++-common/attr-used-4.c                 | 1 +
 gcc/testsuite/c-c++-common/attr-used-5.c                 | 1 +
 gcc/testsuite/c-c++-common/attr-used-6.c                 | 1 +
 gcc/testsuite/c-c++-common/attr-used-7.c                 | 1 +
 gcc/testsuite/c-c++-common/attr-used-8.c                 | 1 +
 gcc/testsuite/c-c++-common/attr-used-9.c                 | 1 +
 gcc/testsuite/c-c++-common/attr-used.c                   | 1 +
 gcc/testsuite/c-c++-common/pr99113.c                     | 7 +++++++
 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c | 1 +
 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c | 2 +-
 gcc/toplev.c                                             | 7 +++++++
 gcc/varasm.c                                             | 8 ++++----
 16 files changed, 38 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/pr99113.c

diff --git a/gcc/common.opt b/gcc/common.opt
index c75dd36843e..47c905a47c5 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1666,6 +1666,10 @@ floop-unroll-and-jam
 Common Var(flag_unroll_jam) Optimization
 Perform unroll-and-jam on loops.
 
+fgnu-retain
+Common Var(flag_gnu_retain)
+Use SHF_GNU_RETAIN on used symbols if supported by the assembler and the linker.
+
 fgnu-tm
 Common Var(flag_tm)
 Enable support for GNU transactional memory.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e8baa545eee..092817b0e9a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -16168,6 +16168,11 @@ DSOs; if your program relies on reinitialization of a DSO via
 @code{dlclose} and @code{dlopen}, you can use
 @option{-fno-gnu-unique}.
 
+@item -fgnu-retain
+@opindex fgnu-retain
+On systems with recent GNU assembler and linker, the compiler places
+used symbols in separate SHF_GNU_RETAIN sections.
+
 @item -fpcc-struct-return
 @opindex fpcc-struct-return
 Return ``short'' @code{struct} and @code{union} values in memory like
diff --git a/gcc/testsuite/c-c++-common/attr-used-2.c b/gcc/testsuite/c-c++-common/attr-used-2.c
index eef2519643f..3f1bd1cdcc8 100644
--- a/gcc/testsuite/c-c++-common/attr-used-2.c
+++ b/gcc/testsuite/c-c++-common/attr-used-2.c
@@ -1,5 +1,6 @@
 /* { dg-do compile } */
 /* { dg-options "-Wall -O2" } */
+/* { dg-additional-options "-fgnu-retain" { target R_flag_in_section } } */
 
 static int xyzzy __attribute__((__used__)) = 1; 
 
diff --git a/gcc/testsuite/c-c++-common/attr-used-3.c b/gcc/testsuite/c-c++-common/attr-used-3.c
index ca64197929c..1946c799fea 100644
--- a/gcc/testsuite/c-c++-common/attr-used-3.c
+++ b/gcc/testsuite/c-c++-common/attr-used-3.c
@@ -1,5 +1,6 @@
 /* { dg-do compile } */
 /* { dg-options "-Wall -O2 -fcommon" } */
+/* { dg-additional-options "-fgnu-retain" { target R_flag_in_section } } */
 
 static int xyzzy __attribute__((__used__)); 
 
diff --git a/gcc/testsuite/c-c++-common/attr-used-4.c b/gcc/testsuite/c-c++-common/attr-used-4.c
index 1cbc4c703e9..ed867cfb25a 100644
--- a/gcc/testsuite/c-c++-common/attr-used-4.c
+++ b/gcc/testsuite/c-c++-common/attr-used-4.c
@@ -1,5 +1,6 @@
 /* { dg-do compile } */
 /* { dg-options "-Wall -O2 -fcommon" } */
+/* { dg-additional-options "-fgnu-retain" { target R_flag_in_section } } */
 
 int xyzzy __attribute__((__used__)); 
 
diff --git a/gcc/testsuite/c-c++-common/attr-used-5.c b/gcc/testsuite/c-c++-common/attr-used-5.c
index 5b4924160fd..a346be1e33e 100644
--- a/gcc/testsuite/c-c++-common/attr-used-5.c
+++ b/gcc/testsuite/c-c++-common/attr-used-5.c
@@ -1,6 +1,7 @@
 /* { dg-do compile } */
 /* { dg-skip-if "non-ELF target" { *-*-darwin* } } */
 /* { dg-options "-Wall -O2" } */
+/* { dg-additional-options "-fgnu-retain" { target R_flag_in_section } } */
 
 struct dtv_slotinfo_list
 {
diff --git a/gcc/testsuite/c-c++-common/attr-used-6.c b/gcc/testsuite/c-c++-common/attr-used-6.c
index 3cf288dd28f..a6ca73444f5 100644
--- a/gcc/testsuite/c-c++-common/attr-used-6.c
+++ b/gcc/testsuite/c-c++-common/attr-used-6.c
@@ -1,6 +1,7 @@
 /* { dg-do compile } */
 /* { dg-skip-if "non-ELF target" { *-*-darwin* } } */
 /* { dg-options "-Wall -O2" } */
+/* { dg-additional-options "-fgnu-retain" { target R_flag_in_section } } */
 
 struct dtv_slotinfo_list
 {
diff --git a/gcc/testsuite/c-c++-common/attr-used-7.c b/gcc/testsuite/c-c++-common/attr-used-7.c
index 1721a8afc4e..496a5ea5f5a 100644
--- a/gcc/testsuite/c-c++-common/attr-used-7.c
+++ b/gcc/testsuite/c-c++-common/attr-used-7.c
@@ -1,6 +1,7 @@
 /* { dg-do compile } */
 /* { dg-skip-if "non-ELF target" { *-*-darwin* } } */
 /* { dg-options "-Wall -O2" } */
+/* { dg-additional-options "-fgnu-retain" { target R_flag_in_section } } */
 
 int __attribute__((used,section(".data.foo"))) foo2 = 2;
 int __attribute__((section(".data.foo"))) foo1 = 1;
diff --git a/gcc/testsuite/c-c++-common/attr-used-8.c b/gcc/testsuite/c-c++-common/attr-used-8.c
index 20662cadf70..6856dd7d4a9 100644
--- a/gcc/testsuite/c-c++-common/attr-used-8.c
+++ b/gcc/testsuite/c-c++-common/attr-used-8.c
@@ -1,6 +1,7 @@
 /* { dg-do compile } */
 /* { dg-skip-if "non-ELF target" { *-*-darwin* } } */
 /* { dg-options "-Wall -O2" } */
+/* { dg-additional-options "-fgnu-retain" { target R_flag_in_section } } */
 
 int __attribute__((section(".data.foo"))) foo1 = 1;
 /* { dg-warning "'.*' without 'used' attribute and '.*' with 'used' attribute are placed in a section with the same name" "" { target R_flag_in_section } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-9.c b/gcc/testsuite/c-c++-common/attr-used-9.c
index 5847b0550ce..47b296ab82f 100644
--- a/gcc/testsuite/c-c++-common/attr-used-9.c
+++ b/gcc/testsuite/c-c++-common/attr-used-9.c
@@ -1,6 +1,7 @@
 /* { dg-do compile } */
 /* { dg-skip-if "non-ELF target" { *-*-darwin* } } */
 /* { dg-options "-Wall -O2" } */
+/* { dg-additional-options "-fgnu-retain" { target R_flag_in_section } } */
 
 struct dtv_slotinfo_list
 {
diff --git a/gcc/testsuite/c-c++-common/attr-used.c b/gcc/testsuite/c-c++-common/attr-used.c
index 2036533c959..95d46decf0c 100644
--- a/gcc/testsuite/c-c++-common/attr-used.c
+++ b/gcc/testsuite/c-c++-common/attr-used.c
@@ -1,5 +1,6 @@
 /* { dg-do compile } */
 /* { dg-options "-O3" } */
+/* { dg-additional-options "-fgnu-retain" { target R_flag_in_section } } */
 
 static void function_declaration_before(void) __attribute__((__used__));
 
diff --git a/gcc/testsuite/c-c++-common/pr99113.c b/gcc/testsuite/c-c++-common/pr99113.c
new file mode 100644
index 00000000000..01814014ac8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr99113.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2" } */
+
+static int xyzzy __attribute__((__used__)) = 1; 
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler-not "\.data.*,\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
index 5f6cbca6e33..f4be8d088dc 100644
--- a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
@@ -5,6 +5,7 @@
 /* { dg-final { scan-assembler ".data.*,\"awR\"" } } */
 /* { dg-final { scan-assembler ".rodata.*,\"aR\"" } } */
 /* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
+/* { dg-options "-fgnu-retain" } */
 
 void __attribute__((used)) used_fn (void) { }
 void unused_fn (void) { }
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
index be5f3917ac8..225a1673bec 100644
--- a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
@@ -11,6 +11,6 @@
 /* { dg-final { scan-assembler ".bss.used_lcomm,\"awR\"" { target arm-*-* } } } */
 /* { dg-final { scan-assembler ".bss.used_lcomm2,\"awR\"" { target arm-*-* } } } */
 /* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
-/* { dg-options "-ffunction-sections -fdata-sections" } */
+/* { dg-options "-ffunction-sections -fdata-sections -fgnu-retain" } */
 
 #include "attr-used-retain-1.c"
diff --git a/gcc/toplev.c b/gcc/toplev.c
index d8cc254adef..119cd7c0432 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1761,6 +1761,13 @@ process_options (void)
   if (flag_large_source_files)
     line_table->default_range_bits = 0;
 
+  if (flag_gnu_retain && !SUPPORTS_SHF_GNU_RETAIN)
+    {
+      warning_at (UNKNOWN_LOCATION, 0, "%qs is not supported for this target",
+		  "-fgnu-retain");
+      flag_gnu_retain = 0;
+    }
+
   /* Please don't change global_options after this point, those changes won't
      be reflected in optimization_{default,current}_node.  */
 }
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 29478ab0d8d..4e0e30abee5 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -297,7 +297,7 @@ get_section (const char *name, unsigned int flags, tree decl,
   slot = section_htab->find_slot_with_hash (name, htab_hash_string (name),
 					    INSERT);
   flags |= SECTION_NAMED;
-  if (SUPPORTS_SHF_GNU_RETAIN
+  if (flag_gnu_retain
       && decl != nullptr
       && DECL_P (decl)
       && DECL_PRESERVE_P (decl))
@@ -487,7 +487,7 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
   if (DECL_SECTION_NAME (decl) == NULL
       && targetm_common.have_named_sections
       && (flag_function_or_data_sections
-	  || (SUPPORTS_SHF_GNU_RETAIN && DECL_PRESERVE_P (decl))
+	  || (flag_gnu_retain && DECL_PRESERVE_P (decl))
 	  || DECL_COMDAT_GROUP (decl)))
     {
       targetm.asm_out.unique_section (decl, reloc);
@@ -1227,7 +1227,7 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
     vnode->get_constructor ();
 
   if (DECL_COMMON (decl)
-      && !(SUPPORTS_SHF_GNU_RETAIN && DECL_PRESERVE_P (decl)))
+      && !(flag_gnu_retain && DECL_PRESERVE_P (decl)))
     {
       /* If the decl has been given an explicit section name, or it resides
 	 in a non-generic address space, then it isn't common, and shouldn't
@@ -7761,7 +7761,7 @@ switch_to_section (section *new_section, tree decl)
 {
   if (in_section == new_section)
     {
-      if (SUPPORTS_SHF_GNU_RETAIN
+      if (flag_gnu_retain
 	  && (new_section->common.flags & SECTION_NAMED)
 	  && decl != nullptr
 	  && DECL_P (decl)
-- 
2.29.2

Reply via email to