From 7fece97913380e58d310e5dcda45aec909eed696 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 3 Feb 2011 20:12:07 +0100 Subject: re PR middle-end/31490 (Compile error section type conflict) PR middle-end/31490 * output.h (SECTION_RELRO): Define. (SECTION_MACH_DEP): Adjust. (get_variable_section): New prototype. * 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. From-SVN: r169804 --- gcc/ChangeLog | 28 ++++++++++++++++++ gcc/cgraph.h | 3 +- gcc/cgraphunit.c | 4 +++ gcc/output.h | 6 ++-- gcc/testsuite/ChangeLog | 7 +++++ gcc/testsuite/gcc.dg/pr31490-2.c | 7 +++++ gcc/testsuite/gcc.dg/pr31490-3.c | 7 +++++ gcc/testsuite/gcc.dg/pr31490-4.c | 10 +++++++ gcc/varasm.c | 61 ++++++++++++++++++++++++++++++---------- gcc/varpool.c | 21 ++++++++++++++ 10 files changed, 136 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr31490-2.c create mode 100644 gcc/testsuite/gcc.dg/pr31490-3.c create mode 100644 gcc/testsuite/gcc.dg/pr31490-4.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 759227d..59f7a45 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,33 @@ 2011-02-03 Jakub Jelinek + PR middle-end/31490 + * output.h (SECTION_RELRO): Define. + (SECTION_MACH_DEP): Adjust. + (get_variable_section): New prototype. + * 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. + +2011-02-03 Jakub Jelinek + * config/darwin.h (SECTION_NO_ANCHOR): Remove. * config/darwin.c (SECTION_NO_ANCHOR): Define. (darwin_init_sections): Remove assertion. diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 2df3fa5..de376ac 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1,5 +1,5 @@ /* Callgraph handling code. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Jan Hubicka @@ -720,6 +720,7 @@ bool cgraph_node_can_be_local_p (struct cgraph_node *); 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); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index f6fe2724..fdff7e39 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1715,6 +1715,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) { diff --git a/gcc/output.h b/gcc/output.h index 39225a3a..c668d35 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -1,7 +1,7 @@ /* Declarations for insn-output.c. These functions are defined in recog.c, final.c, and varasm.c. Copyright (C) 1987, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -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 (unsigned int, void (*) (const void *), 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5adb4a3..e32c521 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-02-03 Jakub Jelinek + + PR middle-end/31490 + * gcc.dg/pr31490-2.c: New test. + * gcc.dg/pr31490-3.c: New test. + * gcc.dg/pr31490-4.c: New test. + 2011-02-03 Nathan Froyd Jakub Jelinek diff --git a/gcc/testsuite/gcc.dg/pr31490-2.c b/gcc/testsuite/gcc.dg/pr31490-2.c new file mode 100644 index 0000000..2449ac4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr31490-2.c @@ -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; diff --git a/gcc/testsuite/gcc.dg/pr31490-3.c b/gcc/testsuite/gcc.dg/pr31490-3.c new file mode 100644 index 0000000..e7ccc67 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr31490-3.c @@ -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"; diff --git a/gcc/testsuite/gcc.dg/pr31490-4.c b/gcc/testsuite/gcc.dg/pr31490-4.c new file mode 100644 index 0000000..cbfc687 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr31490-4.c @@ -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"; 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 * diff --git a/gcc/varpool.c b/gcc/varpool.c index 2e37255..5d0eb68 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -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; -- cgit v1.1