aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2011-02-03 20:12:07 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2011-02-03 20:12:07 +0100
commit7fece97913380e58d310e5dcda45aec909eed696 (patch)
treed84c6553f07cd91230768e24b2d35f690b8488db
parentd18d5478621cac97cf938e412883f2eb34f351cc (diff)
downloadgcc-7fece97913380e58d310e5dcda45aec909eed696.zip
gcc-7fece97913380e58d310e5dcda45aec909eed696.tar.gz
gcc-7fece97913380e58d310e5dcda45aec909eed696.tar.bz2
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 <dtemirbulatov@gmail.com> Steve Ellcey <sje@cup.hp.com> 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
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/cgraph.h3
-rw-r--r--gcc/cgraphunit.c4
-rw-r--r--gcc/output.h6
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/pr31490-2.c7
-rw-r--r--gcc/testsuite/gcc.dg/pr31490-3.c7
-rw-r--r--gcc/testsuite/gcc.dg/pr31490-4.c10
-rw-r--r--gcc/varasm.c61
-rw-r--r--gcc/varpool.c21
10 files changed, 136 insertions, 18 deletions
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 <jakub@redhat.com>
+ 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 <dtemirbulatov@gmail.com>
+ Steve Ellcey <sje@cup.hp.com>
+
+ PR middle-end/31490
+ * varasm.c (categorize_decl_for_section): Ignore reloc_rw_mask
+ if section attribute used.
+
+2011-02-03 Jakub Jelinek <jakub@redhat.com>
+
* 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 <jakub@redhat.com>
+
+ 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 <froydnj@codesourcery.com>
Jakub Jelinek <jakub@redhat.com>
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;