aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c61
1 files changed, 46 insertions, 15 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index a1cddac..3a9fbae 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -119,6 +119,7 @@ static void output_addressed_constants (tree);
static unsigned HOST_WIDE_INT array_size_for_constructor (tree);
static unsigned min_align (unsigned, unsigned);
static void globalize_decl (tree);
+static bool decl_readonly_section_1 (enum section_category);
#ifdef BSS_SECTION_ASM_OP
#ifdef ASM_OUTPUT_BSS
static void asm_output_bss (FILE *, tree, const char *,
@@ -294,11 +295,31 @@ get_section (const char *name, unsigned int flags, tree decl)
if ((sect->common.flags & ~SECTION_DECLARED) != flags
&& ((sect->common.flags | flags) & SECTION_OVERRIDE) == 0)
{
+ /* It is fine if one of the section flags is
+ SECTION_WRITE | SECTION_RELRO and the other has none of these
+ flags (i.e. read-only) in named sections and either the
+ section hasn't been declared yet or has been declared as writable.
+ In that case just make sure the resulting flags are
+ SECTION_WRITE | SECTION_RELRO, ie. writable only because of
+ relocations. */
+ if (((sect->common.flags ^ flags) & (SECTION_WRITE | SECTION_RELRO))
+ == (SECTION_WRITE | SECTION_RELRO)
+ && (sect->common.flags
+ & ~(SECTION_DECLARED | SECTION_WRITE | SECTION_RELRO))
+ == (flags & ~(SECTION_WRITE | SECTION_RELRO))
+ && ((sect->common.flags & SECTION_DECLARED) == 0
+ || (sect->common.flags & SECTION_WRITE)))
+ {
+ sect->common.flags |= (SECTION_WRITE | SECTION_RELRO);
+ return sect;
+ }
/* Sanity check user variables for flag changes. */
if (decl == 0)
decl = sect->named.decl;
gcc_assert (decl);
error ("%+D causes a section type conflict", decl);
+ /* Make sure we don't error about one section multiple times. */
+ sect->common.flags |= SECTION_OVERRIDE;
}
}
return sect;
@@ -985,7 +1006,7 @@ align_variable (tree decl, bool dont_output_data)
should be placed. PREFER_NOSWITCH_P is true if a noswitch
section should be used wherever possible. */
-static section *
+section *
get_variable_section (tree decl, bool prefer_noswitch_p)
{
addr_space_t as = ADDR_SPACE_GENERIC;
@@ -6026,8 +6047,18 @@ default_section_type_flags (tree decl, const char *name, int reloc)
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
flags = SECTION_CODE;
- else if (decl && decl_readonly_section (decl, reloc))
- flags = 0;
+ else if (decl)
+ {
+ enum section_category category
+ = categorize_decl_for_section (decl, reloc);
+ if (decl_readonly_section_1 (category))
+ flags = 0;
+ else if (category == SECCAT_DATA_REL_RO
+ || category == SECCAT_DATA_REL_RO_LOCAL)
+ flags = SECTION_WRITE | SECTION_RELRO;
+ else
+ flags = SECTION_WRITE;
+ }
else
flags = SECTION_WRITE;
@@ -6250,17 +6281,13 @@ categorize_decl_for_section (const_tree decl, int reloc)
/* Here the reloc_rw_mask is not testing whether the section should
be read-only or not, but whether the dynamic link will have to
do something. If so, we wish to segregate the data in order to
- minimize cache misses inside the dynamic linker. If the data
- has a section attribute, ignore reloc_rw_mask() so that all data
- in a given named section is catagorized in the same way. */
- if (reloc & targetm.asm_out.reloc_rw_mask ()
- && !lookup_attribute ("section", DECL_ATTRIBUTES (decl)))
+ minimize cache misses inside the dynamic linker. */
+ if (reloc & targetm.asm_out.reloc_rw_mask ())
ret = reloc == 1 ? SECCAT_DATA_REL_LOCAL : SECCAT_DATA_REL;
else
ret = SECCAT_DATA;
}
- else if (reloc & targetm.asm_out.reloc_rw_mask ()
- && !lookup_attribute ("section", DECL_ATTRIBUTES (decl)))
+ else if (reloc & targetm.asm_out.reloc_rw_mask ())
ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO;
else if (reloc || flag_merge_constants < 2)
/* C and C++ don't allow different variables to share the same
@@ -6311,10 +6338,10 @@ categorize_decl_for_section (const_tree decl, int reloc)
return ret;
}
-bool
-decl_readonly_section (const_tree decl, int reloc)
+static bool
+decl_readonly_section_1 (enum section_category category)
{
- switch (categorize_decl_for_section (decl, reloc))
+ switch (category)
{
case SECCAT_RODATA:
case SECCAT_RODATA_MERGE_STR:
@@ -6322,13 +6349,17 @@ decl_readonly_section (const_tree decl, int reloc)
case SECCAT_RODATA_MERGE_CONST:
case SECCAT_SRODATA:
return true;
- break;
default:
return false;
- break;
}
}
+bool
+decl_readonly_section (const_tree decl, int reloc)
+{
+ return decl_readonly_section_1 (categorize_decl_for_section (decl, reloc));
+}
+
/* Select a section based on the above categorization. */
section *