OSDN Git Service

PR middle-end/31490
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 Feb 2011 19:12:07 +0000 (19:12 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 Feb 2011 19:12:07 +0000 (19:12 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@169804 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cgraph.h
gcc/cgraphunit.c
gcc/output.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr31490-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr31490-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr31490-4.c [new file with mode: 0644]
gcc/varasm.c
gcc/varpool.c

index 759227d..59f7a45 100644 (file)
@@ -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.
index 2df3fa5..de376ac 100644 (file)
@@ -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);
index f6fe272..fdff7e3 100644 (file)
@@ -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)
        {
index 39225a3..c668d35 100644 (file)
@@ -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);
index 5adb4a3..e32c521 100644 (file)
@@ -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 (file)
index 0000000..2449ac4
--- /dev/null
@@ -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 (file)
index 0000000..e7ccc67
--- /dev/null
@@ -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 (file)
index 0000000..cbfc687
--- /dev/null
@@ -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";
index a1cddac..3a9fbae 100644 (file)
@@ -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 *
index 2e37255..5d0eb68 100644 (file)
@@ -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;