Properly handle uninitialized common symbol
authorH.J. Lu <hongjiu.lu@intel.com>
Fri, 17 Apr 2015 16:23:24 +0000 (16:23 +0000)
committerH.J. Lu <hjl@gcc.gnu.org>
Fri, 17 Apr 2015 16:23:24 +0000 (09:23 -0700)
Uninitialized common symbol behavior in executables is target and linker
dependent.  default_binds_local_p_3 is made public and updated to take an
argument to indicate if the linker can guarantee that an uninitialized
common symbol in the executable will still be defined (through COPY
relocation) in the executable.  If common symbol is local to executable,
default_binds_local_p_3 will treat non-external variable as defined
locally.  default_binds_local_p_2 is changed to treat common symbol as
local for non-PIE binaries.

For i386, common symbol is local only for non-PIE binaries.  For x86-64,
common symbol is local only for non-PIE binaries or linker supports copy
reloc in PIE binaries.  If a target treats common symbol as local only
for non-PIE binaries, it can define TARGET_BINDS_LOCAL_P as
default_binds_local_p_2.

gcc/

PR target/65780
* output.h (default_binds_local_p_3): New.
* varasm.c (default_binds_local_p_3): Make it public.  Take an
argument to indicate if common symbol may be local.  If common
symbol may be local, treat non-external variable as defined
locally.
(default_binds_local_p_2): Pass !flag_pic to default_binds_local_p_3.
(default_binds_local_p_1): Pass false to default_binds_local_p_3.
* config/i386/i386.c (ix86_binds_local_p): New.
(TARGET_BINDS_LOCAL_P): Replace default_binds_local_p_2 with
ix86_binds_local_p.

gcc/testsuite/

PR target/65780
* gcc.dg/pr65780-1.c: New test.
* gcc.dg/pr65780-2.c: Likewise.
* gcc.target/i386/pr32219-9.c: Likewise.
* gcc.target/i386/pr32219-1.c (xxx): Make it initialized common
symbol.
* gcc.target/i386/pr64317.c (c): Initialize.

From-SVN: r222184

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/output.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr65780-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr65780-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr32219-1.c
gcc/testsuite/gcc.target/i386/pr32219-9.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr64317.c
gcc/varasm.c

index 008e36ab5ee8537312fd8b82c21c43fb93b41ead..71c692e91a038c733c5ceeded8229fa944acc516 100644 (file)
@@ -1,3 +1,17 @@
+2015-04-17  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/65780
+       * output.h (default_binds_local_p_3): New.
+       * varasm.c (default_binds_local_p_3): Make it public.  Take an
+       argument to indicate if common symbol may be local.  If common
+       symbol may be local, treat non-external variable as defined
+       locally.
+       (default_binds_local_p_2): Pass !flag_pic to default_binds_local_p_3.
+       (default_binds_local_p_1): Pass false to default_binds_local_p_3.
+       * config/i386/i386.c (ix86_binds_local_p): New.
+       (TARGET_BINDS_LOCAL_P): Replace default_binds_local_p_2 with
+       ix86_binds_local_p.
+
 2015-04-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR debug/65771
index 1f20ff394c83be989a8acd1aecb7df1221340476..72e6bc27f6219a596822f5d93fe6827b0f8b08d3 100644 (file)
@@ -51793,6 +51793,19 @@ ix86_initialize_bounds (tree var, tree lb, tree ub, tree *stmts)
   return 2;
 }
 
+/* For i386, common symbol is local only for non-PIE binaries.  For
+   x86-64, common symbol is local only for non-PIE binaries or linker
+   supports copy reloc in PIE binaries.   */
+
+static bool
+ix86_binds_local_p (const_tree exp)
+{
+  return default_binds_local_p_3 (exp, flag_shlib != 0, true, true,
+                                 (!flag_pic
+                                  || (TARGET_64BIT
+                                      && HAVE_LD_PIE_COPYRELOC != 0)));
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
@@ -51927,7 +51940,7 @@ ix86_initialize_bounds (tree var, tree lb, tree ub, tree *stmts)
 #define TARGET_BINDS_LOCAL_P darwin_binds_local_p
 #else
 #undef TARGET_BINDS_LOCAL_P
-#define TARGET_BINDS_LOCAL_P default_binds_local_p_2
+#define TARGET_BINDS_LOCAL_P ix86_binds_local_p
 #endif
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 #undef TARGET_BINDS_LOCAL_P
index 53e47d03b3a6f99d767717e0b29ccf0436e6889c..81d2ad29a83f894de72c87f417bafa367b45a546 100644 (file)
@@ -587,6 +587,7 @@ extern bool default_use_anchors_for_symbol_p (const_rtx);
 extern bool default_binds_local_p (const_tree);
 extern bool default_binds_local_p_1 (const_tree, int);
 extern bool default_binds_local_p_2 (const_tree);
+extern bool default_binds_local_p_3 (const_tree, bool, bool, bool, bool);
 extern void default_globalize_label (FILE *, const char *);
 extern void default_globalize_decl_name (FILE *, tree);
 extern void default_emit_unwind_label (FILE *, tree, int, int);
index e7b30489c7f2a912025e2df849c2c80fdbfe49d8..c6bd2eda4b674866ab686318add553b1c3e48f3a 100644 (file)
@@ -1,3 +1,13 @@
+2015-04-17  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/65780
+       * gcc.dg/pr65780-1.c: New test.
+       * gcc.dg/pr65780-2.c: Likewise.
+       * gcc.target/i386/pr32219-9.c: Likewise.
+       * gcc.target/i386/pr32219-1.c (xxx): Make it initialized common
+       symbol.
+       * gcc.target/i386/pr64317.c (c): Initialize.
+
 2015-04-17  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/65612
diff --git a/gcc/testsuite/gcc.dg/pr65780-1.c b/gcc/testsuite/gcc.dg/pr65780-1.c
new file mode 100644 (file)
index 0000000..b586211
--- /dev/null
@@ -0,0 +1,12 @@
+/* PR target/65780 */
+/* { dg-do link { target *-*-linux* *-*-gnu* } } */
+/* { dg-options "-O2" } */
+
+int optopt;
+
+int
+main ()
+{
+  optopt = 4;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr65780-2.c b/gcc/testsuite/gcc.dg/pr65780-2.c
new file mode 100644 (file)
index 0000000..bff3323
--- /dev/null
@@ -0,0 +1,13 @@
+/* PR target/65780 */
+/* { dg-do link { target *-*-linux* *-*-gnu* } } */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -fpie" } */
+
+int optopt;
+
+int
+main ()
+{
+  optopt = 4;
+  return 0;
+}
index 5bd80a0cd47aa6edb77c86ff61afae9f23a0e21e..2622f663059ff7bf2b57c12a30166f55930fabca 100644 (file)
@@ -1,7 +1,8 @@
 /* { dg-do compile { target *-*-linux* } } */
 /* { dg-options "-O2 -fpie" } */
 
-/* Common symbol with -fpie.  */
+/* Initialized common symbol with -fpie.  */
+int xxx = 5;
 int xxx;
 
 int
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-9.c b/gcc/testsuite/gcc.target/i386/pr32219-9.c
new file mode 100644 (file)
index 0000000..8c21826
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-require-effective-target pie_copyreloc } */
+/* { dg-options "-O2 -fpie" } */
+
+/* Uninitialized common symbol with -fpie.  */
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
index 32969fc689acb3de9b4a63f37f04c1862de6f472..8cac6ddb25d46bd9748cbf9437eda71aea7e9a84 100644 (file)
@@ -3,7 +3,7 @@
 /* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" } } */
 /* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" } } */
 /* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" } } */
-long c;
+long c = 1;
 
 int bar();
 
index e644b1daa7ef8f64abe4c7b9d815a41a4ce735ce..e8d996cb1e38564b8294701bb2e62f62469543cc 100644 (file)
@@ -6809,9 +6809,13 @@ resolution_local_p (enum ld_plugin_symbol_resolution resolution)
          || resolution == LDPR_RESOLVED_EXEC);
 }
 
-static bool
+/* COMMON_LOCAL_P is true means that the linker can guarantee that an
+   uninitialized common symbol in the executable will still be defined
+   (through COPY relocation) in the executable.  */
+
+bool
 default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
-                        bool extern_protected_data)
+                        bool extern_protected_data, bool common_local_p)
 {
   /* A non-decl is an entry in the constant pool.  */
   if (!DECL_P (exp))
@@ -6836,7 +6840,16 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
      because dynamic linking might overwrite symbols
      in shared libraries.  */
   bool resolved_locally = false;
-  bool defined_locally = !DECL_EXTERNAL (exp);
+
+  bool uninited_common = (DECL_COMMON (exp)
+                         && (DECL_INITIAL (exp) == NULL
+                             || (!in_lto_p
+                                 && DECL_INITIAL (exp) == error_mark_node)));
+
+  /* A non-external variable is defined locally only if it isn't
+     uninitialized COMMON variable or common_local_p is true.  */
+  bool defined_locally = (!DECL_EXTERNAL (exp)
+                         && (!uninited_common || common_local_p));
   if (symtab_node *node = symtab_node::get (exp))
     {
       if (node->in_other_partition)
@@ -6878,10 +6891,7 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
 
   /* Uninitialized COMMON variable may be unified with symbols
      resolved from other modules.  */
-  if (DECL_COMMON (exp)
-      && !resolved_locally
-      && (DECL_INITIAL (exp) == NULL
-         || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
+  if (uninited_common && !resolved_locally)
     return false;
 
   /* Otherwise we're left with initialized (or non-common) global data
@@ -6895,21 +6905,22 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
 bool
 default_binds_local_p (const_tree exp)
 {
-  return default_binds_local_p_3 (exp, flag_shlib != 0, true, false);
+  return default_binds_local_p_3 (exp, flag_shlib != 0, true, false, false);
 }
 
-/* Similar to default_binds_local_p, but protected data may be
-   external.  */
+/* Similar to default_binds_local_p, but common symbol may be local.  */
+
 bool
 default_binds_local_p_2 (const_tree exp)
 {
-  return default_binds_local_p_3 (exp, flag_shlib != 0, true, true);
+  return default_binds_local_p_3 (exp, flag_shlib != 0, true, false,
+                                 !flag_pic);
 }
 
 bool
 default_binds_local_p_1 (const_tree exp, int shlib)
 {
-  return default_binds_local_p_3 (exp, shlib != 0, false, false);
+  return default_binds_local_p_3 (exp, shlib != 0, false, false, false);
 }
 
 /* Return true when references to DECL must bind to current definition in