diff mbox

PR target/65780: [5/6 Regression] Uninitialized common handling in executables

Message ID 20150416185748.GA28126@intel.com
State New
Headers show

Commit Message

H.J. Lu April 16, 2015, 6:57 p.m. UTC
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 common symbol may be local.  If common symbol
may be local, 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.

Tested on Linux/x86-64 using -m32 with binutils master and 2.24.  OK for
trunk and 5 branch?


H.J.
---
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.
---
 gcc/config/i386/i386.c                    | 15 ++++++++++++++-
 gcc/output.h                              |  1 +
 gcc/testsuite/gcc.dg/pr65780-1.c          | 12 ++++++++++++
 gcc/testsuite/gcc.dg/pr65780-2.c          | 13 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr32219-1.c |  3 ++-
 gcc/testsuite/gcc.target/i386/pr32219-9.c | 15 +++++++++++++++
 gcc/testsuite/gcc.target/i386/pr64317.c   |  2 +-
 gcc/varasm.c                              | 31 +++++++++++++++++++------------
 8 files changed, 77 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr65780-1.c
 create mode 100644 gcc/testsuite/gcc.dg/pr65780-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-9.c

Comments

Jeff Law April 17, 2015, 4:12 p.m. UTC | #1
On 04/16/2015 12:57 PM, H.J. Lu wrote:
> 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 common symbol may be local.  If common symbol
> may be local, 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.
>
> Tested on Linux/x86-64 using -m32 with binutils master and 2.24.  OK for
> trunk and 5 branch?
>
>
> H.J.
> ---
> 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.
I approved the slightly different version of this attached to pr 65780, 
c#35.

Jeff
diff mbox

Patch

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 1f20ff3..72e6bc2 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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
diff --git a/gcc/output.h b/gcc/output.h
index 53e47d0..81d2ad2 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -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);
diff --git a/gcc/testsuite/gcc.dg/pr65780-1.c b/gcc/testsuite/gcc.dg/pr65780-1.c
new file mode 100644
index 0000000..b586211
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr65780-1.c
@@ -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
index 0000000..bff3323
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr65780-2.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-1.c b/gcc/testsuite/gcc.target/i386/pr32219-1.c
index 5bd80a0..2622f66 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-1.c
@@ -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
index 0000000..8c21826
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-9.c
@@ -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 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr64317.c b/gcc/testsuite/gcc.target/i386/pr64317.c
index 32969fc..8cac6dd 100644
--- a/gcc/testsuite/gcc.target/i386/pr64317.c
+++ b/gcc/testsuite/gcc.target/i386/pr64317.c
@@ -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();
 
diff --git a/gcc/varasm.c b/gcc/varasm.c
index e644b1d..609b644 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -6809,9 +6809,9 @@  resolution_local_p (enum ld_plugin_symbol_resolution resolution)
 	  || resolution == LDPR_RESOLVED_EXEC);
 }
 
-static bool
+bool
 default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
-			 bool extern_protected_data)
+			 bool extern_protected_data, bool common_maybe_local)
 {
   /* A non-decl is an entry in the constant pool.  */
   if (!DECL_P (exp))
@@ -6836,7 +6836,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_maybe_local is true.  */
+  bool defined_locally = (!DECL_EXTERNAL (exp)
+			  && (!uninited_common || common_maybe_local));
   if (symtab_node *node = symtab_node::get (exp))
     {
       if (node->in_other_partition)
@@ -6878,10 +6887,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 +6901,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