290 lines
11 KiB
Diff
290 lines
11 KiB
Diff
2011-01-27 Jakub Jelinek <jakub@redhat.com>
|
|
|
|
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 <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.
|
|
|
|
--- 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";
|