* [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
@ 2020-11-12 22:41 H.J. Lu
2020-11-13 11:36 ` Jozef Lawrynowicz
0 siblings, 1 reply; 11+ messages in thread
From: H.J. Lu @ 2020-11-12 22:41 UTC (permalink / raw)
To: gcc-patches
In assemly code, the section flag 'R' sets the SHF_GNU_RETAIN flag to
indicate that the section must be preserved by the linker.
Add SECTION_RETAIN to indicate a section should be retained by the linker
and set SECTION_RETAIN on section for the preserved symbol if assembler
supports SHF_GNU_RETAIN. All retained symbols are placed in separate
sections with
.section .data.rel.local.preserved_symbol,"awR"
preserved_symbol:
...
.section .data.rel.local,"aw"
not_preserved_symbol:
...
to avoid
.section .data.rel.local,"awR"
preserved_symbol:
...
not_preserved_symbol:
...
which places not_preserved_symbol definition in the SHF_GNU_RETAIN
section.
gcc/
2020-11-XX H.J. Lu <hjl.tools@gmail.com>
* configure.ac (HAVE_GAS_SHF_GNU_RETAIN): New. Define 1 if
the assembler supports marking sections with SHF_GNU_RETAIN flag.
* output.h (SECTION_RETAIN): New. Defined as 0x4000000.
(SECTION_MACH_DEP): Changed from 0x4000000 to 0x8000000.
(default_unique_section): Add a bool argument.
* varasm.c (get_section): Set SECTION_RETAIN for the preserved
symbol with HAVE_GAS_SHF_GNU_RETAIN.
(resolve_unique_section): Used named section for the preserved
symbol if assembler supports SHF_GNU_RETAIN.
(get_variable_section): Handle the preserved common symbol with
HAVE_GAS_SHF_GNU_RETAIN.
(default_elf_asm_named_section): Require the full declaration and
use the 'R' flag for SECTION_RETAIN.
* config.in: Regenerated.
* configure: Likewise.
gcc/testsuite/
2020-11-XX H.J. Lu <hjl.tools@gmail.com>
Jozef Lawrynowicz <jozef.l@mittosystems.com>
* c-c++-common/attr-used.c: Check the 'R' flag.
* c-c++-common/attr-used-2.c: Likewise.
* c-c++-common/attr-used-3.c: New test.
* c-c++-common/attr-used-4.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-1.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
* lib/target-supports.exp
(check_effective_target_R_flag_in_section): New proc.
---
gcc/config.in | 7 +++
gcc/configure | 51 +++++++++++++++++++
gcc/configure.ac | 20 ++++++++
gcc/output.h | 6 ++-
gcc/testsuite/c-c++-common/attr-used-2.c | 1 +
gcc/testsuite/c-c++-common/attr-used-3.c | 7 +++
gcc/testsuite/c-c++-common/attr-used-4.c | 7 +++
gcc/testsuite/c-c++-common/attr-used.c | 1 +
.../compile/attr-used-retain-1.c | 32 ++++++++++++
.../compile/attr-used-retain-2.c | 15 ++++++
gcc/testsuite/lib/target-supports.exp | 40 +++++++++++++++
gcc/varasm.c | 17 +++++--
12 files changed, 200 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/attr-used-3.c
create mode 100644 gcc/testsuite/c-c++-common/attr-used-4.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
diff --git a/gcc/config.in b/gcc/config.in
index b7c3107bfe3..23ae2f9bc1b 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1352,6 +1352,13 @@
#endif
+/* Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN
+ flag. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SHF_GNU_RETAIN
+#endif
+
+
/* Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.
*/
#ifndef USED_FOR_TARGET
diff --git a/gcc/configure b/gcc/configure
index dbda4415a17..a925a6e5efb 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -24272,6 +24272,57 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'R' flag" >&5
+$as_echo_n "checking assembler for section 'R' flag... " >&6; }
+if ${gcc_cv_as_shf_gnu_retain+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_shf_gnu_retain=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 36 \) \* 1000 + 0`
+ then gcc_cv_as_shf_gnu_retain=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo '.section .foo,"awR",%progbits
+.byte 0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_shf_gnu_retain=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_shf_gnu_retain" >&5
+$as_echo "$gcc_cv_as_shf_gnu_retain" >&6; }
+
+
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SHF_GNU_RETAIN `if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
$as_echo_n "checking assembler for section merging support... " >&6; }
if ${gcc_cv_as_shf_merge+:} false; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 08f3034986e..9713b0abecc 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3256,6 +3256,26 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE,
[`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`],
[Define if your assembler supports specifying the exclude section flag.])
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ gcc_GAS_CHECK_FEATURE([section 'R' flag], gcc_cv_as_shf_gnu_retain,
+ [elf,2,36,0], [--fatal-warnings],
+ [.section .foo,"awR",%progbits
+.byte 0])
+ ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_GNU_RETAIN,
+ [`if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN flag.])
+
gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
[elf,2,12,0], [--fatal-warnings],
[.section .rodata.str, "aMS", @progbits, 1])
diff --git a/gcc/output.h b/gcc/output.h
index 2f2f1697fd8..50c5f7b4a8b 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -381,7 +381,11 @@ extern void no_asm_to_stream (FILE *);
#define SECTION_COMMON 0x800000 /* contains common data */
#define SECTION_RELRO 0x1000000 /* data is readonly after relocation processing */
#define SECTION_EXCLUDE 0x2000000 /* discarded by the linker */
-#define SECTION_MACH_DEP 0x4000000 /* subsequent bits reserved for target */
+#define SECTION_RETAIN 0x4000000 /* retained by the linker. */
+
+/* NB: The maximum SECTION_MACH_DEP is 0x10000000 since AVR needs 4 bits
+ in SECTION_MACH_DEP. */
+#define SECTION_MACH_DEP 0x8000000 /* subsequent bits reserved for target */
/* This SECTION_STYLE is used for unnamed sections that we can switch
to using a special assembler directive. */
diff --git a/gcc/testsuite/c-c++-common/attr-used-2.c b/gcc/testsuite/c-c++-common/attr-used-2.c
index f78b94b53a9..eef2519643f 100644
--- a/gcc/testsuite/c-c++-common/attr-used-2.c
+++ b/gcc/testsuite/c-c++-common/attr-used-2.c
@@ -9,3 +9,4 @@ void foo()
}
/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler "\.data.*,\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-3.c b/gcc/testsuite/c-c++-common/attr-used-3.c
new file mode 100644
index 00000000000..ca64197929c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+static int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-4.c b/gcc/testsuite/c-c++-common/attr-used-4.c
new file mode 100644
index 00000000000..1cbc4c703e9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-4.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used.c b/gcc/testsuite/c-c++-common/attr-used.c
index ba7705aaa77..2036533c959 100644
--- a/gcc/testsuite/c-c++-common/attr-used.c
+++ b/gcc/testsuite/c-c++-common/attr-used.c
@@ -11,3 +11,4 @@ static void function_declaration_after(void) __attribute__((__used__));
/* { dg-final { scan-assembler "function_declaration_before" } } */
/* { dg-final { scan-assembler "function_declaration_after" } } */
+/* { dg-final { scan-assembler "\.text.*,\"axR\"" { 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
new file mode 100644
index 00000000000..b7763af11e4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.*,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.*,\"aR\"" } } */
+
+void __attribute__((used)) used_fn (void) { }
+void unused_fn (void) { }
+void __attribute__((hot,used)) used_hot_fn (void) { }
+void __attribute__((hot)) unused_hot_fn (void) { }
+void __attribute__((cold,used)) used_cold_fn (void) { }
+void __attribute__((cold)) unused_cold_fn (void) { }
+int __attribute__((used)) used_bss = 0;
+int __attribute__((used)) used_data = 1;
+const int __attribute__((used)) used_rodata = 2;
+int __attribute__((used)) used_comm;
+static int __attribute__((used)) used_lcomm;
+
+int unused_bss = 0;
+int unused_data = 1;
+const int unused_rodata = 2;
+int unused_comm;
+static int unused_lcomm;
+
+/* Test switching back to the retained sections. */
+void __attribute__((used)) used_fn2 (void) { }
+int __attribute__((used)) used_bss2 = 0;
+int __attribute__((used)) used_data2 = 1;
+const int __attribute__((used)) used_rodata2 = 2;
+int __attribute__((used)) used_comm2;
+static int __attribute__((used)) used_lcomm2;
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
new file mode 100644
index 00000000000..e3b3cf184f8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.used_fn,\"axR\"" } } */
+/* { dg-final { scan-assembler ".text.used_fn2,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata,\"aR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_lcomm,\"awR\"" { target arm-*-* } } } */
+/* { dg-final { scan-assembler ".bss.used_lcomm2,\"awR\"" { target arm-*-* } } } */
+/* { dg-options "-ffunction-sections -fdata-sections" } */
+
+#include "attr-used-retain-1.c"
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ceee78c26a9..dbebaeb638f 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -10643,3 +10643,43 @@ proc check_effective_target_no_fsanitize_address {} {
}
return 0;
}
+
+# Return 1 if this target supports 'R' flag in .section directive, 0
+# otherwise. Cache the result.
+
+proc check_effective_target_R_flag_in_section { } {
+ global tool
+ global GCC_UNDER_TEST
+
+ # Need auto-host.h to check linker support.
+ if { ![file exists ../../auto-host.h ] } {
+ return 0
+ }
+
+ return [check_cached_effective_target R_flag_in_section {
+
+ set src pie[pid].c
+ set obj pie[pid].o
+
+ set f [open $src "w"]
+ puts $f "#include \"../../auto-host.h\""
+ puts $f "#if HAVE_GAS_SHF_GNU_RETAIN == 0"
+ puts $f "# error Assembler does not support 'R' flag in .section directive."
+ puts $f "#endif"
+ close $f
+
+ verbose "check_effective_target_R_flag_in_section compiling testfile $src" 2
+ set lines [${tool}_target_compile $src $obj assembly ""]
+
+ file delete $src
+ file delete $obj
+
+ if [string match "" $lines] then {
+ verbose "check_effective_target_R_flag_in_section testfile compilation passed" 2
+ return 1
+ } else {
+ verbose "check_effective_target_R_flag_in_section testfile compilation failed" 2
+ return 0
+ }
+ }]
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 435c7b348a5..c48ef9692ee 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -289,6 +289,10 @@ 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 HAVE_GAS_SHF_GNU_RETAIN
+ if (decl != nullptr && DECL_PRESERVE_P (decl))
+ flags |= SECTION_RETAIN;
+#endif
if (*slot == NULL)
{
sect = ggc_alloc<section> ();
@@ -469,6 +473,9 @@ 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
+#if HAVE_GAS_SHF_GNU_RETAIN
+ || DECL_PRESERVE_P (decl)
+#endif
|| DECL_COMDAT_GROUP (decl)))
{
targetm.asm_out.unique_section (decl, reloc);
@@ -1170,7 +1177,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
if (vnode)
vnode->get_constructor ();
- if (DECL_COMMON (decl))
+ if (DECL_COMMON (decl)
+ && !(HAVE_GAS_SHF_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
@@ -6704,9 +6712,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
/* If we have already declared this section, we can use an
abbreviated form to switch back to it -- unless this section is
- part of a COMDAT groups, in which case GAS requires the full
- declaration every time. */
+ part of a COMDAT groups or with SHF_GNU_RETAIN, in which case GAS
+ requires the full declaration every time. */
if (!(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
+ && !(flags & SECTION_RETAIN)
&& (flags & SECTION_DECLARED))
{
fprintf (asm_out_file, "\t.section\t%s\n", name);
@@ -6739,6 +6748,8 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
*f++ = TLS_SECTION_ASM_FLAG;
if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
*f++ = 'G';
+ if (flags & SECTION_RETAIN)
+ *f++ = 'R';
#ifdef MACH_DEP_SECTION_ASM_FLAG
if (flags & SECTION_MACH_DEP)
*f++ = MACH_DEP_SECTION_ASM_FLAG;
--
2.28.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-11-12 22:41 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions H.J. Lu
@ 2020-11-13 11:36 ` Jozef Lawrynowicz
2020-11-13 13:45 ` V2 " H.J. Lu
0 siblings, 1 reply; 11+ messages in thread
From: Jozef Lawrynowicz @ 2020-11-13 11:36 UTC (permalink / raw)
To: H.J. Lu; +Cc: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 757 bytes --]
On Thu, Nov 12, 2020 at 02:41:52PM -0800, H.J. Lu wrote:
> diff --git a/gcc/varasm.c b/gcc/varasm.c
> index 435c7b348a5..c48ef9692ee 100644
> --- a/gcc/varasm.c
> +++ b/gcc/varasm.c
> @@ -289,6 +289,10 @@ 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 HAVE_GAS_SHF_GNU_RETAIN
> + if (decl != nullptr && DECL_PRESERVE_P (decl))
Minor nit, but I think this should be "decl != NULL_TREE".
We should also test that "used" with the "section" attribute applies the
"R" flag. Please apply the attached patch if this gets approved. These
new tests pass with arm-none-eabi and x86_64-pc-linux-gnu.
Thanks,
Jozef
[-- Attachment #2: 1113-used-test-section-attr.diff --]
[-- Type: text/plain, Size: 1809 bytes --]
commit cf8e26deb43d13268ab6ee231995aecbf41ba3a3
Author: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Fri Nov 13 11:07:14 2020 +0000
Test "used" attribute in conjunction "section" attribute
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 b7763af11e4..5f6cbca6e33 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
@@ -4,6 +4,7 @@
/* { dg-final { scan-assembler ".bss.*,\"awR\"" } } */
/* { dg-final { scan-assembler ".data.*,\"awR\"" } } */
/* { dg-final { scan-assembler ".rodata.*,\"aR\"" } } */
+/* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
void __attribute__((used)) used_fn (void) { }
void unused_fn (void) { }
@@ -30,3 +31,5 @@ int __attribute__((used)) used_data2 = 1;
const int __attribute__((used)) used_rodata2 = 2;
int __attribute__((used)) used_comm2;
static int __attribute__((used)) used_lcomm2;
+
+int __attribute__((used,section(".data.used_foo_sec"))) used_foo = 2;
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 e3b3cf184f8..be5f3917ac8 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
@@ -10,6 +10,7 @@
/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
/* { 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" } */
#include "attr-used-retain-1.c"
^ permalink raw reply [flat|nested] 11+ messages in thread
* V2 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-11-13 11:36 ` Jozef Lawrynowicz
@ 2020-11-13 13:45 ` H.J. Lu
2020-11-17 3:59 ` Hans-Peter Nilsson
0 siblings, 1 reply; 11+ messages in thread
From: H.J. Lu @ 2020-11-13 13:45 UTC (permalink / raw)
Cc: GCC Patches
[-- Attachment #1: Type: text/plain, Size: 1026 bytes --]
On Fri, Nov 13, 2020 at 3:36 AM Jozef Lawrynowicz
<jozef.l@mittosystems.com> wrote:
>
> On Thu, Nov 12, 2020 at 02:41:52PM -0800, H.J. Lu wrote:
> > diff --git a/gcc/varasm.c b/gcc/varasm.c
> > index 435c7b348a5..c48ef9692ee 100644
> > --- a/gcc/varasm.c
> > +++ b/gcc/varasm.c
> > @@ -289,6 +289,10 @@ 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 HAVE_GAS_SHF_GNU_RETAIN
> > + if (decl != nullptr && DECL_PRESERVE_P (decl))
>
> Minor nit, but I think this should be "decl != NULL_TREE".
We are using C++ now. Should we start using nullptr instead of
NULL_TREE or NULL_RTX?
> We should also test that "used" with the "section" attribute applies the
> "R" flag. Please apply the attached patch if this gets approved. These
> new tests pass with arm-none-eabi and x86_64-pc-linux-gnu.
>
Done. Here is the updated patch.
--
H.J.
[-- Attachment #2: 0001-Use-SHF_GNU_RETAIN-to-preserve-symbol-definitions.patch --]
[-- Type: text/x-patch, Size: 16312 bytes --]
From 07c4c78c43d3b94e56d6ace97b660c69998011e4 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 3 Feb 2020 11:55:43 -0800
Subject: [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
In assemly code, the section flag 'R' sets the SHF_GNU_RETAIN flag to
indicate that the section must be preserved by the linker.
Add SECTION_RETAIN to indicate a section should be retained by the linker
and set SECTION_RETAIN on section for the preserved symbol if assembler
supports SHF_GNU_RETAIN. All retained symbols are placed in separate
sections with
.section .data.rel.local.preserved_symbol,"awR"
preserved_symbol:
...
.section .data.rel.local,"aw"
not_preserved_symbol:
...
to avoid
.section .data.rel.local,"awR"
preserved_symbol:
...
not_preserved_symbol:
...
which places not_preserved_symbol definition in the SHF_GNU_RETAIN
section.
gcc/
2020-11-XX H.J. Lu <hjl.tools@gmail.com>
* configure.ac (HAVE_GAS_SHF_GNU_RETAIN): New. Define 1 if
the assembler supports marking sections with SHF_GNU_RETAIN flag.
* output.h (SECTION_RETAIN): New. Defined as 0x4000000.
(SECTION_MACH_DEP): Changed from 0x4000000 to 0x8000000.
(default_unique_section): Add a bool argument.
* varasm.c (get_section): Set SECTION_RETAIN for the preserved
symbol with HAVE_GAS_SHF_GNU_RETAIN.
(resolve_unique_section): Used named section for the preserved
symbol if assembler supports SHF_GNU_RETAIN.
(get_variable_section): Handle the preserved common symbol with
HAVE_GAS_SHF_GNU_RETAIN.
(default_elf_asm_named_section): Require the full declaration and
use the 'R' flag for SECTION_RETAIN.
* config.in: Regenerated.
* configure: Likewise.
gcc/testsuite/
2020-11-XX H.J. Lu <hjl.tools@gmail.com>
Jozef Lawrynowicz <jozef.l@mittosystems.com>
* c-c++-common/attr-used.c: Check the 'R' flag.
* c-c++-common/attr-used-2.c: Likewise.
* c-c++-common/attr-used-3.c: New test.
* c-c++-common/attr-used-4.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-1.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
* lib/target-supports.exp
(check_effective_target_R_flag_in_section): New proc.
---
gcc/config.in | 7 +++
gcc/configure | 51 +++++++++++++++++++
gcc/configure.ac | 20 ++++++++
gcc/output.h | 6 ++-
gcc/testsuite/c-c++-common/attr-used-2.c | 1 +
gcc/testsuite/c-c++-common/attr-used-3.c | 7 +++
gcc/testsuite/c-c++-common/attr-used-4.c | 7 +++
gcc/testsuite/c-c++-common/attr-used.c | 1 +
.../compile/attr-used-retain-1.c | 35 +++++++++++++
.../compile/attr-used-retain-2.c | 16 ++++++
gcc/testsuite/lib/target-supports.exp | 40 +++++++++++++++
gcc/varasm.c | 17 +++++--
12 files changed, 204 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/attr-used-3.c
create mode 100644 gcc/testsuite/c-c++-common/attr-used-4.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
diff --git a/gcc/config.in b/gcc/config.in
index b7c3107bfe3..23ae2f9bc1b 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1352,6 +1352,13 @@
#endif
+/* Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN
+ flag. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SHF_GNU_RETAIN
+#endif
+
+
/* Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.
*/
#ifndef USED_FOR_TARGET
diff --git a/gcc/configure b/gcc/configure
index dbda4415a17..a925a6e5efb 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -24272,6 +24272,57 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'R' flag" >&5
+$as_echo_n "checking assembler for section 'R' flag... " >&6; }
+if ${gcc_cv_as_shf_gnu_retain+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_shf_gnu_retain=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 36 \) \* 1000 + 0`
+ then gcc_cv_as_shf_gnu_retain=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo '.section .foo,"awR",%progbits
+.byte 0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_shf_gnu_retain=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_shf_gnu_retain" >&5
+$as_echo "$gcc_cv_as_shf_gnu_retain" >&6; }
+
+
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SHF_GNU_RETAIN `if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
$as_echo_n "checking assembler for section merging support... " >&6; }
if ${gcc_cv_as_shf_merge+:} false; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 08f3034986e..9713b0abecc 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3256,6 +3256,26 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE,
[`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`],
[Define if your assembler supports specifying the exclude section flag.])
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ gcc_GAS_CHECK_FEATURE([section 'R' flag], gcc_cv_as_shf_gnu_retain,
+ [elf,2,36,0], [--fatal-warnings],
+ [.section .foo,"awR",%progbits
+.byte 0])
+ ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_GNU_RETAIN,
+ [`if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN flag.])
+
gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
[elf,2,12,0], [--fatal-warnings],
[.section .rodata.str, "aMS", @progbits, 1])
diff --git a/gcc/output.h b/gcc/output.h
index 2f2f1697fd8..50c5f7b4a8b 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -381,7 +381,11 @@ extern void no_asm_to_stream (FILE *);
#define SECTION_COMMON 0x800000 /* contains common data */
#define SECTION_RELRO 0x1000000 /* data is readonly after relocation processing */
#define SECTION_EXCLUDE 0x2000000 /* discarded by the linker */
-#define SECTION_MACH_DEP 0x4000000 /* subsequent bits reserved for target */
+#define SECTION_RETAIN 0x4000000 /* retained by the linker. */
+
+/* NB: The maximum SECTION_MACH_DEP is 0x10000000 since AVR needs 4 bits
+ in SECTION_MACH_DEP. */
+#define SECTION_MACH_DEP 0x8000000 /* subsequent bits reserved for target */
/* This SECTION_STYLE is used for unnamed sections that we can switch
to using a special assembler directive. */
diff --git a/gcc/testsuite/c-c++-common/attr-used-2.c b/gcc/testsuite/c-c++-common/attr-used-2.c
index f78b94b53a9..eef2519643f 100644
--- a/gcc/testsuite/c-c++-common/attr-used-2.c
+++ b/gcc/testsuite/c-c++-common/attr-used-2.c
@@ -9,3 +9,4 @@ void foo()
}
/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler "\.data.*,\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-3.c b/gcc/testsuite/c-c++-common/attr-used-3.c
new file mode 100644
index 00000000000..ca64197929c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+static int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-4.c b/gcc/testsuite/c-c++-common/attr-used-4.c
new file mode 100644
index 00000000000..1cbc4c703e9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-4.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used.c b/gcc/testsuite/c-c++-common/attr-used.c
index ba7705aaa77..2036533c959 100644
--- a/gcc/testsuite/c-c++-common/attr-used.c
+++ b/gcc/testsuite/c-c++-common/attr-used.c
@@ -11,3 +11,4 @@ static void function_declaration_after(void) __attribute__((__used__));
/* { dg-final { scan-assembler "function_declaration_before" } } */
/* { dg-final { scan-assembler "function_declaration_after" } } */
+/* { dg-final { scan-assembler "\.text.*,\"axR\"" { 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
new file mode 100644
index 00000000000..5f6cbca6e33
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.*,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.*,\"aR\"" } } */
+/* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
+
+void __attribute__((used)) used_fn (void) { }
+void unused_fn (void) { }
+void __attribute__((hot,used)) used_hot_fn (void) { }
+void __attribute__((hot)) unused_hot_fn (void) { }
+void __attribute__((cold,used)) used_cold_fn (void) { }
+void __attribute__((cold)) unused_cold_fn (void) { }
+int __attribute__((used)) used_bss = 0;
+int __attribute__((used)) used_data = 1;
+const int __attribute__((used)) used_rodata = 2;
+int __attribute__((used)) used_comm;
+static int __attribute__((used)) used_lcomm;
+
+int unused_bss = 0;
+int unused_data = 1;
+const int unused_rodata = 2;
+int unused_comm;
+static int unused_lcomm;
+
+/* Test switching back to the retained sections. */
+void __attribute__((used)) used_fn2 (void) { }
+int __attribute__((used)) used_bss2 = 0;
+int __attribute__((used)) used_data2 = 1;
+const int __attribute__((used)) used_rodata2 = 2;
+int __attribute__((used)) used_comm2;
+static int __attribute__((used)) used_lcomm2;
+
+int __attribute__((used,section(".data.used_foo_sec"))) used_foo = 2;
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
new file mode 100644
index 00000000000..be5f3917ac8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.used_fn,\"axR\"" } } */
+/* { dg-final { scan-assembler ".text.used_fn2,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata,\"aR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
+/* { 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" } */
+
+#include "attr-used-retain-1.c"
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ceee78c26a9..dbebaeb638f 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -10643,3 +10643,43 @@ proc check_effective_target_no_fsanitize_address {} {
}
return 0;
}
+
+# Return 1 if this target supports 'R' flag in .section directive, 0
+# otherwise. Cache the result.
+
+proc check_effective_target_R_flag_in_section { } {
+ global tool
+ global GCC_UNDER_TEST
+
+ # Need auto-host.h to check linker support.
+ if { ![file exists ../../auto-host.h ] } {
+ return 0
+ }
+
+ return [check_cached_effective_target R_flag_in_section {
+
+ set src pie[pid].c
+ set obj pie[pid].o
+
+ set f [open $src "w"]
+ puts $f "#include \"../../auto-host.h\""
+ puts $f "#if HAVE_GAS_SHF_GNU_RETAIN == 0"
+ puts $f "# error Assembler does not support 'R' flag in .section directive."
+ puts $f "#endif"
+ close $f
+
+ verbose "check_effective_target_R_flag_in_section compiling testfile $src" 2
+ set lines [${tool}_target_compile $src $obj assembly ""]
+
+ file delete $src
+ file delete $obj
+
+ if [string match "" $lines] then {
+ verbose "check_effective_target_R_flag_in_section testfile compilation passed" 2
+ return 1
+ } else {
+ verbose "check_effective_target_R_flag_in_section testfile compilation failed" 2
+ return 0
+ }
+ }]
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 435c7b348a5..c48ef9692ee 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -289,6 +289,10 @@ 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 HAVE_GAS_SHF_GNU_RETAIN
+ if (decl != nullptr && DECL_PRESERVE_P (decl))
+ flags |= SECTION_RETAIN;
+#endif
if (*slot == NULL)
{
sect = ggc_alloc<section> ();
@@ -469,6 +473,9 @@ 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
+#if HAVE_GAS_SHF_GNU_RETAIN
+ || DECL_PRESERVE_P (decl)
+#endif
|| DECL_COMDAT_GROUP (decl)))
{
targetm.asm_out.unique_section (decl, reloc);
@@ -1170,7 +1177,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
if (vnode)
vnode->get_constructor ();
- if (DECL_COMMON (decl))
+ if (DECL_COMMON (decl)
+ && !(HAVE_GAS_SHF_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
@@ -6704,9 +6712,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
/* If we have already declared this section, we can use an
abbreviated form to switch back to it -- unless this section is
- part of a COMDAT groups, in which case GAS requires the full
- declaration every time. */
+ part of a COMDAT groups or with SHF_GNU_RETAIN, in which case GAS
+ requires the full declaration every time. */
if (!(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
+ && !(flags & SECTION_RETAIN)
&& (flags & SECTION_DECLARED))
{
fprintf (asm_out_file, "\t.section\t%s\n", name);
@@ -6739,6 +6748,8 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
*f++ = TLS_SECTION_ASM_FLAG;
if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
*f++ = 'G';
+ if (flags & SECTION_RETAIN)
+ *f++ = 'R';
#ifdef MACH_DEP_SECTION_ASM_FLAG
if (flags & SECTION_MACH_DEP)
*f++ = MACH_DEP_SECTION_ASM_FLAG;
--
2.28.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V2 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-11-13 13:45 ` V2 " H.J. Lu
@ 2020-11-17 3:59 ` Hans-Peter Nilsson
2020-11-17 13:20 ` H.J. Lu
0 siblings, 1 reply; 11+ messages in thread
From: Hans-Peter Nilsson @ 2020-11-17 3:59 UTC (permalink / raw)
To: H.J. Lu; +Cc: GCC Patches
On Fri, 13 Nov 2020, H.J. Lu via Gcc-patches wrote:
> Done. Here is the updated patch.
Hi. I see a test-case for this kind of construct:
int foo __attribute__((__used__, __section__ (".bar"))) = 42;
and IIUC that it's handled as I'd hope (setting "R" on the named
section, not another derived section), good.
Could you also add a test-case that the same construct
*without* a specific initializer is handled the same way?
I.e.:
int foo __attribute__((__used__, __section__ (".bar")));
Thanks in advance.
brgds, H-P
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V2 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-11-17 3:59 ` Hans-Peter Nilsson
@ 2020-11-17 13:20 ` H.J. Lu
2020-12-02 0:04 ` Jeff Law
0 siblings, 1 reply; 11+ messages in thread
From: H.J. Lu @ 2020-11-17 13:20 UTC (permalink / raw)
To: Hans-Peter Nilsson; +Cc: GCC Patches
[-- Attachment #1: Type: text/plain, Size: 821 bytes --]
On Mon, Nov 16, 2020 at 7:59 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>
> On Fri, 13 Nov 2020, H.J. Lu via Gcc-patches wrote:
> > Done. Here is the updated patch.
>
> Hi. I see a test-case for this kind of construct:
>
> int foo __attribute__((__used__, __section__ (".bar"))) = 42;
>
> and IIUC that it's handled as I'd hope (setting "R" on the named
> section, not another derived section), good.
>
> Could you also add a test-case that the same construct
> *without* a specific initializer is handled the same way?
> I.e.:
> int foo __attribute__((__used__, __section__ (".bar")));
>
Done. The only changes are
/* { dg-final { scan-assembler ".data.used_bar_sec,\"awR\"" } } */
...
int __attribute__((used,section(".data.used_bar_sec"))) used_bar;
and 2 additional tests for -fcommon.
Thanks.
--
H.J.
[-- Attachment #2: 0001-Use-SHF_GNU_RETAIN-to-preserve-symbol-definitions.patch --]
[-- Type: text/x-patch, Size: 19445 bytes --]
From d19f2e2ec7f0f47121a2a4c05ffe20af8972c1bb Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 3 Feb 2020 11:55:43 -0800
Subject: [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
In assemly code, the section flag 'R' sets the SHF_GNU_RETAIN flag to
indicate that the section must be preserved by the linker.
Add SECTION_RETAIN to indicate a section should be retained by the linker
and set SECTION_RETAIN on section for the preserved symbol if assembler
supports SHF_GNU_RETAIN. All retained symbols are placed in separate
sections with
.section .data.rel.local.preserved_symbol,"awR"
preserved_symbol:
...
.section .data.rel.local,"aw"
not_preserved_symbol:
...
to avoid
.section .data.rel.local,"awR"
preserved_symbol:
...
not_preserved_symbol:
...
which places not_preserved_symbol definition in the SHF_GNU_RETAIN
section.
gcc/
2020-11-XX H.J. Lu <hjl.tools@gmail.com>
* configure.ac (HAVE_GAS_SHF_GNU_RETAIN): New. Define 1 if
the assembler supports marking sections with SHF_GNU_RETAIN flag.
* output.h (SECTION_RETAIN): New. Defined as 0x4000000.
(SECTION_MACH_DEP): Changed from 0x4000000 to 0x8000000.
(default_unique_section): Add a bool argument.
* varasm.c (get_section): Set SECTION_RETAIN for the preserved
symbol with HAVE_GAS_SHF_GNU_RETAIN.
(resolve_unique_section): Used named section for the preserved
symbol if assembler supports SHF_GNU_RETAIN.
(get_variable_section): Handle the preserved common symbol with
HAVE_GAS_SHF_GNU_RETAIN.
(default_elf_asm_named_section): Require the full declaration and
use the 'R' flag for SECTION_RETAIN.
* config.in: Regenerated.
* configure: Likewise.
gcc/testsuite/
2020-11-XX H.J. Lu <hjl.tools@gmail.com>
Jozef Lawrynowicz <jozef.l@mittosystems.com>
* c-c++-common/attr-used.c: Check the 'R' flag.
* c-c++-common/attr-used-2.c: Likewise.
* c-c++-common/attr-used-3.c: New test.
* c-c++-common/attr-used-4.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-1.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-3.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-4.c: Likewise.
* lib/target-supports.exp
(check_effective_target_R_flag_in_section): New proc.
---
gcc/config.in | 7 +++
gcc/configure | 51 +++++++++++++++++++
gcc/configure.ac | 20 ++++++++
gcc/output.h | 6 ++-
gcc/testsuite/c-c++-common/attr-used-2.c | 1 +
gcc/testsuite/c-c++-common/attr-used-3.c | 7 +++
gcc/testsuite/c-c++-common/attr-used-4.c | 7 +++
gcc/testsuite/c-c++-common/attr-used.c | 1 +
.../compile/attr-used-retain-1.c | 37 ++++++++++++++
.../compile/attr-used-retain-2.c | 17 +++++++
.../compile/attr-used-retain-3.c | 17 +++++++
.../compile/attr-used-retain-4.c | 17 +++++++
gcc/testsuite/lib/target-supports.exp | 40 +++++++++++++++
gcc/varasm.c | 17 +++++--
14 files changed, 241 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/attr-used-3.c
create mode 100644 gcc/testsuite/c-c++-common/attr-used-4.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-3.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-4.c
diff --git a/gcc/config.in b/gcc/config.in
index b7c3107bfe3..23ae2f9bc1b 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1352,6 +1352,13 @@
#endif
+/* Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN
+ flag. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SHF_GNU_RETAIN
+#endif
+
+
/* Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.
*/
#ifndef USED_FOR_TARGET
diff --git a/gcc/configure b/gcc/configure
index dbda4415a17..a925a6e5efb 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -24272,6 +24272,57 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'R' flag" >&5
+$as_echo_n "checking assembler for section 'R' flag... " >&6; }
+if ${gcc_cv_as_shf_gnu_retain+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_shf_gnu_retain=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 36 \) \* 1000 + 0`
+ then gcc_cv_as_shf_gnu_retain=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo '.section .foo,"awR",%progbits
+.byte 0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_shf_gnu_retain=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_shf_gnu_retain" >&5
+$as_echo "$gcc_cv_as_shf_gnu_retain" >&6; }
+
+
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SHF_GNU_RETAIN `if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
$as_echo_n "checking assembler for section merging support... " >&6; }
if ${gcc_cv_as_shf_merge+:} false; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 08f3034986e..9713b0abecc 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3256,6 +3256,26 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE,
[`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`],
[Define if your assembler supports specifying the exclude section flag.])
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ gcc_GAS_CHECK_FEATURE([section 'R' flag], gcc_cv_as_shf_gnu_retain,
+ [elf,2,36,0], [--fatal-warnings],
+ [.section .foo,"awR",%progbits
+.byte 0])
+ ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_GNU_RETAIN,
+ [`if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN flag.])
+
gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
[elf,2,12,0], [--fatal-warnings],
[.section .rodata.str, "aMS", @progbits, 1])
diff --git a/gcc/output.h b/gcc/output.h
index b44c1bd6fc7..729c52099e6 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -381,7 +381,11 @@ extern void no_asm_to_stream (FILE *);
#define SECTION_COMMON 0x800000 /* contains common data */
#define SECTION_RELRO 0x1000000 /* data is readonly after relocation processing */
#define SECTION_EXCLUDE 0x2000000 /* discarded by the linker */
-#define SECTION_MACH_DEP 0x4000000 /* subsequent bits reserved for target */
+#define SECTION_RETAIN 0x4000000 /* retained by the linker. */
+
+/* NB: The maximum SECTION_MACH_DEP is 0x10000000 since AVR needs 4 bits
+ in SECTION_MACH_DEP. */
+#define SECTION_MACH_DEP 0x8000000 /* subsequent bits reserved for target */
/* This SECTION_STYLE is used for unnamed sections that we can switch
to using a special assembler directive. */
diff --git a/gcc/testsuite/c-c++-common/attr-used-2.c b/gcc/testsuite/c-c++-common/attr-used-2.c
index f78b94b53a9..eef2519643f 100644
--- a/gcc/testsuite/c-c++-common/attr-used-2.c
+++ b/gcc/testsuite/c-c++-common/attr-used-2.c
@@ -9,3 +9,4 @@ void foo()
}
/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler "\.data.*,\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-3.c b/gcc/testsuite/c-c++-common/attr-used-3.c
new file mode 100644
index 00000000000..ca64197929c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+static int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-4.c b/gcc/testsuite/c-c++-common/attr-used-4.c
new file mode 100644
index 00000000000..1cbc4c703e9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-4.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used.c b/gcc/testsuite/c-c++-common/attr-used.c
index ba7705aaa77..2036533c959 100644
--- a/gcc/testsuite/c-c++-common/attr-used.c
+++ b/gcc/testsuite/c-c++-common/attr-used.c
@@ -11,3 +11,4 @@ static void function_declaration_after(void) __attribute__((__used__));
/* { dg-final { scan-assembler "function_declaration_before" } } */
/* { dg-final { scan-assembler "function_declaration_after" } } */
+/* { dg-final { scan-assembler "\.text.*,\"axR\"" { 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
new file mode 100644
index 00000000000..b386b8882d4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.*,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.*,\"aR\"" } } */
+/* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_bar_sec,\"awR\"" } } */
+
+void __attribute__((used)) used_fn (void) { }
+void unused_fn (void) { }
+void __attribute__((hot,used)) used_hot_fn (void) { }
+void __attribute__((hot)) unused_hot_fn (void) { }
+void __attribute__((cold,used)) used_cold_fn (void) { }
+void __attribute__((cold)) unused_cold_fn (void) { }
+int __attribute__((used)) used_bss = 0;
+int __attribute__((used)) used_data = 1;
+const int __attribute__((used)) used_rodata = 2;
+int __attribute__((used)) used_comm;
+static int __attribute__((used)) used_lcomm;
+
+int unused_bss = 0;
+int unused_data = 1;
+const int unused_rodata = 2;
+int unused_comm;
+static int unused_lcomm;
+
+/* Test switching back to the retained sections. */
+void __attribute__((used)) used_fn2 (void) { }
+int __attribute__((used)) used_bss2 = 0;
+int __attribute__((used)) used_data2 = 1;
+const int __attribute__((used)) used_rodata2 = 2;
+int __attribute__((used)) used_comm2;
+static int __attribute__((used)) used_lcomm2;
+
+int __attribute__((used,section(".data.used_foo_sec"))) used_foo = 2;
+int __attribute__((used,section(".data.used_bar_sec"))) used_bar;
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
new file mode 100644
index 00000000000..1ad454a2801
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.used_fn,\"axR\"" } } */
+/* { dg-final { scan-assembler ".text.used_fn2,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata,\"aR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
+/* { 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-final { scan-assembler ".data.used_bar_sec,\"awR\"" } } */
+/* { dg-options "-ffunction-sections -fdata-sections" } */
+
+#include "attr-used-retain-1.c"
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-3.c b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-3.c
new file mode 100644
index 00000000000..5f537e4efa9
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.used_fn,\"axR\"" } } */
+/* { dg-final { scan-assembler ".text.used_fn2,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata,\"aR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
+/* { 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-final { scan-assembler ".data.used_bar_sec,\"awR\"" } } */
+/* { dg-options "-fcommon" } */
+
+#include "attr-used-retain-1.c"
diff --git a/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-4.c b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-4.c
new file mode 100644
index 00000000000..e15753f55d5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.used_fn,\"axR\"" } } */
+/* { dg-final { scan-assembler ".text.used_fn2,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata,\"aR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
+/* { 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-final { scan-assembler ".data.used_bar_sec,\"awR\"" } } */
+/* { dg-options "-fcommon -ffunction-sections -fdata-sections" } */
+
+#include "attr-used-retain-1.c"
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 22acda2a74f..20dcc8b91ce 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -10650,3 +10650,43 @@ proc check_effective_target_no_fsanitize_address {} {
}
return 0;
}
+
+# Return 1 if this target supports 'R' flag in .section directive, 0
+# otherwise. Cache the result.
+
+proc check_effective_target_R_flag_in_section { } {
+ global tool
+ global GCC_UNDER_TEST
+
+ # Need auto-host.h to check linker support.
+ if { ![file exists ../../auto-host.h ] } {
+ return 0
+ }
+
+ return [check_cached_effective_target R_flag_in_section {
+
+ set src pie[pid].c
+ set obj pie[pid].o
+
+ set f [open $src "w"]
+ puts $f "#include \"../../auto-host.h\""
+ puts $f "#if HAVE_GAS_SHF_GNU_RETAIN == 0"
+ puts $f "# error Assembler does not support 'R' flag in .section directive."
+ puts $f "#endif"
+ close $f
+
+ verbose "check_effective_target_R_flag_in_section compiling testfile $src" 2
+ set lines [${tool}_target_compile $src $obj assembly ""]
+
+ file delete $src
+ file delete $obj
+
+ if [string match "" $lines] then {
+ verbose "check_effective_target_R_flag_in_section testfile compilation passed" 2
+ return 1
+ } else {
+ verbose "check_effective_target_R_flag_in_section testfile compilation failed" 2
+ return 0
+ }
+ }]
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index ada99940f65..745e51a31a8 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -289,6 +289,10 @@ 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 HAVE_GAS_SHF_GNU_RETAIN
+ if (decl != nullptr && DECL_PRESERVE_P (decl))
+ flags |= SECTION_RETAIN;
+#endif
if (*slot == NULL)
{
sect = ggc_alloc<section> ();
@@ -469,6 +473,9 @@ 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
+#if HAVE_GAS_SHF_GNU_RETAIN
+ || DECL_PRESERVE_P (decl)
+#endif
|| DECL_COMDAT_GROUP (decl)))
{
targetm.asm_out.unique_section (decl, reloc);
@@ -1203,7 +1210,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
if (vnode)
vnode->get_constructor ();
- if (DECL_COMMON (decl))
+ if (DECL_COMMON (decl)
+ && !(HAVE_GAS_SHF_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
@@ -6737,9 +6745,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
/* If we have already declared this section, we can use an
abbreviated form to switch back to it -- unless this section is
- part of a COMDAT groups, in which case GAS requires the full
- declaration every time. */
+ part of a COMDAT groups or with SHF_GNU_RETAIN, in which case GAS
+ requires the full declaration every time. */
if (!(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
+ && !(flags & SECTION_RETAIN)
&& (flags & SECTION_DECLARED))
{
fprintf (asm_out_file, "\t.section\t%s\n", name);
@@ -6772,6 +6781,8 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
*f++ = TLS_SECTION_ASM_FLAG;
if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
*f++ = 'G';
+ if (flags & SECTION_RETAIN)
+ *f++ = 'R';
#ifdef MACH_DEP_SECTION_ASM_FLAG
if (flags & SECTION_MACH_DEP)
*f++ = MACH_DEP_SECTION_ASM_FLAG;
--
2.28.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V2 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-11-17 13:20 ` H.J. Lu
@ 2020-12-02 0:04 ` Jeff Law
2020-12-02 0:36 ` V3 " H.J. Lu
0 siblings, 1 reply; 11+ messages in thread
From: Jeff Law @ 2020-12-02 0:04 UTC (permalink / raw)
To: H.J. Lu, Hans-Peter Nilsson; +Cc: GCC Patches
On 11/17/20 6:20 AM, H.J. Lu via Gcc-patches wrote:
> On Mon, Nov 16, 2020 at 7:59 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>> On Fri, 13 Nov 2020, H.J. Lu via Gcc-patches wrote:
>>> Done. Here is the updated patch.
>> Hi. I see a test-case for this kind of construct:
>>
>> int foo __attribute__((__used__, __section__ (".bar"))) = 42;
>>
>> and IIUC that it's handled as I'd hope (setting "R" on the named
>> section, not another derived section), good.
>>
>> Could you also add a test-case that the same construct
>> *without* a specific initializer is handled the same way?
>> I.e.:
>> int foo __attribute__((__used__, __section__ (".bar")));
>>
> Done. The only changes are
>
> /* { dg-final { scan-assembler ".data.used_bar_sec,\"awR\"" } } */
> ...
> int __attribute__((used,section(".data.used_bar_sec"))) used_bar;
>
> and 2 additional tests for -fcommon.
>
> Thanks.
>
>
> 0001-Use-SHF_GNU_RETAIN-to-preserve-symbol-definitions.patch
>
> From d19f2e2ec7f0f47121a2a4c05ffe20af8972c1bb Mon Sep 17 00:00:00 2001
> From: "H.J. Lu" <hjl.tools@gmail.com>
> Date: Mon, 3 Feb 2020 11:55:43 -0800
> Subject: [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
>
> In assemly code, the section flag 'R' sets the SHF_GNU_RETAIN flag to
> indicate that the section must be preserved by the linker.
>
> Add SECTION_RETAIN to indicate a section should be retained by the linker
> and set SECTION_RETAIN on section for the preserved symbol if assembler
> supports SHF_GNU_RETAIN. All retained symbols are placed in separate
> sections with
>
> .section .data.rel.local.preserved_symbol,"awR"
> preserved_symbol:
> ...
> .section .data.rel.local,"aw"
> not_preserved_symbol:
> ...
>
> to avoid
>
> .section .data.rel.local,"awR"
> preserved_symbol:
> ...
> not_preserved_symbol:
> ...
>
> which places not_preserved_symbol definition in the SHF_GNU_RETAIN
> section.
>
> gcc/
>
> 2020-11-XX H.J. Lu <hjl.tools@gmail.com>
>
> * configure.ac (HAVE_GAS_SHF_GNU_RETAIN): New. Define 1 if
> the assembler supports marking sections with SHF_GNU_RETAIN flag.
> * output.h (SECTION_RETAIN): New. Defined as 0x4000000.
> (SECTION_MACH_DEP): Changed from 0x4000000 to 0x8000000.
> (default_unique_section): Add a bool argument.
> * varasm.c (get_section): Set SECTION_RETAIN for the preserved
> symbol with HAVE_GAS_SHF_GNU_RETAIN.
> (resolve_unique_section): Used named section for the preserved
> symbol if assembler supports SHF_GNU_RETAIN.
> (get_variable_section): Handle the preserved common symbol with
> HAVE_GAS_SHF_GNU_RETAIN.
> (default_elf_asm_named_section): Require the full declaration and
> use the 'R' flag for SECTION_RETAIN.
> * config.in: Regenerated.
> * configure: Likewise.
>
> gcc/testsuite/
>
> 2020-11-XX H.J. Lu <hjl.tools@gmail.com>
> Jozef Lawrynowicz <jozef.l@mittosystems.com>
>
> * c-c++-common/attr-used.c: Check the 'R' flag.
> * c-c++-common/attr-used-2.c: Likewise.
> * c-c++-common/attr-used-3.c: New test.
> * c-c++-common/attr-used-4.c: Likewise.
> * gcc.c-torture/compile/attr-used-retain-1.c: Likewise.
> * gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
> * gcc.c-torture/compile/attr-used-retain-3.c: Likewise.
> * gcc.c-torture/compile/attr-used-retain-4.c: Likewise.
> * lib/target-supports.exp
> (check_effective_target_R_flag_in_section): New proc.
Can we try to avoid the #if stuff, particulary in varasm.c. We worked
pretty hard to reduce the amount of conditionally compiled code through
the years and we should try to avoid adding new instances.
HAVE_GAS_SHF_GNU_RETAIN is going to be a compile-time constant, so it
should be just as efficient to do things like
if (HAVE_GAS_SHF_GNU_RETAIN)
... whatever ...
This has the advantage that the same code is presented to the
front-ends, so we're at lot less likely to stumble over set-but-not-used
warnings and the like that were so problematical a few years back. In
fact, you use that style elsewhere in varasm.c :-)
I think you need to document the new effective target check in
doc/sourcebuild.texi
With those changes this should be fine.
jeff
^ permalink raw reply [flat|nested] 11+ messages in thread
* V3 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-12-02 0:04 ` Jeff Law
@ 2020-12-02 0:36 ` H.J. Lu
2020-12-02 0:38 ` Jeff Law
0 siblings, 1 reply; 11+ messages in thread
From: H.J. Lu @ 2020-12-02 0:36 UTC (permalink / raw)
To: Jeff Law; +Cc: Hans-Peter Nilsson, GCC Patches
[-- Attachment #1: Type: text/plain, Size: 4617 bytes --]
On Tue, Dec 1, 2020 at 4:04 PM Jeff Law <law@redhat.com> wrote:
>
>
>
> On 11/17/20 6:20 AM, H.J. Lu via Gcc-patches wrote:
> > On Mon, Nov 16, 2020 at 7:59 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> >> On Fri, 13 Nov 2020, H.J. Lu via Gcc-patches wrote:
> >>> Done. Here is the updated patch.
> >> Hi. I see a test-case for this kind of construct:
> >>
> >> int foo __attribute__((__used__, __section__ (".bar"))) = 42;
> >>
> >> and IIUC that it's handled as I'd hope (setting "R" on the named
> >> section, not another derived section), good.
> >>
> >> Could you also add a test-case that the same construct
> >> *without* a specific initializer is handled the same way?
> >> I.e.:
> >> int foo __attribute__((__used__, __section__ (".bar")));
> >>
> > Done. The only changes are
> >
> > /* { dg-final { scan-assembler ".data.used_bar_sec,\"awR\"" } } */
> > ...
> > int __attribute__((used,section(".data.used_bar_sec"))) used_bar;
> >
> > and 2 additional tests for -fcommon.
> >
> > Thanks.
> >
> >
> > 0001-Use-SHF_GNU_RETAIN-to-preserve-symbol-definitions.patch
> >
> > From d19f2e2ec7f0f47121a2a4c05ffe20af8972c1bb Mon Sep 17 00:00:00 2001
> > From: "H.J. Lu" <hjl.tools@gmail.com>
> > Date: Mon, 3 Feb 2020 11:55:43 -0800
> > Subject: [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
> >
> > In assemly code, the section flag 'R' sets the SHF_GNU_RETAIN flag to
> > indicate that the section must be preserved by the linker.
> >
> > Add SECTION_RETAIN to indicate a section should be retained by the linker
> > and set SECTION_RETAIN on section for the preserved symbol if assembler
> > supports SHF_GNU_RETAIN. All retained symbols are placed in separate
> > sections with
> >
> > .section .data.rel.local.preserved_symbol,"awR"
> > preserved_symbol:
> > ...
> > .section .data.rel.local,"aw"
> > not_preserved_symbol:
> > ...
> >
> > to avoid
> >
> > .section .data.rel.local,"awR"
> > preserved_symbol:
> > ...
> > not_preserved_symbol:
> > ...
> >
> > which places not_preserved_symbol definition in the SHF_GNU_RETAIN
> > section.
> >
> > gcc/
> >
> > 2020-11-XX H.J. Lu <hjl.tools@gmail.com>
> >
> > * configure.ac (HAVE_GAS_SHF_GNU_RETAIN): New. Define 1 if
> > the assembler supports marking sections with SHF_GNU_RETAIN flag.
> > * output.h (SECTION_RETAIN): New. Defined as 0x4000000.
> > (SECTION_MACH_DEP): Changed from 0x4000000 to 0x8000000.
> > (default_unique_section): Add a bool argument.
> > * varasm.c (get_section): Set SECTION_RETAIN for the preserved
> > symbol with HAVE_GAS_SHF_GNU_RETAIN.
> > (resolve_unique_section): Used named section for the preserved
> > symbol if assembler supports SHF_GNU_RETAIN.
> > (get_variable_section): Handle the preserved common symbol with
> > HAVE_GAS_SHF_GNU_RETAIN.
> > (default_elf_asm_named_section): Require the full declaration and
> > use the 'R' flag for SECTION_RETAIN.
> > * config.in: Regenerated.
> > * configure: Likewise.
> >
> > gcc/testsuite/
> >
> > 2020-11-XX H.J. Lu <hjl.tools@gmail.com>
> > Jozef Lawrynowicz <jozef.l@mittosystems.com>
> >
> > * c-c++-common/attr-used.c: Check the 'R' flag.
> > * c-c++-common/attr-used-2.c: Likewise.
> > * c-c++-common/attr-used-3.c: New test.
> > * c-c++-common/attr-used-4.c: Likewise.
> > * gcc.c-torture/compile/attr-used-retain-1.c: Likewise.
> > * gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
> > * gcc.c-torture/compile/attr-used-retain-3.c: Likewise.
> > * gcc.c-torture/compile/attr-used-retain-4.c: Likewise.
> > * lib/target-supports.exp
> > (check_effective_target_R_flag_in_section): New proc.
> Can we try to avoid the #if stuff, particulary in varasm.c. We worked
> pretty hard to reduce the amount of conditionally compiled code through
> the years and we should try to avoid adding new instances.
>
> HAVE_GAS_SHF_GNU_RETAIN is going to be a compile-time constant, so it
> should be just as efficient to do things like
>
> if (HAVE_GAS_SHF_GNU_RETAIN)
> ... whatever ...
Fixed.
> This has the advantage that the same code is presented to the
> front-ends, so we're at lot less likely to stumble over set-but-not-used
> warnings and the like that were so problematical a few years back. In
> fact, you use that style elsewhere in varasm.c :-)
>
>
> I think you need to document the new effective target check in
> doc/sourcebuild.texi
Fixed.
> With those changes this should be fine.
>
Here is the updated patch. OK for master?
Thanks.
--
H.J.
[-- Attachment #2: 0001-Use-SHF_GNU_RETAIN-to-preserve-symbol-definitions.patch --]
[-- Type: text/x-patch, Size: 16862 bytes --]
From 5b31f3fdc891480da499049869cd5d0e2529ebd0 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 3 Feb 2020 11:55:43 -0800
Subject: [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
In assemly code, the section flag 'R' sets the SHF_GNU_RETAIN flag to
indicate that the section must be preserved by the linker.
Add SECTION_RETAIN to indicate a section should be retained by the linker
and set SECTION_RETAIN on section for the preserved symbol if assembler
supports SHF_GNU_RETAIN. All retained symbols are placed in separate
sections with
.section .data.rel.local.preserved_symbol,"awR"
preserved_symbol:
...
.section .data.rel.local,"aw"
not_preserved_symbol:
...
to avoid
.section .data.rel.local,"awR"
preserved_symbol:
...
not_preserved_symbol:
...
which places not_preserved_symbol definition in the SHF_GNU_RETAIN
section.
gcc/
2020-12-01 H.J. Lu <hjl.tools@gmail.com>
* configure.ac (HAVE_GAS_SHF_GNU_RETAIN): New. Define 1 if
the assembler supports marking sections with SHF_GNU_RETAIN flag.
* output.h (SECTION_RETAIN): New. Defined as 0x4000000.
(SECTION_MACH_DEP): Changed from 0x4000000 to 0x8000000.
(default_unique_section): Add a bool argument.
* varasm.c (get_section): Set SECTION_RETAIN for the preserved
symbol with HAVE_GAS_SHF_GNU_RETAIN.
(resolve_unique_section): Used named section for the preserved
symbol if assembler supports SHF_GNU_RETAIN.
(get_variable_section): Handle the preserved common symbol with
HAVE_GAS_SHF_GNU_RETAIN.
(default_elf_asm_named_section): Require the full declaration and
use the 'R' flag for SECTION_RETAIN.
* config.in: Regenerated.
* configure: Likewise.
* doc/sourcebuild.texi: Document R_flag_in_section.
gcc/testsuite/
2020-12-01 H.J. Lu <hjl.tools@gmail.com>
Jozef Lawrynowicz <jozef.l@mittosystems.com>
* c-c++-common/attr-used.c: Check the 'R' flag.
* c-c++-common/attr-used-2.c: Likewise.
* c-c++-common/attr-used-3.c: New test.
* c-c++-common/attr-used-4.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-1.c: Likewise.
* gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
* lib/target-supports.exp
(check_effective_target_R_flag_in_section): New proc.
---
gcc/config.in | 7 +++
gcc/configure | 51 +++++++++++++++++++
gcc/configure.ac | 20 ++++++++
gcc/doc/sourcebuild.texi | 3 ++
gcc/output.h | 6 ++-
gcc/testsuite/c-c++-common/attr-used-2.c | 1 +
gcc/testsuite/c-c++-common/attr-used-3.c | 7 +++
gcc/testsuite/c-c++-common/attr-used-4.c | 7 +++
gcc/testsuite/c-c++-common/attr-used.c | 1 +
.../compile/attr-used-retain-1.c | 35 +++++++++++++
.../compile/attr-used-retain-2.c | 16 ++++++
gcc/testsuite/lib/target-supports.exp | 40 +++++++++++++++
gcc/varasm.c | 15 ++++--
13 files changed, 205 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/attr-used-3.c
create mode 100644 gcc/testsuite/c-c++-common/attr-used-4.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
create mode 100644 gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
diff --git a/gcc/config.in b/gcc/config.in
index cc6276d0df0..b6e041d311e 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1386,6 +1386,13 @@
#endif
+/* Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN
+ flag. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SHF_GNU_RETAIN
+#endif
+
+
/* Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.
*/
#ifndef USED_FOR_TARGET
diff --git a/gcc/configure b/gcc/configure
index 5206f0d93b2..747822208f2 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -24430,6 +24430,57 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'R' flag" >&5
+$as_echo_n "checking assembler for section 'R' flag... " >&6; }
+if ${gcc_cv_as_shf_gnu_retain+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_shf_gnu_retain=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 36 \) \* 1000 + 0`
+ then gcc_cv_as_shf_gnu_retain=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo '.section .foo,"awR",%progbits
+.byte 0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_shf_gnu_retain=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_shf_gnu_retain" >&5
+$as_echo "$gcc_cv_as_shf_gnu_retain" >&6; }
+
+
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SHF_GNU_RETAIN `if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
$as_echo_n "checking assembler for section merging support... " >&6; }
if ${gcc_cv_as_shf_merge+:} false; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index ded124cb07f..478d0d6f238 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3330,6 +3330,26 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE,
[`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`],
[Define if your assembler supports specifying the exclude section flag.])
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ gcc_GAS_CHECK_FEATURE([section 'R' flag], gcc_cv_as_shf_gnu_retain,
+ [elf,2,36,0], [--fatal-warnings],
+ [.section .foo,"awR",%progbits
+.byte 0])
+ ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_GNU_RETAIN,
+ [`if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN flag.])
+
gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
[elf,2,12,0], [--fatal-warnings],
[.section .rodata.str, "aMS", @progbits, 1])
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 4f7af2074fe..55538c3586b 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2462,6 +2462,9 @@ Target supports wide characters.
@subsubsection Other attributes
@table @code
+@item R_flag_in_section
+Target supports the 'R' flag in .section directive in assembly inputs.
+
@item automatic_stack_alignment
Target supports automatic stack alignment.
diff --git a/gcc/output.h b/gcc/output.h
index b44c1bd6fc7..729c52099e6 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -381,7 +381,11 @@ extern void no_asm_to_stream (FILE *);
#define SECTION_COMMON 0x800000 /* contains common data */
#define SECTION_RELRO 0x1000000 /* data is readonly after relocation processing */
#define SECTION_EXCLUDE 0x2000000 /* discarded by the linker */
-#define SECTION_MACH_DEP 0x4000000 /* subsequent bits reserved for target */
+#define SECTION_RETAIN 0x4000000 /* retained by the linker. */
+
+/* NB: The maximum SECTION_MACH_DEP is 0x10000000 since AVR needs 4 bits
+ in SECTION_MACH_DEP. */
+#define SECTION_MACH_DEP 0x8000000 /* subsequent bits reserved for target */
/* This SECTION_STYLE is used for unnamed sections that we can switch
to using a special assembler directive. */
diff --git a/gcc/testsuite/c-c++-common/attr-used-2.c b/gcc/testsuite/c-c++-common/attr-used-2.c
index f78b94b53a9..eef2519643f 100644
--- a/gcc/testsuite/c-c++-common/attr-used-2.c
+++ b/gcc/testsuite/c-c++-common/attr-used-2.c
@@ -9,3 +9,4 @@ void foo()
}
/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler "\.data.*,\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-3.c b/gcc/testsuite/c-c++-common/attr-used-3.c
new file mode 100644
index 00000000000..ca64197929c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+static int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used-4.c b/gcc/testsuite/c-c++-common/attr-used-4.c
new file mode 100644
index 00000000000..1cbc4c703e9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attr-used-4.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fcommon" } */
+
+int xyzzy __attribute__((__used__));
+
+/* { dg-final { scan-assembler "xyzzy" } } */
+/* { dg-final { scan-assembler ",\"awR\"" { target R_flag_in_section } } } */
diff --git a/gcc/testsuite/c-c++-common/attr-used.c b/gcc/testsuite/c-c++-common/attr-used.c
index ba7705aaa77..2036533c959 100644
--- a/gcc/testsuite/c-c++-common/attr-used.c
+++ b/gcc/testsuite/c-c++-common/attr-used.c
@@ -11,3 +11,4 @@ static void function_declaration_after(void) __attribute__((__used__));
/* { dg-final { scan-assembler "function_declaration_before" } } */
/* { dg-final { scan-assembler "function_declaration_after" } } */
+/* { dg-final { scan-assembler "\.text.*,\"axR\"" { 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
new file mode 100644
index 00000000000..5f6cbca6e33
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.*,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.*,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.*,\"aR\"" } } */
+/* { dg-final { scan-assembler ".data.used_foo_sec,\"awR\"" } } */
+
+void __attribute__((used)) used_fn (void) { }
+void unused_fn (void) { }
+void __attribute__((hot,used)) used_hot_fn (void) { }
+void __attribute__((hot)) unused_hot_fn (void) { }
+void __attribute__((cold,used)) used_cold_fn (void) { }
+void __attribute__((cold)) unused_cold_fn (void) { }
+int __attribute__((used)) used_bss = 0;
+int __attribute__((used)) used_data = 1;
+const int __attribute__((used)) used_rodata = 2;
+int __attribute__((used)) used_comm;
+static int __attribute__((used)) used_lcomm;
+
+int unused_bss = 0;
+int unused_data = 1;
+const int unused_rodata = 2;
+int unused_comm;
+static int unused_lcomm;
+
+/* Test switching back to the retained sections. */
+void __attribute__((used)) used_fn2 (void) { }
+int __attribute__((used)) used_bss2 = 0;
+int __attribute__((used)) used_data2 = 1;
+const int __attribute__((used)) used_rodata2 = 2;
+int __attribute__((used)) used_comm2;
+static int __attribute__((used)) used_lcomm2;
+
+int __attribute__((used,section(".data.used_foo_sec"))) used_foo = 2;
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
new file mode 100644
index 00000000000..be5f3917ac8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/attr-used-retain-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target R_flag_in_section } */
+/* { dg-final { scan-assembler ".text.used_fn,\"axR\"" } } */
+/* { dg-final { scan-assembler ".text.used_fn2,\"axR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss,\"awR\"" } } */
+/* { dg-final { scan-assembler ".bss.used_bss2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data,\"awR\"" } } */
+/* { dg-final { scan-assembler ".data.used_data2,\"awR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata,\"aR\"" } } */
+/* { dg-final { scan-assembler ".rodata.used_rodata2,\"aR\"" } } */
+/* { 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" } */
+
+#include "attr-used-retain-1.c"
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ff6bc5f4b92..9d0a25d77e5 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -10662,3 +10662,43 @@ proc check_effective_target_no_fsanitize_address {} {
}
return 0;
}
+
+# Return 1 if this target supports 'R' flag in .section directive, 0
+# otherwise. Cache the result.
+
+proc check_effective_target_R_flag_in_section { } {
+ global tool
+ global GCC_UNDER_TEST
+
+ # Need auto-host.h to check linker support.
+ if { ![file exists ../../auto-host.h ] } {
+ return 0
+ }
+
+ return [check_cached_effective_target R_flag_in_section {
+
+ set src pie[pid].c
+ set obj pie[pid].o
+
+ set f [open $src "w"]
+ puts $f "#include \"../../auto-host.h\""
+ puts $f "#if HAVE_GAS_SHF_GNU_RETAIN == 0"
+ puts $f "# error Assembler does not support 'R' flag in .section directive."
+ puts $f "#endif"
+ close $f
+
+ verbose "check_effective_target_R_flag_in_section compiling testfile $src" 2
+ set lines [${tool}_target_compile $src $obj assembly ""]
+
+ file delete $src
+ file delete $obj
+
+ if [string match "" $lines] then {
+ verbose "check_effective_target_R_flag_in_section testfile compilation passed" 2
+ return 1
+ } else {
+ verbose "check_effective_target_R_flag_in_section testfile compilation failed" 2
+ return 0
+ }
+ }]
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index b92da26fb82..6c13f528f7b 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -289,6 +289,10 @@ 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 (HAVE_GAS_SHF_GNU_RETAIN
+ && decl != nullptr
+ && DECL_PRESERVE_P (decl))
+ flags |= SECTION_RETAIN;
if (*slot == NULL)
{
sect = ggc_alloc<section> ();
@@ -469,6 +473,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
+ || (HAVE_GAS_SHF_GNU_RETAIN && DECL_PRESERVE_P (decl))
|| DECL_COMDAT_GROUP (decl)))
{
targetm.asm_out.unique_section (decl, reloc);
@@ -1207,7 +1212,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
if (vnode)
vnode->get_constructor ();
- if (DECL_COMMON (decl))
+ if (DECL_COMMON (decl)
+ && !(HAVE_GAS_SHF_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
@@ -6745,9 +6751,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
/* If we have already declared this section, we can use an
abbreviated form to switch back to it -- unless this section is
- part of a COMDAT groups, in which case GAS requires the full
- declaration every time. */
+ part of a COMDAT groups or with SHF_GNU_RETAIN, in which case GAS
+ requires the full declaration every time. */
if (!(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
+ && !(flags & SECTION_RETAIN)
&& (flags & SECTION_DECLARED))
{
fprintf (asm_out_file, "\t.section\t%s\n", name);
@@ -6780,6 +6787,8 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
*f++ = TLS_SECTION_ASM_FLAG;
if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
*f++ = 'G';
+ if (flags & SECTION_RETAIN)
+ *f++ = 'R';
#ifdef MACH_DEP_SECTION_ASM_FLAG
if (flags & SECTION_MACH_DEP)
*f++ = MACH_DEP_SECTION_ASM_FLAG;
--
2.28.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V3 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-12-02 0:36 ` V3 " H.J. Lu
@ 2020-12-02 0:38 ` Jeff Law
2020-12-02 21:31 ` Joseph Myers
0 siblings, 1 reply; 11+ messages in thread
From: Jeff Law @ 2020-12-02 0:38 UTC (permalink / raw)
To: H.J. Lu; +Cc: Hans-Peter Nilsson, GCC Patches
On 12/1/20 5:36 PM, H.J. Lu wrote:
> On Tue, Dec 1, 2020 at 4:04 PM Jeff Law <law@redhat.com> wrote:
>>
>>
>> On 11/17/20 6:20 AM, H.J. Lu via Gcc-patches wrote:
>>> On Mon, Nov 16, 2020 at 7:59 PM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>>>> On Fri, 13 Nov 2020, H.J. Lu via Gcc-patches wrote:
>>>>> Done. Here is the updated patch.
>>>> Hi. I see a test-case for this kind of construct:
>>>>
>>>> int foo __attribute__((__used__, __section__ (".bar"))) = 42;
>>>>
>>>> and IIUC that it's handled as I'd hope (setting "R" on the named
>>>> section, not another derived section), good.
>>>>
>>>> Could you also add a test-case that the same construct
>>>> *without* a specific initializer is handled the same way?
>>>> I.e.:
>>>> int foo __attribute__((__used__, __section__ (".bar")));
>>>>
>>> Done. The only changes are
>>>
>>> /* { dg-final { scan-assembler ".data.used_bar_sec,\"awR\"" } } */
>>> ...
>>> int __attribute__((used,section(".data.used_bar_sec"))) used_bar;
>>>
>>> and 2 additional tests for -fcommon.
>>>
>>> Thanks.
>>>
>>>
>>> 0001-Use-SHF_GNU_RETAIN-to-preserve-symbol-definitions.patch
>>>
>>> From d19f2e2ec7f0f47121a2a4c05ffe20af8972c1bb Mon Sep 17 00:00:00 2001
>>> From: "H.J. Lu" <hjl.tools@gmail.com>
>>> Date: Mon, 3 Feb 2020 11:55:43 -0800
>>> Subject: [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
>>>
>>> In assemly code, the section flag 'R' sets the SHF_GNU_RETAIN flag to
>>> indicate that the section must be preserved by the linker.
>>>
>>> Add SECTION_RETAIN to indicate a section should be retained by the linker
>>> and set SECTION_RETAIN on section for the preserved symbol if assembler
>>> supports SHF_GNU_RETAIN. All retained symbols are placed in separate
>>> sections with
>>>
>>> .section .data.rel.local.preserved_symbol,"awR"
>>> preserved_symbol:
>>> ...
>>> .section .data.rel.local,"aw"
>>> not_preserved_symbol:
>>> ...
>>>
>>> to avoid
>>>
>>> .section .data.rel.local,"awR"
>>> preserved_symbol:
>>> ...
>>> not_preserved_symbol:
>>> ...
>>>
>>> which places not_preserved_symbol definition in the SHF_GNU_RETAIN
>>> section.
>>>
>>> gcc/
>>>
>>> 2020-11-XX H.J. Lu <hjl.tools@gmail.com>
>>>
>>> * configure.ac (HAVE_GAS_SHF_GNU_RETAIN): New. Define 1 if
>>> the assembler supports marking sections with SHF_GNU_RETAIN flag.
>>> * output.h (SECTION_RETAIN): New. Defined as 0x4000000.
>>> (SECTION_MACH_DEP): Changed from 0x4000000 to 0x8000000.
>>> (default_unique_section): Add a bool argument.
>>> * varasm.c (get_section): Set SECTION_RETAIN for the preserved
>>> symbol with HAVE_GAS_SHF_GNU_RETAIN.
>>> (resolve_unique_section): Used named section for the preserved
>>> symbol if assembler supports SHF_GNU_RETAIN.
>>> (get_variable_section): Handle the preserved common symbol with
>>> HAVE_GAS_SHF_GNU_RETAIN.
>>> (default_elf_asm_named_section): Require the full declaration and
>>> use the 'R' flag for SECTION_RETAIN.
>>> * config.in: Regenerated.
>>> * configure: Likewise.
>>>
>>> gcc/testsuite/
>>>
>>> 2020-11-XX H.J. Lu <hjl.tools@gmail.com>
>>> Jozef Lawrynowicz <jozef.l@mittosystems.com>
>>>
>>> * c-c++-common/attr-used.c: Check the 'R' flag.
>>> * c-c++-common/attr-used-2.c: Likewise.
>>> * c-c++-common/attr-used-3.c: New test.
>>> * c-c++-common/attr-used-4.c: Likewise.
>>> * gcc.c-torture/compile/attr-used-retain-1.c: Likewise.
>>> * gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
>>> * gcc.c-torture/compile/attr-used-retain-3.c: Likewise.
>>> * gcc.c-torture/compile/attr-used-retain-4.c: Likewise.
>>> * lib/target-supports.exp
>>> (check_effective_target_R_flag_in_section): New proc.
>> Can we try to avoid the #if stuff, particulary in varasm.c. We worked
>> pretty hard to reduce the amount of conditionally compiled code through
>> the years and we should try to avoid adding new instances.
>>
>> HAVE_GAS_SHF_GNU_RETAIN is going to be a compile-time constant, so it
>> should be just as efficient to do things like
>>
>> if (HAVE_GAS_SHF_GNU_RETAIN)
>> ... whatever ...
> Fixed.
>
>> This has the advantage that the same code is presented to the
>> front-ends, so we're at lot less likely to stumble over set-but-not-used
>> warnings and the like that were so problematical a few years back. In
>> fact, you use that style elsewhere in varasm.c :-)
>>
>>
>> I think you need to document the new effective target check in
>> doc/sourcebuild.texi
> Fixed.
>
>> With those changes this should be fine.
>>
> Here is the updated patch. OK for master?
>
> Thanks.
>
>
> 0001-Use-SHF_GNU_RETAIN-to-preserve-symbol-definitions.patch
>
> From 5b31f3fdc891480da499049869cd5d0e2529ebd0 Mon Sep 17 00:00:00 2001
> From: "H.J. Lu" <hjl.tools@gmail.com>
> Date: Mon, 3 Feb 2020 11:55:43 -0800
> Subject: [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
>
> In assemly code, the section flag 'R' sets the SHF_GNU_RETAIN flag to
> indicate that the section must be preserved by the linker.
>
> Add SECTION_RETAIN to indicate a section should be retained by the linker
> and set SECTION_RETAIN on section for the preserved symbol if assembler
> supports SHF_GNU_RETAIN. All retained symbols are placed in separate
> sections with
>
> .section .data.rel.local.preserved_symbol,"awR"
> preserved_symbol:
> ...
> .section .data.rel.local,"aw"
> not_preserved_symbol:
> ...
>
> to avoid
>
> .section .data.rel.local,"awR"
> preserved_symbol:
> ...
> not_preserved_symbol:
> ...
>
> which places not_preserved_symbol definition in the SHF_GNU_RETAIN
> section.
>
> gcc/
>
> 2020-12-01 H.J. Lu <hjl.tools@gmail.com>
>
> * configure.ac (HAVE_GAS_SHF_GNU_RETAIN): New. Define 1 if
> the assembler supports marking sections with SHF_GNU_RETAIN flag.
> * output.h (SECTION_RETAIN): New. Defined as 0x4000000.
> (SECTION_MACH_DEP): Changed from 0x4000000 to 0x8000000.
> (default_unique_section): Add a bool argument.
> * varasm.c (get_section): Set SECTION_RETAIN for the preserved
> symbol with HAVE_GAS_SHF_GNU_RETAIN.
> (resolve_unique_section): Used named section for the preserved
> symbol if assembler supports SHF_GNU_RETAIN.
> (get_variable_section): Handle the preserved common symbol with
> HAVE_GAS_SHF_GNU_RETAIN.
> (default_elf_asm_named_section): Require the full declaration and
> use the 'R' flag for SECTION_RETAIN.
> * config.in: Regenerated.
> * configure: Likewise.
> * doc/sourcebuild.texi: Document R_flag_in_section.
>
> gcc/testsuite/
>
> 2020-12-01 H.J. Lu <hjl.tools@gmail.com>
> Jozef Lawrynowicz <jozef.l@mittosystems.com>
>
> * c-c++-common/attr-used.c: Check the 'R' flag.
> * c-c++-common/attr-used-2.c: Likewise.
> * c-c++-common/attr-used-3.c: New test.
> * c-c++-common/attr-used-4.c: Likewise.
> * gcc.c-torture/compile/attr-used-retain-1.c: Likewise.
> * gcc.c-torture/compile/attr-used-retain-2.c: Likewise.
> * lib/target-supports.exp
> (check_effective_target_R_flag_in_section): New proc.
OK
jeff
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V3 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-12-02 0:38 ` Jeff Law
@ 2020-12-02 21:31 ` Joseph Myers
2020-12-02 21:49 ` H.J. Lu
0 siblings, 1 reply; 11+ messages in thread
From: Joseph Myers @ 2020-12-02 21:31 UTC (permalink / raw)
To: Jeff Law; +Cc: H.J. Lu, GCC Patches, libc-alpha
This patch (GCC commit 6fbec038f7a7ddf29f074943611b53210d17c40c) has
broken the glibc build (at least with current binutils master). The
errors are of the form:
In file included from <command-line>:
gconv_dl.c: In function 'free_mem':
gconv_dl.c:202:18: error: 'free_mem' causes a section type conflict with 'do_release_all'
202 | libc_freeres_fn (free_mem)
| ^~~~~~~~
./../include/libc-symbols.h:316:15: note: in definition of macro 'libc_freeres_fn'
316 | static void name (void)
| ^~~~
gconv_dl.c:191:1: note: 'do_release_all' was declared here
191 | do_release_all (void *nodep)
| ^~~~~~~~~~~~~~
Not sure if this is a GCC bug or indicates that glibc's libc_freeres_fn or
related macros need to change to work with both old and new GCC.
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V3 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-12-02 21:31 ` Joseph Myers
@ 2020-12-02 21:49 ` H.J. Lu
2020-12-02 21:55 ` Joseph Myers
0 siblings, 1 reply; 11+ messages in thread
From: H.J. Lu @ 2020-12-02 21:49 UTC (permalink / raw)
To: Joseph Myers; +Cc: Jeff Law, GCC Patches, GNU C Library
On Wed, Dec 2, 2020 at 1:31 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> This patch (GCC commit 6fbec038f7a7ddf29f074943611b53210d17c40c) has
> broken the glibc build (at least with current binutils master). The
> errors are of the form:
>
> In file included from <command-line>:
> gconv_dl.c: In function 'free_mem':
> gconv_dl.c:202:18: error: 'free_mem' causes a section type conflict with 'do_release_all'
> 202 | libc_freeres_fn (free_mem)
> | ^~~~~~~~
> ./../include/libc-symbols.h:316:15: note: in definition of macro 'libc_freeres_fn'
> 316 | static void name (void)
> | ^~~~
> gconv_dl.c:191:1: note: 'do_release_all' was declared here
> 191 | do_release_all (void *nodep)
> | ^~~~~~~~~~~~~~
>
> Not sure if this is a GCC bug or indicates that glibc's libc_freeres_fn or
> related macros need to change to work with both old and new GCC.
We may need to update glibc for GCC 11. Can you open a glibc bug and
CC me?
Thanks.
--
H.J.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V3 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions
2020-12-02 21:49 ` H.J. Lu
@ 2020-12-02 21:55 ` Joseph Myers
0 siblings, 0 replies; 11+ messages in thread
From: Joseph Myers @ 2020-12-02 21:55 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, GCC Patches
On Wed, 2 Dec 2020, H.J. Lu via Gcc-patches wrote:
> > Not sure if this is a GCC bug or indicates that glibc's libc_freeres_fn or
> > related macros need to change to work with both old and new GCC.
>
> We may need to update glibc for GCC 11. Can you open a glibc bug and
> CC me?
https://sourceware.org/bugzilla/show_bug.cgi?id=27002
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2020-12-02 21:55 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-12 22:41 [PATCH] Use SHF_GNU_RETAIN to preserve symbol definitions H.J. Lu
2020-11-13 11:36 ` Jozef Lawrynowicz
2020-11-13 13:45 ` V2 " H.J. Lu
2020-11-17 3:59 ` Hans-Peter Nilsson
2020-11-17 13:20 ` H.J. Lu
2020-12-02 0:04 ` Jeff Law
2020-12-02 0:36 ` V3 " H.J. Lu
2020-12-02 0:38 ` Jeff Law
2020-12-02 21:31 ` Joseph Myers
2020-12-02 21:49 ` H.J. Lu
2020-12-02 21:55 ` Joseph Myers
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).