diff options
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r-- | gcc/varasm.c | 61 |
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 * |