aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-02-03 11:55:43 -0800
committerH.J. Lu <hjl.tools@gmail.com>2020-12-01 16:42:50 -0800
commit6fbec038f7a7ddf29f074943611b53210d17c40c (patch)
tree17b1d7fb7010085b8d79deab1e4a07edf51ddf9b /gcc/varasm.c
parent670f5095e4aacc30099f6b73c1e67c06df76f36b (diff)
downloadgcc-6fbec038f7a7ddf29f074943611b53210d17c40c.zip
gcc-6fbec038f7a7ddf29f074943611b53210d17c40c.tar.gz
gcc-6fbec038f7a7ddf29f074943611b53210d17c40c.tar.bz2
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.
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index b92da26..6c13f52 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;