2011-01-27 Jakub Jelinek PR middle-end/31490 * output.h (SECTION_RELRO): Define. (SECTION_MACH_DEP): Adjust. (get_variable_section): New prototype. * config/darwin.h (SECTION_NO_ANCHOR): Adjust. * varpool.c (varpool_finalize_named_section_flags): New function. (varpool_assemble_pending_decls): Call it. * cgraph.h (varpool_finalize_named_section_flags): New prototype. * cgraphunit.c (cgraph_output_in_order): Call varpool_finalize_named_section_flags. * varasm.c (get_section): Allow section flags conflicts between relro and read-only sections if the section hasn't been declared yet. Set SECTION_OVERRIDE after diagnosing section type conflict. (get_variable_section): No longer static. (default_section_type_flags): Use SECTION_WRITE | SECTION_RELRO for readonly sections that need relocations. (decl_readonly_section_1): New function. (decl_readonly_section): Use it. Revert: 2010-11-17 Dinar Temirbulatov Steve Ellcey PR middle-end/31490 * varasm.c (categorize_decl_for_section): Ignore reloc_rw_mask if section attribute used. * gcc.dg/pr31490-2.c: New test. * gcc.dg/pr31490-3.c: New test. * gcc.dg/pr31490-4.c: New test. --- gcc/output.h.jj 2011-01-27 17:33:28.200496345 +0100 +++ gcc/output.h 2011-01-27 17:40:33.355649071 +0100 @@ -441,7 +441,8 @@ extern void no_asm_to_stream (FILE *); #define SECTION_DECLARED 0x100000 /* section has been used */ #define SECTION_STYLE_MASK 0x600000 /* bits used for SECTION_STYLE */ #define SECTION_COMMON 0x800000 /* contains common data */ -#define SECTION_MACH_DEP 0x1000000 /* subsequent bits reserved for target */ +#define SECTION_RELRO 0x1000000 /* data is readonly after relocation processing */ +#define SECTION_MACH_DEP 0x2000000 /* subsequent bits reserved for target */ /* This SECTION_STYLE is used for unnamed sections that we can switch to using a special assembler directive. */ @@ -585,6 +586,7 @@ extern section *get_unnamed_section (uns const void *); extern section *get_section (const char *, unsigned int, tree); extern section *get_named_section (tree, const char *, int); +extern section *get_variable_section (tree, bool); extern void place_block_symbol (rtx); extern rtx get_section_anchor (struct object_block *, HOST_WIDE_INT, enum tls_model); --- gcc/varpool.c.jj 2011-01-27 17:33:28.229830104 +0100 +++ gcc/varpool.c 2011-01-27 19:48:24.567639053 +0100 @@ -565,11 +565,29 @@ varpool_remove_unreferenced_decls (void) varpool_analyze_pending_decls (); } +/* For variables in named sections make sure get_variable_section + is called before we switch to those sections. Then section + conflicts between read-only and read-only requiring relocations + sections can be resolved. */ +void +varpool_finalize_named_section_flags (struct varpool_node *node) +{ + if (!TREE_ASM_WRITTEN (node->decl) + && !node->alias + && !node->in_other_partition + && !DECL_EXTERNAL (node->decl) + && TREE_CODE (node->decl) == VAR_DECL + && !DECL_HAS_VALUE_EXPR_P (node->decl) + && DECL_SECTION_NAME (node->decl)) + get_variable_section (node->decl, false); +} + /* Output all variables enqueued to be assembled. */ bool varpool_assemble_pending_decls (void) { bool changed = false; + struct varpool_node *node; if (seen_error ()) return false; @@ -580,6 +598,9 @@ varpool_assemble_pending_decls (void) elsewhere. */ varpool_analyze_pending_decls (); + for (node = varpool_nodes_queue; node; node = node->next_needed) + varpool_finalize_named_section_flags (node); + while (varpool_nodes_queue) { struct varpool_node *node = varpool_nodes_queue; --- gcc/config/darwin.h.jj 2011-01-27 17:33:28.217391021 +0100 +++ gcc/config/darwin.h 2011-01-27 17:40:33.356655497 +0100 @@ -654,7 +654,7 @@ int darwin_label_is_anonymous_local_objc /* Private flag applied to disable section-anchors in a particular section. This needs to be kept in sync with the flags used by varasm.c (defined in output.h). */ -#define SECTION_NO_ANCHOR 0x2000000 +#define SECTION_NO_ANCHOR 0x4000000 /* Declare the section variables. */ #ifndef USED_FOR_TARGET --- gcc/cgraph.h.jj 2011-01-27 17:33:28.011433405 +0100 +++ gcc/cgraph.h 2011-01-27 17:33:28.011433405 +0100 @@ -720,6 +720,7 @@ bool cgraph_node_can_be_local_p (struct struct varpool_node * varpool_get_node (const_tree decl); void varpool_remove_node (struct varpool_node *node); +void varpool_finalize_named_section_flags (struct varpool_node *node); bool varpool_assemble_pending_decls (void); bool varpool_assemble_decl (struct varpool_node *node); bool varpool_analyze_pending_decls (void); --- gcc/varasm.c.jj 2011-01-27 17:40:25.196565130 +0100 +++ gcc/varasm.c 2011-01-27 17:40:33.361429176 +0100 @@ -119,6 +119,7 @@ static void output_addressed_constants ( 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 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_out 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, c 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 /* 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 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, 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 * --- gcc/cgraphunit.c.jj 2011-01-27 17:33:29.416940770 +0100 +++ gcc/cgraphunit.c 2011-01-27 19:48:24.567639053 +0100 @@ -1708,6 +1708,10 @@ cgraph_output_in_order (void) varpool_empty_needed_queue (); for (i = 0; i < max; ++i) + if (nodes[i].kind == ORDER_VAR) + varpool_finalize_named_section_flags (nodes[i].u.v); + + for (i = 0; i < max; ++i) { switch (nodes[i].kind) { --- gcc/testsuite/gcc.dg/pr31490-2.c.jj 2011-01-27 17:40:33.365546146 +0100 +++ gcc/testsuite/gcc.dg/pr31490-2.c 2011-01-27 17:40:33.365546146 +0100 @@ -0,0 +1,7 @@ +/* PR middle-end/31490 */ +/* { dg-do compile } */ +/* { dg-options "-fpic" { target fpic } } */ +/* { dg-require-named-sections "" } */ + +const char *const x __attribute__((section("foo"))) = ""; +const char *const g __attribute__((section("foo"))) = (const char *) 0; --- gcc/testsuite/gcc.dg/pr31490-3.c.jj 2011-01-27 17:40:33.365546146 +0100 +++ gcc/testsuite/gcc.dg/pr31490-3.c 2011-01-27 17:40:33.365546146 +0100 @@ -0,0 +1,7 @@ +/* PR middle-end/31490 */ +/* { dg-do compile } */ +/* { dg-options "-fpic" { target fpic } } */ +/* { dg-require-named-sections "" } */ + +const char *const x __attribute__((section("foo"))) = (const char *) 0; +const char *const g __attribute__((section("foo"))) = "bar"; --- gcc/testsuite/gcc.dg/pr31490-4.c.jj 2011-01-27 17:40:33.366545270 +0100 +++ gcc/testsuite/gcc.dg/pr31490-4.c 2011-01-27 17:40:33.366545270 +0100 @@ -0,0 +1,10 @@ +/* PR middle-end/31490 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-options "-O2 -fpic" { target fpic } } */ +/* { dg-require-named-sections "" } */ + +const char *const x __attribute__((section("foo"))) = ""; +const char *const g __attribute__((section("foo"))) = (const char *) 0; +const char *const y __attribute__((section("bar"))) = (const char *) 0; +const char *const h __attribute__((section("bar"))) = "bar";