public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 3/5] Properly handle -fno-plt in ix86_expand_call
  2015-10-22 17:09 [PATCH 0/5] Improve x86 Position-Independent codegen H.J. Lu
@ 2015-10-22 17:09 ` H.J. Lu
  2015-10-22 17:09 ` [PATCH 1/5] X86: Optimize access to globals in PIE with copy reloc H.J. Lu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2015-10-22 17:09 UTC (permalink / raw)
  To: gcc-patches

prepare_call_address in calls.c is the wrong place to handle -fno-plt.
We shoudn't force function address into register and hope that load
function address via GOT and indirect call via register will be folded
into indirect call via GOT, which doesn't always happen.  Also non-PIC
case can only be handled in backend.  Instead, backend should expand
external function call into indirect call via GOT for -fno-plt.

This patch reverts -fno-plt in prepare_call_address and handles it in
ix86_expand_call.  Other backends may need similar changes to support
-fno-plt.  Alternately, we can introduce a target hook to indicate
whether an external function should be called via register for -fno-plt
so that i386 backend can disable it in prepare_call_address.

gcc/

	PR target/67215
	* calls.c (prepare_call_address): Don't handle -fno-plt here.
	* config/i386/i386.c (ix86_expand_call): Generate indirect call
	via GOT for -fno-plt.  Support indirect call via GOT for x32.
	* config/i386/predicates.md (sibcall_memory_operand): Allow
	GOT memory operand.

gcc/testsuite/

	PR target/67215
	* gcc.target/i386/pr67215-1.c: New test.
	* gcc.target/i386/pr67215-2.c: Likewise.
	* gcc.target/i386/pr67215-3.c: Likewise.
---
 gcc/calls.c                               | 12 ------
 gcc/config/i386/i386.c                    | 71 ++++++++++++++++++++++++-------
 gcc/config/i386/predicates.md             |  7 ++-
 gcc/testsuite/gcc.target/i386/pr67215-1.c | 20 +++++++++
 gcc/testsuite/gcc.target/i386/pr67215-2.c | 20 +++++++++
 gcc/testsuite/gcc.target/i386/pr67215-3.c | 13 ++++++
 6 files changed, 114 insertions(+), 29 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr67215-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr67215-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr67215-3.c

diff --git a/gcc/calls.c b/gcc/calls.c
index 6e6f33d..68c4eb5 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -203,18 +203,6 @@ prepare_call_address (tree fndecl_or_type, rtx funexp, rtx static_chain_value,
 	       && targetm.small_register_classes_for_mode_p (FUNCTION_MODE))
 	      ? force_not_mem (memory_address (FUNCTION_MODE, funexp))
 	      : memory_address (FUNCTION_MODE, funexp));
-  else if (flag_pic
-	   && fndecl_or_type
-	   && TREE_CODE (fndecl_or_type) == FUNCTION_DECL
-	   && (!flag_plt
-	       || lookup_attribute ("noplt", DECL_ATTRIBUTES (fndecl_or_type)))
-	   && !targetm.binds_local_p (fndecl_or_type))
-    {
-      /* This is done only for PIC code.  There is no easy interface to force the
-	 function address into GOT for non-PIC case.  non-PIC case needs to be
-	 handled specially by the backend.  */
-      funexp = force_reg (Pmode, funexp);
-    }
   else if (! sibcallp)
     {
       if (!NO_FUNCTION_CSE && optimize && ! flag_no_function_cse)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index c66cb8c..f5b1717 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -26749,21 +26749,54 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
       /* Static functions and indirect calls don't need the pic register.  Also,
 	 check if PLT was explicitly avoided via no-plt or "noplt" attribute, making
 	 it an indirect call.  */
+      rtx addr = XEXP (fnaddr, 0);
       if (flag_pic
-	  && (!TARGET_64BIT
-	      || (ix86_cmodel == CM_LARGE_PIC
-		  && DEFAULT_ABI != MS_ABI))
-	  && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
-	  && !SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0))
-	  && flag_plt
-	  && (SYMBOL_REF_DECL ((XEXP (fnaddr, 0))) == NULL_TREE
-	      || !lookup_attribute ("noplt",
-		     DECL_ATTRIBUTES (SYMBOL_REF_DECL (XEXP (fnaddr, 0))))))
+	  && GET_CODE (addr) == SYMBOL_REF
+	  && !SYMBOL_REF_LOCAL_P (addr))
 	{
-	  use_reg (&use, gen_rtx_REG (Pmode, REAL_PIC_OFFSET_TABLE_REGNUM));
-	  if (ix86_use_pseudo_pic_reg ())
-	    emit_move_insn (gen_rtx_REG (Pmode, REAL_PIC_OFFSET_TABLE_REGNUM),
-			    pic_offset_table_rtx);
+	  if (flag_plt
+	      && (SYMBOL_REF_DECL (addr) == NULL_TREE
+		  || !lookup_attribute ("noplt",
+					DECL_ATTRIBUTES (SYMBOL_REF_DECL (addr)))))
+	    {
+	      if (!TARGET_64BIT
+		  || (ix86_cmodel == CM_LARGE_PIC
+		      && DEFAULT_ABI != MS_ABI))
+		{
+		  use_reg (&use, gen_rtx_REG (Pmode,
+					      REAL_PIC_OFFSET_TABLE_REGNUM));
+		  if (ix86_use_pseudo_pic_reg ())
+		    emit_move_insn (gen_rtx_REG (Pmode,
+						 REAL_PIC_OFFSET_TABLE_REGNUM),
+				    pic_offset_table_rtx);
+		}
+	    }
+	  else if (!TARGET_PECOFF && !TARGET_MACHO)
+	    {
+	      if (TARGET_64BIT)
+		{
+		  fnaddr = gen_rtx_UNSPEC (Pmode,
+					   gen_rtvec (1, addr),
+					   UNSPEC_GOTPCREL);
+		  fnaddr = gen_rtx_CONST (Pmode, fnaddr);
+		}
+	      else
+		{
+		  fnaddr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
+					   UNSPEC_GOT);
+		  fnaddr = gen_rtx_CONST (Pmode, fnaddr);
+		  fnaddr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
+					 fnaddr);
+		}
+	      fnaddr = gen_const_mem (Pmode, fnaddr);
+	      /* Pmode may not be the same as word_mode for x32, which
+		 doesn't support indirect branch via 32-bit memory slot.
+		 Since x32 GOT slot is 64 bit with zero upper 32 bits,
+		 indirect branch via x32 GOT slot is OK.  */
+	      if (GET_MODE (fnaddr) != word_mode)
+		fnaddr = gen_rtx_ZERO_EXTEND (word_mode, fnaddr);
+	      fnaddr = gen_rtx_MEM (QImode, fnaddr);
+	    }
 	}
     }
 
@@ -26785,9 +26818,15 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
       && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
       && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
     fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
-  else if (sibcall
-	   ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
-	   : !call_insn_operand (XEXP (fnaddr, 0), word_mode))
+  /* Since x32 GOT slot is 64 bit with zero upper 32 bits, indirect
+     branch via x32 GOT slot is OK.  */
+  else if (!(TARGET_X32
+	     && MEM_P (fnaddr)
+	     && GET_CODE (XEXP (fnaddr, 0)) == ZERO_EXTEND
+	     && GOT_memory_operand (XEXP (XEXP (fnaddr, 0), 0), Pmode))
+	   && (sibcall
+	       ? !sibcall_insn_operand (XEXP (fnaddr, 0), word_mode)
+	       : !call_insn_operand (XEXP (fnaddr, 0), word_mode)))
     {
       fnaddr = convert_to_mode (word_mode, XEXP (fnaddr, 0), 1);
       fnaddr = gen_rtx_MEM (QImode, copy_to_mode_reg (word_mode, fnaddr));
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 042b949..1595142 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -599,7 +599,12 @@
 ;; Return true if OP is a memory operands that can be used in sibcalls.
 (define_predicate "sibcall_memory_operand"
   (and (match_operand 0 "memory_operand")
-       (match_test "CONSTANT_P (XEXP (op, 0))")))
+       (match_test "CONSTANT_P (XEXP (op, 0))
+		    || (GET_CODE (XEXP (op, 0)) == PLUS
+			&& REG_P (XEXP (XEXP (op, 0), 0))
+			&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST
+			&& GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 0)) == UNSPEC
+			&& XINT (XEXP (XEXP (XEXP (op, 0), 1), 0), 1) == UNSPEC_GOT)")))
 
 ;; Test for a valid operand for a call instruction.
 ;; Allow constant call address operands in Pmode only.
diff --git a/gcc/testsuite/gcc.target/i386/pr67215-1.c b/gcc/testsuite/gcc.target/i386/pr67215-1.c
new file mode 100644
index 0000000..fd37f8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr67215-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+extern char* bar (int);
+extern char* arr[32];
+
+void
+foo (void)
+{
+  int i;
+
+  for (i = 0; i < 32; i++)
+    arr[i] = bar (128);
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "mov(l|q)\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*.bar@PLT" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr67215-2.c b/gcc/testsuite/gcc.target/i386/pr67215-2.c
new file mode 100644
index 0000000..ebf2919
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr67215-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic" } */
+
+extern char* bar (int) __attribute__ ((noplt));
+extern char* arr[32];
+
+void
+foo (void)
+{
+  int i;
+
+  for (i = 0; i < 32; i++)
+    arr[i] = bar (128);
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "mov(l|q)\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]*.bar@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*.bar@PLT" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr67215-3.c b/gcc/testsuite/gcc.target/i386/pr67215-3.c
new file mode 100644
index 0000000..eb6bb39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr67215-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fno-plt -fdump-rtl-expand" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar ();
+}
+
+/* { dg-final { scan-rtl-dump "\\(call \\(mem:QI \\(mem/u/c:" "expand" { target { ! x32 } } } } */
+/* { dg-final { scan-rtl-dump "\\(call \\(mem:QI \\(zero_extend:DI \\(mem/u/c:" "expand" { target x32 } } } */
-- 
2.4.3

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 5/5] Generate R_386_GOT32x relocation for -fno-plt -fno-pic
  2015-10-22 17:09 [PATCH 0/5] Improve x86 Position-Independent codegen H.J. Lu
                   ` (2 preceding siblings ...)
  2015-10-22 17:09 ` [PATCH 4/5] Check if x86 binutils supports R_386_GOT32X/R_X86_64_GOTPCRELX H.J. Lu
@ 2015-10-22 17:09 ` H.J. Lu
  2015-10-22 17:13 ` [PATCH 2/5] Enable -fsymbolic in LTO if -Bsymbolic is used H.J. Lu
  4 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2015-10-22 17:09 UTC (permalink / raw)
  To: gcc-patches

This patch extends -fno-plt to non-PIC on x86.  -fno-plt works in 64-bit
mode with the existing binutils.  For 32-bit, we need the updated
assembler and linker to support "call/jmp *foo@GOT", which accesses the
GOT slot without a base register, with a new R_386_GOT32x relocation.

gcc/

	* config/i386/i386.c (ix86_nopic_noplt_attribute_p): Check
	HAVE_LD_R_386_GOT32X == 0 before returning false.
	(ix86_output_call_insn): Generate "%!jmp/call\t*%p0@GOT" for
	32-bit.

gcc/testsuite/

	* gcc.target/i386/pr66232-10.c: New file.
	* gcc.target/i386/pr66232-11.c: Likewise.
	* gcc.target/i386/pr66232-12.c: Likewise.
	* gcc.target/i386/pr66232-13.c: Likewise.
	* lib/target-supports.exp (check_effective_target_r_386_got32x):
	New.
	(check_effective_target_r_x86_64_gotpcrelx): Likewise.
---
 gcc/config/i386/i386.c                     |  19 +++++-
 gcc/testsuite/gcc.target/i386/pr66232-10.c |  13 ++++
 gcc/testsuite/gcc.target/i386/pr66232-11.c |  14 ++++
 gcc/testsuite/gcc.target/i386/pr66232-12.c |  13 ++++
 gcc/testsuite/gcc.target/i386/pr66232-13.c |  13 ++++
 gcc/testsuite/lib/target-supports.exp      | 104 +++++++++++++++++++++++++++++
 6 files changed, 173 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-10.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-11.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-12.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-13.c

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f5b1717..b4c57ba 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -26904,7 +26904,8 @@ static bool
 ix86_nopic_noplt_attribute_p (rtx call_op)
 {
   if (flag_pic || ix86_cmodel == CM_LARGE
-      || !TARGET_64BIT || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF
+      || (!TARGET_64BIT && HAVE_LD_R_386_GOT32X == 0)
+      || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF
       || SYMBOL_REF_LOCAL_P (call_op))
     return false;
 
@@ -26929,8 +26930,14 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
 
   if (SIBLING_CALL_P (insn))
     {
+      /* ix86_nopic_noplt_attribute_p returns false for PIC.  */
       if (direct_p && ix86_nopic_noplt_attribute_p (call_op))
-	xasm = "%!jmp\t*%p0@GOTPCREL(%%rip)";
+	{
+	  if (TARGET_64BIT)
+	    xasm = "%!jmp\t*%p0@GOTPCREL(%%rip)";
+	  else
+	    xasm = "%!jmp\t*%p0@GOT";
+	}
       else if (direct_p)
 	xasm = "%!jmp\t%P0";
       /* SEH epilogue detection requires the indirect branch case
@@ -26974,8 +26981,14 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
 	seh_nop_p = true;
     }
 
+  /* ix86_nopic_noplt_attribute_p returns false for PIC.  */
   if (direct_p && ix86_nopic_noplt_attribute_p (call_op))
-    xasm = "%!call\t*%p0@GOTPCREL(%%rip)";
+    {
+      if (TARGET_64BIT)
+	xasm = "%!call\t*%p0@GOTPCREL(%%rip)";
+      else
+	xasm = "%!call\t*%p0@GOT";
+    }
   else if (direct_p)
     xasm = "%!call\t%P0";
   else
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-10.c b/gcc/testsuite/gcc.target/i386/pr66232-10.c
new file mode 100644
index 0000000..2e902d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-10.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fno-plt" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+  bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOT" { target { ia32 && r_386_got32x } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-11.c b/gcc/testsuite/gcc.target/i386/pr66232-11.c
new file mode 100644
index 0000000..9254759
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-11.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fno-plt" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+  bar ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" { target { ia32 && r_386_got32x } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-12.c b/gcc/testsuite/gcc.target/i386/pr66232-12.c
new file mode 100644
index 0000000..97c3a3c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-12.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOT" { target { ia32 && r_386_got32x } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66232-13.c b/gcc/testsuite/gcc.target/i386/pr66232-13.c
new file mode 100644
index 0000000..14ad039
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66232-13.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -fno-plt" } */
+
+extern int bar (void);
+
+int
+foo (void)
+{
+  return bar () + 1;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" { target { ia32 && r_386_got32x } } } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 2de8fac..e6d4601 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -6472,6 +6472,110 @@ proc check_effective_target_pie_copyreloc { } {
     return $pie_copyreloc_available_saved
 }
 
+# Return 1 if the x86 target generates R_386_GOT32X for "call *foo@GOT",
+# 0 otherwise.  Cache the result.
+
+proc check_effective_target_r_386_got32x { } {
+    global r_386_got32x_available_saved
+    global tool
+    global GCC_UNDER_TEST
+
+    if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+	return 0
+    }
+
+    # Need auto-host.h to check linker support.
+    if { ![file exists ../../auto-host.h ] } {
+	return 0
+    }
+
+    if [info exists r_386_got32x_available_saved] {
+	verbose "check_effective_target_r_386_got32x returning saved $r_386_got32x_available_saved" 2
+    } else {
+	# Set up and compile to see if linker supports PIE with copy
+	# reloc.  Include the current process ID in the file names to
+	# prevent conflicts with invocations for multiple testsuites.
+
+	set src pie[pid].c
+	set obj pie[pid].o
+
+	set f [open $src "w"]
+	puts $f "#include \"../../auto-host.h\""
+	puts $f "#if HAVE_LD_R_386_GOT32X == 0"
+	puts $f "# error Assembler does not support R_386_GOT32X."
+	puts $f "#endif"
+	close $f
+
+	verbose "check_effective_target_r_386_got32x compiling testfile $src" 2
+	set lines [${tool}_target_compile $src $obj object ""]
+
+	file delete $src
+	file delete $obj
+
+	if [string match "" $lines] then {
+	    verbose "check_effective_target_r_386_got32x testfile compilation passed" 2
+	    set r_386_got32x_available_saved 1
+	} else {
+	    verbose "check_effective_target_r_386_got32x testfile compilation failed" 2
+	    set r_386_got32x_available_saved 0
+	}
+    }
+
+    return $r_386_got32x_available_saved
+}
+
+# Return 1 if the x86 target generates R_386_GOT32X for
+# "call *foo@GOTPCREL(%rip)", 0 otherwise.  Cache the result.
+
+proc check_effective_target_r_x86_64_gotpcrelx { } {
+    global r_x86_64_gotpcrelx_available_saved
+    global tool
+    global GCC_UNDER_TEST
+
+    if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+	return 0
+    }
+
+    # Need auto-host.h to check linker support.
+    if { ![file exists ../../auto-host.h ] } {
+	return 0
+    }
+
+    if [info exists r_x86_64_gotpcrelx_available_saved] {
+	verbose "check_effective_target_r_x86_64_gotpcrelx returning saved $r_x86_64_gotpcrelx_available_saved" 2
+    } else {
+	# Set up and compile to see if linker supports PIE with copy
+	# reloc.  Include the current process ID in the file names to
+	# prevent conflicts with invocations for multiple testsuites.
+
+	set src pie[pid].c
+	set obj pie[pid].o
+
+	set f [open $src "w"]
+	puts $f "#include \"../../auto-host.h\""
+	puts $f "#if HAVE_LD_R_X86_64_GOTPCRELX == 0"
+	puts $f "# error Assembler does not support R_X86_64_GOTPCRELX."
+	puts $f "#endif"
+	close $f
+
+	verbose "check_effective_target_r_x86_64_gotpcrelx compiling testfile $src" 2
+	set lines [${tool}_target_compile $src $obj object ""]
+
+	file delete $src
+	file delete $obj
+
+	if [string match "" $lines] then {
+	    verbose "check_effective_target_r_x86_64_gotpcrelx testfile compilation passed" 2
+	    set r_x86_64_gotpcrelx_available_saved 1
+	} else {
+	    verbose "check_effective_target_r_x86_64_gotpcrelx testfile compilation failed" 2
+	    set r_x86_64_gotpcrelx_available_saved 0
+	}
+    }
+
+    return $r_x86_64_gotpcrelx_available_saved
+}
+
 # Return 1 if the target uses comdat groups.
 
 proc check_effective_target_comdat_group {} {
-- 
2.4.3

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] X86: Optimize access to globals in PIE with copy reloc
  2015-10-22 17:09 [PATCH 0/5] Improve x86 Position-Independent codegen H.J. Lu
  2015-10-22 17:09 ` [PATCH 3/5] Properly handle -fno-plt in ix86_expand_call H.J. Lu
@ 2015-10-22 17:09 ` H.J. Lu
  2015-10-22 17:09 ` [PATCH 4/5] Check if x86 binutils supports R_386_GOT32X/R_X86_64_GOTPCRELX H.J. Lu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2015-10-22 17:09 UTC (permalink / raw)
  To: gcc-patches

Normally, with PIE, GCC accesses globals that are extern to the module
using GOT.  This is two instructions, one to get the address of the global
from GOT and the other to get the value.  Examples:

---
extern int a_glob;
int
main ()
{
  return a_glob;
}
---

With PIE, the generated code accesses global via GOT using two memory
loads:

	movq	a_glob@GOTPCREL(%rip), %rax
	movl	(%rax), %eax

for 64-bit or

	movl	a_glob@GOT(%ecx), %eax
	movl	(%eax), %eax

for 32-bit.

Some experiments on google and SPEC CPU benchmarks show that the extra
instruction affects performance by 1% to 5%.

Solution - Copy Relocations:

When the linker supports copy relocations, GCC can always assume that
the global will be defined in the executable.  For globals that are
truly extern (come from shared objects), the linker will create copy
relocations and have them defined in the executable.  Result is that
no global access needs to go through GOT and hence improves performance.
We can generate

	movl	a_glob(%rip), %eax

for 64-bit and

	movl	a_glob@GOTOFF(%eax), %eax

for 32-bit.  This optimization only applies to undefined non-weak
non-TLS global data.  Undefined weak global or TLS data access still
must go through GOT.

This patch reverts legitimate_pic_address_disp_p change made in revision
218397, which only applies to x86-64.  Instead, this patch updates
targetm.binds_local_p to indicate if undefined non-weak non-TLS global
data is defined locally in PIE.  It also introduces a new target hook,
binds_tls_local_p to distinguish TLS variable from non-TLS variable.  By
default, binds_tls_local_p is the same as binds_local_p which assumes
TLS variable.

This patch checks if 32-bit and 64-bit linkers support PIE with copy
reloc at configure time.  64-bit linker is enabled in binutils 2.25
and 32-bit linker is enabled in binutils 2.26.  This optimization
is enabled only if the linker support is available.

Since copy relocation in PIE is incompatible with DSO created by
-Wl,-Bsymbolic, this patch also adds a new option, -fsymbolic, which
controls how references to global symbols are bound.  The -fsymbolic
option binds references to global symbols to the local definitions
and external references globally.  It avoids copy relocations in PIE
and optimizes global symbol references in shared library created
by -Wl,-Bsymbolic.

gcc/

	PR target/65846
	PR target/65886
	* configure.ac (HAVE_LD_PIE_COPYRELOC): Renamed to ...
	(HAVE_LD_X86_64_PIE_COPYRELOC): This.
	(HAVE_LD_386_PIE_COPYRELOC): New.   Defined to 1 if Linux/ia32
	linker supports PIE with copy reloc.
	* output.h (default_binds_tls_local_p): New.
	(default_binds_local_p_3): Add 2 bool arguments.
	* target.def (binds_tls_local_p): New target hook.
	* varasm.c (decl_default_tls_model): Replace targetm.binds_local_p
	with targetm.binds_tls_local_p.
	(default_binds_local_p_3): Add a bool argument to indicate TLS
	variable and a bool argument to indicate if an undefined non-TLS
	non-weak data is local.  Double check TLS variable.  If an
	undefined non-TLS non-weak data is local, treat it as defined
	locally.
	(default_binds_local_p): Pass true and false to
	default_binds_local_p_3.
	(default_binds_local_p_2): Likewise.
	(default_binds_local_p_1): Likewise.
	(default_binds_tls_local_p): New.
	* config.in: Regenerated.
	* configure: Likewise.
	* doc/tm.texi: Likewise.
	* config/i386/i386.c (legitimate_pic_address_disp_p): Don't
	check HAVE_LD_PIE_COPYRELOC here.
	(ix86_binds_local): New.
	(ix86_binds_tls_local_p): Likewise.
	(ix86_binds_local_p): Use it.
	(TARGET_BINDS_TLS_LOCAL_P): New.
	* doc/tm.texi.in (TARGET_BINDS_TLS_LOCAL_P): New hook.

gcc/testsuite/

	PR target/65846
	PR target/65886
	* gcc.target/i386/pie-copyrelocs-1.c: Updated for ia32.
	* gcc.target/i386/pie-copyrelocs-2.c: Likewise.
	* gcc.target/i386/pie-copyrelocs-3.c: Likewise.
	* gcc.target/i386/pie-copyrelocs-4.c: Likewise.
	* gcc.target/i386/pr32219-9.c: Likewise.
	* gcc.target/i386/pr32219-10.c: New file.
	* gcc.target/i386/pr65886-1.c: Likewise.
	* gcc.target/i386/pr65886-2.c: Likewise.
	* gcc.target/i386/pr65886-3.c: Likewise.
	* gcc.target/i386/pr65886-4.c: Likewise.
	* gcc.target/i386/pr65886-4.c: Likewise.
	* gcc.target/i386/pr65886-5.c: Likewise.

	* lib/target-supports.exp (check_effective_target_pie_copyreloc):
	Check HAVE_LD_X86_64_PIE_COPYRELOC and HAVE_LD_386_PIE_COPYRELOC
	instead of HAVE_LD_X86_64_PIE_COPYRELOC.
---
 gcc/common.opt                                   |  4 ++
 gcc/config.in                                    | 18 ++++---
 gcc/config/i386/i386.c                           | 44 ++++++++++-----
 gcc/configure                                    | 68 ++++++++++++++++++++---
 gcc/configure.ac                                 | 64 +++++++++++++++++++---
 gcc/doc/invoke.texi                              | 12 ++++-
 gcc/doc/tm.texi                                  | 10 ++++
 gcc/doc/tm.texi.in                               |  2 +
 gcc/output.h                                     |  4 +-
 gcc/target.def                                   | 14 +++++
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c |  4 +-
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c |  4 +-
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c |  2 +-
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c |  4 +-
 gcc/testsuite/gcc.target/i386/pr32219-10.c       | 16 ++++++
 gcc/testsuite/gcc.target/i386/pr32219-9.c        |  2 +
 gcc/testsuite/gcc.target/i386/pr65886-1.c        | 17 ++++++
 gcc/testsuite/gcc.target/i386/pr65886-2.c        | 15 ++++++
 gcc/testsuite/gcc.target/i386/pr65886-3.c        | 16 ++++++
 gcc/testsuite/gcc.target/i386/pr65886-4.c        | 15 ++++++
 gcc/testsuite/gcc.target/i386/pr65886-5.c        | 18 +++++++
 gcc/testsuite/gcc.target/i386/pr65886-6.c        | 18 +++++++
 gcc/testsuite/lib/target-supports.exp            | 10 +++-
 gcc/varasm.c                                     | 69 ++++++++++++++++++------
 24 files changed, 393 insertions(+), 57 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-10.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-5.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-6.c

diff --git a/gcc/common.opt b/gcc/common.opt
index 12ca0d6..6148e49 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1010,6 +1010,10 @@ fcommon
 Common Report Var(flag_no_common,0)
 Do not put uninitialized globals in the common section.
 
+fsymbolic
+Common Report Var(flag_symbolic)
+Bind global references locally and external references globally
+
 fcompare-debug
 Driver
 ; Converted by the driver to -fcompare-debug= options.
diff --git a/gcc/config.in b/gcc/config.in
index 48d7e64..77b3862 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1408,6 +1408,12 @@
 #endif
 
 
+/* Define 0/1 if your 386 linker supports -pie option with copy reloc. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_386_PIE_COPYRELOC
+#endif
+
+
 /* Define if your linker supports --as-needed/--no-as-needed or equivalent
    options. */
 #ifndef USED_FOR_TARGET
@@ -1494,12 +1500,6 @@
 #endif
 
 
-/* Define 0/1 if your linker supports -pie option with copy reloc. */
-#ifndef USED_FOR_TARGET
-#undef HAVE_LD_PIE_COPYRELOC
-#endif
-
-
 /* Define if your linker links a mix of read-only and read-write sections into
    a read-write section. */
 #ifndef USED_FOR_TARGET
@@ -1525,6 +1525,12 @@
 #endif
 
 
+/* Define 0/1 if your x86-64 linker supports -pie option with copy reloc. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_X86_64_PIE_COPYRELOC
+#endif
+
+
 /* Define to 1 if you have the <limits.h> header file. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_LIMITS_H
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 6fd4a56..c66cb8c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -14517,11 +14517,7 @@ legitimate_pic_address_disp_p (rtx disp)
 		return true;
 	    }
 	  else if (!SYMBOL_REF_FAR_ADDR_P (op0)
-		   && (SYMBOL_REF_LOCAL_P (op0)
-		       || (HAVE_LD_PIE_COPYRELOC
-			   && flag_pie
-			   && !SYMBOL_REF_WEAK (op0)
-			   && !SYMBOL_REF_FUNCTION_P (op0)))
+		   && SYMBOL_REF_LOCAL_P (op0)
 		   && ix86_cmodel != CM_LARGE_PIC)
 	    return true;
 	  break;
@@ -53496,17 +53492,39 @@ ix86_initialize_bounds (tree var, tree lb, tree ub, tree *stmts)
 }
 
 #if !TARGET_MACHO && !TARGET_DLLIMPORT_DECL_ATTRIBUTES
-/* 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.   */
+/* Common and undefined non-TLS non-weak data symbols are local only
+   for non-PIE executables or linker supports copy reloc in PIE
+   executables.  */
+
+static bool
+ix86_binds_local (const_tree exp, bool tls)
+{
+  bool local_p;
+  if (!flag_pic)
+    local_p = true;
+  else if (flag_pie)
+    {
+      if (TARGET_64BIT)
+	local_p = HAVE_LD_X86_64_PIE_COPYRELOC != 0;
+      else
+	local_p = HAVE_LD_386_PIE_COPYRELOC != 0;
+    }
+  else
+    local_p = false;
+  return default_binds_local_p_3 (exp, tls, flag_shlib != 0, true,
+				  true, local_p, local_p);
+}
 
 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)));
+  return ix86_binds_local (exp, false);
+}
+
+static bool
+ix86_binds_tls_local_p (const_tree exp)
+{
+  return ix86_binds_local (exp, true);
 }
 #endif
 
@@ -53734,6 +53752,8 @@ ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
 #else
 #undef TARGET_BINDS_LOCAL_P
 #define TARGET_BINDS_LOCAL_P ix86_binds_local_p
+#undef TARGET_BINDS_TLS_LOCAL_P
+#define TARGET_BINDS_TLS_LOCAL_P ix86_binds_tls_local_p
 #endif
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 #undef TARGET_BINDS_LOCAL_P
diff --git a/gcc/configure b/gcc/configure
index 3122499..e388318 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -27525,13 +27525,13 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_pie" >&5
 $as_echo "$gcc_cv_ld_pie" >&6; }
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker PIE support with copy reloc" >&5
-$as_echo_n "checking linker PIE support with copy reloc... " >&6; }
-gcc_cv_ld_pie_copyreloc=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking x86-64 linker PIE support with copy reloc" >&5
+$as_echo_n "checking x86-64 linker PIE support with copy reloc... " >&6; }
+gcc_cv_ld_x86_64_pie_copyreloc=no
 if test $gcc_cv_ld_pie = yes ; then
   if test $in_tree_ld = yes ; then
     if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
-      gcc_cv_ld_pie_copyreloc=yes
+      gcc_cv_ld_x86_64_pie_copyreloc=yes
     fi
   elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
     # Check if linker supports -pie option with copy reloc
@@ -27562,7 +27562,7 @@ EOF
          && $gcc_cv_ld -shared -melf_x86_64 -o conftest1.so conftest1.o > /dev/null 2>&1 \
          && $gcc_cv_as --64 -o conftest2.o conftest2.s > /dev/null 2>&1 \
          && $gcc_cv_ld -pie -melf_x86_64 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
-        gcc_cv_ld_pie_copyreloc=yes
+        gcc_cv_ld_x86_64_pie_copyreloc=yes
       fi
       rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
       ;;
@@ -27571,11 +27571,63 @@ EOF
 fi
 
 cat >>confdefs.h <<_ACEOF
-#define HAVE_LD_PIE_COPYRELOC `if test x"$gcc_cv_ld_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`
+#define HAVE_LD_X86_64_PIE_COPYRELOC `if test x"$gcc_cv_ld_x86_64_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`
 _ACEOF
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_pie_copyreloc" >&5
-$as_echo "$gcc_cv_ld_pie_copyreloc" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_x86_64_pie_copyreloc" >&5
+$as_echo "$gcc_cv_ld_x86_64_pie_copyreloc" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking 386 linker PIE support with copy reloc" >&5
+$as_echo_n "checking 386 linker PIE support with copy reloc... " >&6; }
+gcc_cv_ld_386_pie_copyreloc=no
+if test $gcc_cv_ld_pie = yes ; then
+  if test $in_tree_ld = yes ; then
+    if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 26 -o "$gcc_cv_gld_major_version" -gt 2; then
+      gcc_cv_ld_386_pie_copyreloc=yes
+    fi
+  elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+    # Check if linker supports -pie option with copy reloc
+    case "$target" in
+    i?86-*-linux* | x86_64-*-linux*)
+      cat > conftest1.s <<EOF
+	.globl	a_glob
+	.data
+	.type	a_glob, @object
+	.size	a_glob, 4
+a_glob:
+	.long	2
+EOF
+      cat > conftest2.s <<EOF
+	.text
+	.globl	main
+	.type	main, @function
+main:
+	movl	a_glob@GOTOFF(%ebx), %eax
+	.size	main, .-main
+	.globl	ptr
+	.section	.data.rel,"aw",@progbits
+	.type	ptr, @object
+ptr:
+	.long	a_glob
+EOF
+      if $gcc_cv_as --32 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+         && $gcc_cv_ld -shared -melf_i386 -o conftest1.so conftest1.o > /dev/null 2>&1 \
+         && $gcc_cv_as --32 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+         && $gcc_cv_ld -pie -melf_i386 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
+        gcc_cv_ld_386_pie_copyreloc=yes
+      fi
+      rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
+      ;;
+    esac
+  fi
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LD_386_PIE_COPYRELOC `if test x"$gcc_cv_ld_386_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`
+_ACEOF
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_386_pie_copyreloc" >&5
+$as_echo "$gcc_cv_ld_386_pie_copyreloc" >&6; }
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker EH-compatible garbage collection of sections" >&5
 $as_echo_n "checking linker EH-compatible garbage collection of sections... " >&6; }
diff --git a/gcc/configure.ac b/gcc/configure.ac
index a30bb3b..7d5cc9a 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -4844,12 +4844,12 @@ if test x"$gcc_cv_ld_pie" = xyes; then
 fi
 AC_MSG_RESULT($gcc_cv_ld_pie)
 
-AC_MSG_CHECKING(linker PIE support with copy reloc)
-gcc_cv_ld_pie_copyreloc=no
+AC_MSG_CHECKING(x86-64 linker PIE support with copy reloc)
+gcc_cv_ld_x86_64_pie_copyreloc=no
 if test $gcc_cv_ld_pie = yes ; then
   if test $in_tree_ld = yes ; then
     if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
-      gcc_cv_ld_pie_copyreloc=yes
+      gcc_cv_ld_x86_64_pie_copyreloc=yes
     fi
   elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
     # Check if linker supports -pie option with copy reloc
@@ -4880,17 +4880,65 @@ EOF
          && $gcc_cv_ld -shared -melf_x86_64 -o conftest1.so conftest1.o > /dev/null 2>&1 \
          && $gcc_cv_as --64 -o conftest2.o conftest2.s > /dev/null 2>&1 \
          && $gcc_cv_ld -pie -melf_x86_64 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
-        gcc_cv_ld_pie_copyreloc=yes
+        gcc_cv_ld_x86_64_pie_copyreloc=yes
       fi
       rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
       ;;
     esac
   fi
 fi
-AC_DEFINE_UNQUOTED(HAVE_LD_PIE_COPYRELOC,
-  [`if test x"$gcc_cv_ld_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`],
-  [Define 0/1 if your linker supports -pie option with copy reloc.])
-AC_MSG_RESULT($gcc_cv_ld_pie_copyreloc)
+AC_DEFINE_UNQUOTED(HAVE_LD_X86_64_PIE_COPYRELOC,
+  [`if test x"$gcc_cv_ld_x86_64_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`],
+  [Define 0/1 if your x86-64 linker supports -pie option with copy reloc.])
+AC_MSG_RESULT($gcc_cv_ld_x86_64_pie_copyreloc)
+
+AC_MSG_CHECKING(386 linker PIE support with copy reloc)
+gcc_cv_ld_386_pie_copyreloc=no
+if test $gcc_cv_ld_pie = yes ; then
+  if test $in_tree_ld = yes ; then
+    if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 26 -o "$gcc_cv_gld_major_version" -gt 2; then
+      gcc_cv_ld_386_pie_copyreloc=yes
+    fi
+  elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+    # Check if linker supports -pie option with copy reloc
+    case "$target" in
+    i?86-*-linux* | x86_64-*-linux*)
+      cat > conftest1.s <<EOF
+	.globl	a_glob
+	.data
+	.type	a_glob, @object
+	.size	a_glob, 4
+a_glob:
+	.long	2
+EOF
+      cat > conftest2.s <<EOF
+	.text
+	.globl	main
+	.type	main, @function
+main:
+	movl	a_glob@GOTOFF(%ebx), %eax
+	.size	main, .-main
+	.globl	ptr
+	.section	.data.rel,"aw",@progbits
+	.type	ptr, @object
+ptr:
+	.long	a_glob
+EOF
+      if $gcc_cv_as --32 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+         && $gcc_cv_ld -shared -melf_i386 -o conftest1.so conftest1.o > /dev/null 2>&1 \
+         && $gcc_cv_as --32 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+         && $gcc_cv_ld -pie -melf_i386 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
+        gcc_cv_ld_386_pie_copyreloc=yes
+      fi
+      rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
+      ;;
+    esac
+  fi
+fi
+AC_DEFINE_UNQUOTED(HAVE_LD_386_PIE_COPYRELOC,
+  [`if test x"$gcc_cv_ld_386_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`],
+  [Define 0/1 if your 386 linker supports -pie option with copy reloc.])
+AC_MSG_RESULT($gcc_cv_ld_386_pie_copyreloc)
 
 AC_MSG_CHECKING(linker EH-compatible garbage collection of sections)
 gcc_cv_ld_eh_gc_sections=no
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index cd82544..5293a25 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1139,7 +1139,7 @@ See S/390 and zSeries Options.
 -finhibit-size-directive  -finstrument-functions @gol
 -finstrument-functions-exclude-function-list=@var{sym},@var{sym},@dots{} @gol
 -finstrument-functions-exclude-file-list=@var{file},@var{file},@dots{} @gol
--fno-common  -fno-ident @gol
+-fno-common  -fsymbolic  -fno-ident @gol
 -fpcc-struct-return  -fpic  -fPIC -fpie -fPIE -fno-plt @gol
 -fno-jump-tables @gol
 -frecord-gcc-switches @gol
@@ -23944,6 +23944,16 @@ it provides better performance, or if you wish to verify that the
 program will work on other systems that always treat uninitialized
 variable declarations this way.
 
+@item -fsymbolic
+@opindex -fsymbolic
+This option is similar to ELF linker option, @option{-Bsymbolic},
+which controls how references to global symbols are bound.  The
+@option{-fsymbolic} option binds references to global symbols to the
+local definitions and external references globally.  This option
+avoids copy relocations in position-independent executables and
+optimizes global symbol references in shared library created by
+linker option, @option{-Bsymbolic}.
+
 @item -fno-ident
 @opindex fno-ident
 Ignore the @code{#ident} directive.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index e6f712a..2f191b2 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7248,6 +7248,16 @@ for ELF, which has a looser model of global name binding than other
 currently supported object file formats.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_BINDS_TLS_LOCAL_P (const_tree @var{exp})
+Returns true if TLS variable @var{exp} names an object for which name
+resolution rules must resolve to the current ``module'' (dynamic shared
+library or executable image).
+
+The default version of this hook implements the name resolution rules
+for ELF, which has a looser model of global name binding than other
+currently supported object file formats.
+@end deftypefn
+
 @deftypevr {Target Hook} bool TARGET_HAVE_TLS
 Contains the value true if the target supports thread-local storage.
 The default value is false.
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 6f0c252..920ffa9 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -5038,6 +5038,8 @@ it is unlikely to be called.
 
 @hook TARGET_BINDS_LOCAL_P
 
+@hook TARGET_BINDS_TLS_LOCAL_P
+
 @hook TARGET_HAVE_TLS
 
 
diff --git a/gcc/output.h b/gcc/output.h
index 4ce6eea..865e03c 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -583,9 +583,11 @@ extern const char *default_strip_name_encoding (const char *);
 extern void default_asm_output_anchor (rtx);
 extern bool default_use_anchors_for_symbol_p (const_rtx);
 extern bool default_binds_local_p (const_tree);
+extern bool default_binds_tls_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 bool default_binds_local_p_3 (const_tree, bool, bool, 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/target.def b/gcc/target.def
index e4bc249..63b2939 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -2934,6 +2934,20 @@ currently supported object file formats.",
  bool, (const_tree exp),
  default_binds_local_p)
 
+/* True if TLS variable EXP names an object for which name resolution must
+   resolve to the current executable or shared library.  */
+DEFHOOK
+(binds_tls_local_p,
+ "Returns true if TLS variable @var{exp} names an object for which name\n\
+resolution rules must resolve to the current ``module'' (dynamic shared\n\
+library or executable image).\n\
+\n\
+The default version of this hook implements the name resolution rules\n\
+for ELF, which has a looser model of global name binding than other\n\
+currently supported object file formats.",
+ bool, (const_tree exp),
+ default_binds_tls_local_p)
+
 /* Check if profiling code is before or after prologue.  */
 DEFHOOK
 (profile_before_prologue,
diff --git a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c
index 7af851b..69e3f6e 100644
--- a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c
+++ b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c
@@ -1,4 +1,4 @@
-/* Check that GOTPCREL isn't used to access glob_a.  */
+/* Check that GOTPCREL/GOT isn't used to access glob_a.  */
 /* { dg-do compile { target *-*-linux* } } */
 /* { dg-require-effective-target pie_copyreloc } */
 /* { dg-options "-O2 -fpie" } */
@@ -12,3 +12,5 @@ int foo ()
 
 /* glob_a should never be accessed with a GOTPCREL.  */
 /* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* glob_a should never be accessed with a GOT.  */
+/* { dg-final { scan-assembler-not "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c
index 19cb97e..eb0724b 100644
--- a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c
+++ b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c
@@ -1,4 +1,4 @@
-/* Check that GOTPCREL isn't used to access glob_a.  */
+/* Check that GOTPCREL/GOT isn't used to access glob_a.  */
 /* { dg-do compile { target *-*-linux* } } */
 /* { dg-require-effective-target pie_copyreloc } */
 /* { dg-options "-O2 -fpie" } */
@@ -12,3 +12,5 @@ int foo ()
 
 /* glob_a should never be accessed with a GOTPCREL.  */
 /* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* glob_a should never be accessed with a GOT.  */
+/* { dg-final { scan-assembler-not "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c
index c2fa896..1123bd8 100644
--- a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c
+++ b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c
@@ -11,4 +11,4 @@ int foo ()
 }
 
 /* glob_a should be accessed with a PLT.  */
-/* { dg-final { scan-assembler "glob_a@PLT" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "glob_a@PLT" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c
index 413cdf3..4724ede 100644
--- a/gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c
+++ b/gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c
@@ -1,4 +1,4 @@
-/* Check that GOTPCREL is used to access glob_a.  */
+/* Check that GOTPCREL/GOT is used to access glob_a.  */
 /* { dg-do compile { target *-*-linux* } } */
 /* { dg-require-effective-target pie_copyreloc } */
 /* { dg-options "-O2 -fpie" } */
@@ -15,3 +15,5 @@ int foo ()
 
 /* weak glob_a should be accessed with a GOTPCREL.  */
 /* { dg-final { scan-assembler "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* weak glob_a should be accessed with a GOT.  */
+/* { dg-final { scan-assembler "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-10.c b/gcc/testsuite/gcc.target/i386/pr32219-10.c
new file mode 100644
index 0000000..3cd95f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr32219-10.c
@@ -0,0 +1,16 @@
+/* Check that tpoff/ntpoff isn't used to access glob_a.  */
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -fpie" } */
+
+extern __thread int glob_a;
+
+int foo ()
+{
+  return glob_a;
+}
+
+/* glob_a should never be accessed with a tpoff.  */
+/* { dg-final { scan-assembler-not "glob_a@tpoff" { target { ! ia32 } } } } */
+/* glob_a should never be accessed with a ntpoff.  */
+/* { dg-final { scan-assembler-not "glob_a@ntpoff" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-9.c b/gcc/testsuite/gcc.target/i386/pr32219-9.c
index 8c21826..77330be 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-9.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-9.c
@@ -13,3 +13,5 @@ foo ()
 
 /* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
 /* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr65886-1.c b/gcc/testsuite/gcc.target/i386/pr65886-1.c
new file mode 100644
index 0000000..c0d0aaa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr65886-1.c
@@ -0,0 +1,17 @@
+/* Check that GOTPCREL/GOT is used to access glob_a.  */
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2 -fpie -fsymbolic" } */
+
+extern int glob_a;
+
+int foo ()
+{
+  if (&glob_a != 0)
+    return glob_a;
+  else
+    return 0;
+}
+
+/* { dg-final { scan-assembler "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr65886-2.c b/gcc/testsuite/gcc.target/i386/pr65886-2.c
new file mode 100644
index 0000000..b89aaf0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr65886-2.c
@@ -0,0 +1,15 @@
+/* Check that GOTPCREL/GOT isn't used to access glob_a.  */
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fsymbolic" } */
+
+int glob_a = 1;
+
+int foo ()
+{
+  return glob_a;
+}
+
+/* { dg-final { scan-assembler "glob_a\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "glob_a@GOTOFF\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr65886-3.c b/gcc/testsuite/gcc.target/i386/pr65886-3.c
new file mode 100644
index 0000000..ae24fd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr65886-3.c
@@ -0,0 +1,16 @@
+/* Check that PLT isn't used to access glob_a.  */
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fsymbolic" } */
+
+int glob_a (void)
+{
+  return -1;
+}
+
+int foo ()
+{
+  return glob_a ();
+}
+
+/* { dg-final { scan-assembler-not "glob_a@PLT" } } */
+/* { dg-final { scan-assembler-times "movl\[ \t\]\\\$-1, %eax" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr65886-4.c b/gcc/testsuite/gcc.target/i386/pr65886-4.c
new file mode 100644
index 0000000..5f00508
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr65886-4.c
@@ -0,0 +1,15 @@
+/* Check that GOTPCREL/GOT isn't used to access glob_a.  */
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fsymbolic" } */
+
+extern __attribute__((visibility("protected"))) int glob_a;
+
+int foo ()
+{
+  return glob_a;
+}
+
+/* { dg-final { scan-assembler "glob_a\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "glob_a@GOTOFF\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr65886-5.c b/gcc/testsuite/gcc.target/i386/pr65886-5.c
new file mode 100644
index 0000000..a37e2f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr65886-5.c
@@ -0,0 +1,18 @@
+/* Check that GOTPCREL/GOT isn't used to access glob_a.  */
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fsymbolic" } */
+
+int glob_a __attribute__((weak));
+
+int foo ()
+{
+  if (&glob_a != 0)
+    return glob_a;
+  else
+    return 0;
+}
+
+/* { dg-final { scan-assembler "glob_a\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "glob_a@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "glob_a@GOTOFF\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "glob_a@GOT\\(" { target ia32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr65886-6.c b/gcc/testsuite/gcc.target/i386/pr65886-6.c
new file mode 100644
index 0000000..934f53f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr65886-6.c
@@ -0,0 +1,18 @@
+/* Check that PLT isn't used to access glob_a.  */
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -fsymbolic" } */
+
+int
+__attribute__((weak))
+glob_a (void)
+{
+  return -1;
+}
+
+int foo ()
+{
+  return glob_a ();
+}
+
+/* { dg-final { scan-assembler-not "glob_a@PLT" } } */
+/* { dg-final { scan-assembler-times "movl\[ \t\]\\\$-1, %eax" 1 } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 166b19a..2de8fac 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -6443,8 +6443,14 @@ proc check_effective_target_pie_copyreloc { } {
 
 	set f [open $src "w"]
 	puts $f "#include \"../../auto-host.h\""
-	puts $f "#if HAVE_LD_PIE_COPYRELOC == 0"
-	puts $f "# error Linker does not support PIE with copy reloc."
+	puts $f "#ifdef __x86_64__"
+	puts $f "# if HAVE_LD_X86_64_PIE_COPYRELOC == 0"
+	puts $f "#  error 64-bit linker does not support PIE with copy reloc."
+	puts $f "# endif"
+	puts $f "#else"
+	puts $f "# if HAVE_LD_386_PIE_COPYRELOC == 0"
+	puts $f "#  error 32-bit linker does not support PIE with copy reloc."
+	puts $f "# endif"
 	puts $f "#endif"
 	close $f
 
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 9cb7ac1..140f913 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -6062,7 +6062,7 @@ decl_default_tls_model (const_tree decl)
   enum tls_model kind;
   bool is_local;
 
-  is_local = targetm.binds_local_p (decl);
+  is_local = targetm.binds_tls_local_p (decl);
   if (!flag_shlib)
     {
       if (is_local)
@@ -6756,11 +6756,15 @@ resolution_local_p (enum ld_plugin_symbol_resolution resolution)
 
 /* 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.  */
+   (through COPY relocation) in the executable.  DATA_LOCAL_P is true
+   means that the linker can guarantee that undefined, non-TLS, non-weak
+   data 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 common_local_p)
+default_binds_local_p_3 (const_tree exp, bool tls, bool shlib,
+			 bool weak_dominate, bool extern_protected_data,
+			 bool common_local_p, bool data_local_p)
 {
   /* A non-decl is an entry in the constant pool.  */
   if (!DECL_P (exp))
@@ -6791,10 +6795,33 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
 			      || (!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 TLS is false, double check if EXP is a TLS variable.  */
+  if (!tls)
+    tls = TREE_CODE (exp) == VAR_DECL && DECL_THREAD_LOCAL_P (exp);
+
+  bool defined_locally;
+  if (!DECL_EXTERNAL (exp))
+    {
+      /* When a variable isn't defined externally, it is defined locally
+	 only if it isn't uninitialized COMMON variable or common_local_p
+	 is true and external references aren't bound globally.  */
+      defined_locally = (!uninited_common
+			 || (common_local_p && !flag_symbolic));
+
+    }
+  else
+    {
+      /* An undefined variable is defined locally only if it is a
+	 non-TLS non-weak data variable, external references aren't
+	 bound globally and linker can guarantee it will be defined
+	 locally.  */
+      defined_locally = (!tls
+			 && data_local_p
+			 && !flag_symbolic
+			 && TREE_CODE (exp) != FUNCTION_DECL
+			 && !DECL_WEAK (exp));
+    }
+
   if (symtab_node *node = symtab_node::get (exp))
     {
       if (node->in_other_partition)
@@ -6804,7 +6831,7 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
       else if (resolution_local_p (node->resolution))
 	resolved_locally = true;
     }
-  if (defined_locally && weak_dominate && !shlib)
+  if (defined_locally && weak_dominate && (!shlib || flag_symbolic))
     resolved_locally = true;
 
   /* Undefined weak symbols are never defined locally.  */
@@ -6817,13 +6844,15 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
   if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT
       && (TREE_CODE (exp) == FUNCTION_DECL
 	  || !extern_protected_data
+	  || flag_symbolic
 	  || DECL_VISIBILITY (exp) != VISIBILITY_PROTECTED)
       && (DECL_VISIBILITY_SPECIFIED (exp) || defined_locally))
     return true;
 
   /* If PIC, then assume that any global name can be overridden by
-     symbols resolved from other modules.  */
-  if (shlib)
+     symbols resolved from other modules unless global references are
+     bound locally  */
+  if (shlib && !flag_symbolic)
     return false;
 
   /* Variables defined outside this object might not be local.  */
@@ -6850,7 +6879,16 @@ 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, false);
+  return default_binds_local_p_3 (exp, true, flag_shlib != 0, true,
+				  false, false, false);
+}
+
+/* Similar to default_binds_local_p, but for TLS variable.  */
+
+bool
+default_binds_tls_local_p (const_tree exp)
+{
+  return targetm.binds_local_p (exp);
 }
 
 /* Similar to default_binds_local_p, but common symbol may be local and
@@ -6859,14 +6897,15 @@ default_binds_local_p (const_tree exp)
 bool
 default_binds_local_p_2 (const_tree exp)
 {
-  return default_binds_local_p_3 (exp, flag_shlib != 0, true, true,
-				  !flag_pic);
+  return default_binds_local_p_3 (exp, true, flag_shlib != 0, true, true,
+				  !flag_pic, false);
 }
 
 bool
 default_binds_local_p_1 (const_tree exp, int shlib)
 {
-  return default_binds_local_p_3 (exp, shlib != 0, false, false, false);
+  return default_binds_local_p_3 (exp, true, shlib != 0, false, false,
+				  false, false);
 }
 
 /* Return true when references to DECL must bind to current definition in
-- 
2.4.3

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 4/5] Check if x86 binutils supports R_386_GOT32X/R_X86_64_GOTPCRELX
  2015-10-22 17:09 [PATCH 0/5] Improve x86 Position-Independent codegen H.J. Lu
  2015-10-22 17:09 ` [PATCH 3/5] Properly handle -fno-plt in ix86_expand_call H.J. Lu
  2015-10-22 17:09 ` [PATCH 1/5] X86: Optimize access to globals in PIE with copy reloc H.J. Lu
@ 2015-10-22 17:09 ` H.J. Lu
  2015-10-22 17:09 ` [PATCH 5/5] Generate R_386_GOT32x relocation for -fno-plt -fno-pic H.J. Lu
  2015-10-22 17:13 ` [PATCH 2/5] Enable -fsymbolic in LTO if -Bsymbolic is used H.J. Lu
  4 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2015-10-22 17:09 UTC (permalink / raw)
  To: gcc-patches

Define HAVE_LD_R_386_GOT32X to 1 if 32-bit x86 assembler generates
R_386_GOT32X for "jmp *foo@GOT".  Define HAVE_LD_R_X86_64_GOTPCRELX
to 1 if 64-bit x86 assembler generates R_X86_64_GOTPCRELX for
"jmp *foo@GOTPCREL(%rip)".

	* configure.ac (HAVE_LD_R_386_GOT32X): New.  Defined to 1
	if 32-bit assembler generates R_386_GOT32X for "jmp *foo@GOT".
	Otherise, defined to 0.
	(HAVE_LD_R_X86_64_GOTPCRELX): New.  Defined to 1 if 64-bit
	x86 assembler generates R_X86_64_GOTPCRELX for
	"jmp *foo@GOTPCREL(%rip)".
	* config.in: Regenerated.
	* configure: Likewise.
---
 gcc/config.in    | 13 ++++++++++++
 gcc/configure    | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/configure.ac | 45 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 119 insertions(+)

diff --git a/gcc/config.in b/gcc/config.in
index 77b3862..d32906d 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1507,6 +1507,19 @@
 #endif
 
 
+/* Define 0/1 if Define if your linker supports R_386_GOT32X relocation. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_R_386_GOT32X
+#endif
+
+
+/* Define 0/1 if Define if your linker supports R_X86_64_GOTPCRELX relocation.
+   */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_R_X86_64_GOTPCRELX
+#endif
+
+
 /* Define if your linker supports the *_sol2 emulations. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_LD_SOL2_EMULATION
diff --git a/gcc/configure b/gcc/configure
index e388318..0ce7d65 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -25779,6 +25779,67 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker for R_386_GOT32X relocation" >&5
+$as_echo_n "checking linker for R_386_GOT32X relocation... " >&6; }
+if test "${gcc_cv_ld_r_386_got32x+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_ld_r_386_got32x=no
+       if test $in_tree_ld = yes ; then
+	 if grep R_386_GOT32X $srcdir/../include/elf/i386.h > /dev/null 2>&1; then
+	   gcc_cv_ld_r_386_got32x=yes
+	 fi
+       elif test x$gcc_cv_as != x -a x$gcc_cv_readelf != x; then
+	 cat > conftest.s <<EOF
+	 jmp *foo@GOT
+EOF
+	 if $gcc_cv_as --32 -o conftest.o conftest.s > /dev/null 2>&1; then
+	   if $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \
+	      | grep R_386_GOT32X > /dev/null 2>&1; then
+	     gcc_cv_ld_r_386_got32x=yes
+	   fi
+	 fi
+       fi
+       rm -f conftest.s conftest.o
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_r_386_got32x" >&5
+$as_echo "$gcc_cv_ld_r_386_got32x" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LD_R_386_GOT32X `if test x"$gcc_cv_ld_r_386_got32x" = xyes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker for R_X86_64_GOTPCRELX relocation" >&5
+$as_echo_n "checking linker for R_X86_64_GOTPCRELX relocation... " >&6; }
+if test "${gcc_cv_ld_r_x86_64_gotpcrelx+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_ld_r_x86_64_gotpcrelx=no
+       if test $in_tree_ld = yes ; then
+	 if grep R_X86_64_GOTPCRELX $srcdir/../include/elf/i386.h > /dev/null 2>&1; then
+	   gcc_cv_ld_r_x86_64_gotpcrelx=yes
+	 fi
+       elif test x$gcc_cv_as != x -a x$gcc_cv_readelf != x; then
+	 cat > conftest.s <<EOF
+	 jmp *foo@GOTPCREL(%rip)
+EOF
+	 if $gcc_cv_as --64 -o conftest.o conftest.s > /dev/null 2>&1; then
+	   if $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \
+	      | grep R_X86_64_GOTPCRELX > /dev/null 2>&1; then
+	     gcc_cv_ld_r_x86_64_gotpcrelx=yes
+	   fi
+	 fi
+       fi
+       rm -f conftest.s conftest.o
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_r_x86_64_gotpcrelx" >&5
+$as_echo "$gcc_cv_ld_r_x86_64_gotpcrelx" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LD_R_X86_64_GOTPCRELX `if test x"$gcc_cv_ld_r_x86_64_gotpcrelx" = xyes; then echo 1; else echo 0; fi`
+_ACEOF
+
     ;;
 
   ia64*-*-*)
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 7d5cc9a..afada92 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -4137,6 +4137,51 @@ value:'
       [`if test $gcc_cv_as_ix86_tlsldm = yes; then echo 1; else echo 0; fi`],
       [Define to 1 if your assembler and linker support @tlsldm.])
 
+    AC_CACHE_CHECK([linker for R_386_GOT32X relocation],
+      [gcc_cv_ld_r_386_got32x],
+      [gcc_cv_ld_r_386_got32x=no
+       if test $in_tree_ld = yes ; then
+	 if grep R_386_GOT32X $srcdir/../include/elf/i386.h > /dev/null 2>&1; then
+	   gcc_cv_ld_r_386_got32x=yes
+	 fi
+       elif test x$gcc_cv_as != x -a x$gcc_cv_readelf != x; then
+	 cat > conftest.s <<EOF
+	 jmp *foo@GOT
+EOF
+	 if $gcc_cv_as --32 -o conftest.o conftest.s > /dev/null 2>&1; then
+	   if $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \
+	      | grep R_386_GOT32X > /dev/null 2>&1; then
+	     gcc_cv_ld_r_386_got32x=yes
+	   fi
+	 fi
+       fi
+       rm -f conftest.s conftest.o])
+    AC_DEFINE_UNQUOTED(HAVE_LD_R_386_GOT32X,
+      [`if test x"$gcc_cv_ld_r_386_got32x" = xyes; then echo 1; else echo 0; fi`],
+      [Define 0/1 if Define if your linker supports R_386_GOT32X relocation.])
+
+    AC_CACHE_CHECK([linker for R_X86_64_GOTPCRELX relocation],
+      [gcc_cv_ld_r_x86_64_gotpcrelx],
+      [gcc_cv_ld_r_x86_64_gotpcrelx=no
+       if test $in_tree_ld = yes ; then
+	 if grep R_X86_64_GOTPCRELX $srcdir/../include/elf/i386.h > /dev/null 2>&1; then
+	   gcc_cv_ld_r_x86_64_gotpcrelx=yes
+	 fi
+       elif test x$gcc_cv_as != x -a x$gcc_cv_readelf != x; then
+	 cat > conftest.s <<EOF
+	 jmp *foo@GOTPCREL(%rip)
+EOF
+	 if $gcc_cv_as --64 -o conftest.o conftest.s > /dev/null 2>&1; then
+	   if $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \
+	      | grep R_X86_64_GOTPCRELX > /dev/null 2>&1; then
+	     gcc_cv_ld_r_x86_64_gotpcrelx=yes
+	   fi
+	 fi
+       fi
+       rm -f conftest.s conftest.o])
+    AC_DEFINE_UNQUOTED(HAVE_LD_R_X86_64_GOTPCRELX,
+      [`if test x"$gcc_cv_ld_r_x86_64_gotpcrelx" = xyes; then echo 1; else echo 0; fi`],
+      [Define 0/1 if Define if your linker supports R_X86_64_GOTPCRELX relocation.])
     ;;
 
   ia64*-*-*)
-- 
2.4.3

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 0/5] Improve x86 Position-Independent codegen
@ 2015-10-22 17:09 H.J. Lu
  2015-10-22 17:09 ` [PATCH 3/5] Properly handle -fno-plt in ix86_expand_call H.J. Lu
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: H.J. Lu @ 2015-10-22 17:09 UTC (permalink / raw)
  To: gcc-patches

This set of patches improves x86 Position-Independent codegen by

1. Use copy reloction to access externally defined global data from
PIE if linker supports it.
2. Add -fsymbolic to control how references to global symbols are
bound, avoiding copy relocation in PIE against DSO created by
-Wl,-Bsymbolic.
3. Pass -fsymbolic to GCC if -Bsymbolic is used with -flto.
4. Properly handle -fno-plt in ix86_expand_call
5. Generate R_386_GOT32x relocation for -fno-plt -fno-pic if binutils
supports R_386_GOT32x.

H.J. Lu (5):
  X86: Optimize access to globals in PIE with copy reloc
  Enable -fsymbolic in LTO if -Bsymbolic is used
  Properly handle -fno-plt in ix86_expand_call
  Check if x86 binutils supports R_386_GOT32X/R_X86_64_GOTPCRELX
  Generate R_386_GOT32x relocation for -fno-plt -fno-pic

 gcc/calls.c                                      |  12 --
 gcc/collect2.c                                   |  51 ++++++++-
 gcc/common.opt                                   |   4 +
 gcc/config.in                                    |  29 ++++-
 gcc/config/i386/i386.c                           | 134 +++++++++++++++++------
 gcc/config/i386/predicates.md                    |   7 +-
 gcc/configure                                    | 129 ++++++++++++++++++++--
 gcc/configure.ac                                 | 109 ++++++++++++++++--
 gcc/doc/invoke.texi                              |  13 ++-
 gcc/doc/tm.texi                                  |  10 ++
 gcc/doc/tm.texi.in                               |   2 +
 gcc/output.h                                     |   4 +-
 gcc/target.def                                   |  14 +++
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-1.c |   4 +-
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-2.c |   4 +-
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c |   2 +-
 gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c |   4 +-
 gcc/testsuite/gcc.target/i386/pr32219-10.c       |  16 +++
 gcc/testsuite/gcc.target/i386/pr32219-9.c        |   2 +
 gcc/testsuite/gcc.target/i386/pr65886-1.c        |  17 +++
 gcc/testsuite/gcc.target/i386/pr65886-2.c        |  15 +++
 gcc/testsuite/gcc.target/i386/pr65886-3.c        |  16 +++
 gcc/testsuite/gcc.target/i386/pr65886-4.c        |  15 +++
 gcc/testsuite/gcc.target/i386/pr65886-5.c        |  18 +++
 gcc/testsuite/gcc.target/i386/pr65886-6.c        |  18 +++
 gcc/testsuite/gcc.target/i386/pr66232-10.c       |  13 +++
 gcc/testsuite/gcc.target/i386/pr66232-11.c       |  14 +++
 gcc/testsuite/gcc.target/i386/pr66232-12.c       |  13 +++
 gcc/testsuite/gcc.target/i386/pr66232-13.c       |  13 +++
 gcc/testsuite/gcc.target/i386/pr67215-1.c        |  20 ++++
 gcc/testsuite/gcc.target/i386/pr67215-2.c        |  20 ++++
 gcc/testsuite/gcc.target/i386/pr67215-3.c        |  13 +++
 gcc/testsuite/lib/target-supports.exp            | 114 ++++++++++++++++++-
 gcc/varasm.c                                     |  69 +++++++++---
 34 files changed, 848 insertions(+), 90 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr32219-10.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-5.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr65886-6.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-10.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-11.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-12.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-13.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr67215-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr67215-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr67215-3.c

-- 
2.4.3

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2/5] Enable -fsymbolic in LTO if -Bsymbolic is used
  2015-10-22 17:09 [PATCH 0/5] Improve x86 Position-Independent codegen H.J. Lu
                   ` (3 preceding siblings ...)
  2015-10-22 17:09 ` [PATCH 5/5] Generate R_386_GOT32x relocation for -fno-plt -fno-pic H.J. Lu
@ 2015-10-22 17:13 ` H.J. Lu
  2015-10-23  8:57   ` Richard Biener
  4 siblings, 1 reply; 8+ messages in thread
From: H.J. Lu @ 2015-10-22 17:13 UTC (permalink / raw)
  To: gcc-patches

When -Bsymbolic is passed to linker, references to global symbols
defined in the shared library are resolved locally.  We should pass
-fsymbolic to GCC in this case.

	* collect2.c (main): Add -fsymbolic to COLLECT_GCC_OPTIONS if
	-Bsymbolic is used.
	* doc/invoke.texi: Updated.
---
 gcc/collect2.c      | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
 gcc/doc/invoke.texi |  3 ++-
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/gcc/collect2.c b/gcc/collect2.c
index 20c2533..ccbf4c3 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -1044,7 +1044,8 @@ main (int argc, char **argv)
 #ifndef HAVE_LD_DEMANGLE
   current_demangling_style = auto_demangling;
 #endif
-  p = getenv ("COLLECT_GCC_OPTIONS");
+  char *gcc_options = getenv ("COLLECT_GCC_OPTIONS");
+  p = gcc_options;
   while (p && *p)
     {
       const char *q = extract_string (&p);
@@ -1231,7 +1232,8 @@ main (int argc, char **argv)
      AIX support needs to know if -shared has been specified before
      parsing commandline arguments.  */
 
-  p = getenv ("COLLECT_GCC_OPTIONS");
+  int add_fsymbolic = -1;
+  p = gcc_options;
   while (p && *p)
     {
       const char *q = extract_string (&p);
@@ -1241,6 +1243,9 @@ main (int argc, char **argv)
 	*c_ptr++ = xstrdup (q);
       if (strcmp (q, "-shared") == 0)
 	shared_obj = 1;
+      else if (strcmp (q, "-fsymbolic") == 0
+	       || strcmp (q, "-fno-symbolic") == 0)
+	add_fsymbolic = 0;
       if (*q == '-' && q[1] == 'B')
 	{
 	  *c_ptr++ = xstrdup (q);
@@ -1278,6 +1283,13 @@ main (int argc, char **argv)
 	{
 	  switch (arg[1])
 	    {
+	    case 'B':
+	      /* Add -fsymbolic to COLLECT_GCC_OPTIONS if -Bsymbolic is
+		 used.  */
+	      if (add_fsymbolic == -1 && !strcmp (arg + 2, "symbolic"))
+		add_fsymbolic = 1;
+	      break;
+
 	    case 'd':
 	      if (!strcmp (arg, "-debug"))
 		{
@@ -1495,6 +1507,41 @@ main (int argc, char **argv)
 	}
     }
 
+  if (add_fsymbolic > 0)
+    {
+      /* Add -fsymbolic to COLLECT_GCC_OPTIONS.  */
+      size_t sizeof_env = sizeof "COLLECT_GCC_OPTIONS=";
+      size_t sizeof_fsymbolic = sizeof "\'-fsymbolic\' ";
+      size_t len = strlen (gcc_options);
+      size_t next, start;
+      char *first;
+      char *options = (char *) xmalloc (sizeof_env + len +
+					sizeof_fsymbolic - 1);
+      memcpy (options, "COLLECT_GCC_OPTIONS=", sizeof_env - 1);
+      first = strchr (gcc_options, '\'');
+      if (first == NULL)
+	fatal_error (input_location, "malformed COLLECT_GCC_OPTIONS: %s",
+		     gcc_options);
+      next = sizeof_env - 1;
+      if (first != gcc_options)
+	{
+	  size_t first_len = first - gcc_options;
+	  memcpy (options + next, gcc_options, first_len);
+	  next += first_len;
+	  start = first_len;
+	}
+      else
+	start = 0;
+      memcpy (options + next, "\'-fsymbolic\' ", sizeof_fsymbolic - 1);
+      next += sizeof_fsymbolic - 1;
+      memcpy (options + next, gcc_options + start, len);
+      next += len;
+      options[next] = '\0';
+      putenv (options);
+      if (verbose)
+	fprintf (stderr, "%s\n", options);
+    }
+
 #ifdef COLLECT_EXPORT_LIST
   /* This is added only for debugging purposes.  */
   if (debug)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5293a25..47baaa3 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -23952,7 +23952,8 @@ which controls how references to global symbols are bound.  The
 local definitions and external references globally.  This option
 avoids copy relocations in position-independent executables and
 optimizes global symbol references in shared library created by
-linker option, @option{-Bsymbolic}.
+linker option, @option{-Bsymbolic}.  This option is enabled by default
+with @option{-flto} when @option{-Bsymbolic} is used.
 
 @item -fno-ident
 @opindex fno-ident
-- 
2.4.3

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/5] Enable -fsymbolic in LTO if -Bsymbolic is used
  2015-10-22 17:13 ` [PATCH 2/5] Enable -fsymbolic in LTO if -Bsymbolic is used H.J. Lu
@ 2015-10-23  8:57   ` Richard Biener
  2015-10-23 17:36     ` H.J. Lu
  0 siblings, 1 reply; 8+ messages in thread
From: Richard Biener @ 2015-10-23  8:57 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GCC Patches

On Thu, Oct 22, 2015 at 7:09 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> When -Bsymbolic is passed to linker, references to global symbols
> defined in the shared library are resolved locally.  We should pass
> -fsymbolic to GCC in this case.

Hmm, I think this info should come via the linker plugin, otherwise it
won't work
with using plain 'ld' for linking and plugin auto-loading for example.  Maybe
a special symbol resultion can be used for this?

Richard.

>         * collect2.c (main): Add -fsymbolic to COLLECT_GCC_OPTIONS if
>         -Bsymbolic is used.
>         * doc/invoke.texi: Updated.
> ---
>  gcc/collect2.c      | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  gcc/doc/invoke.texi |  3 ++-
>  2 files changed, 51 insertions(+), 3 deletions(-)
>
> diff --git a/gcc/collect2.c b/gcc/collect2.c
> index 20c2533..ccbf4c3 100644
> --- a/gcc/collect2.c
> +++ b/gcc/collect2.c
> @@ -1044,7 +1044,8 @@ main (int argc, char **argv)
>  #ifndef HAVE_LD_DEMANGLE
>    current_demangling_style = auto_demangling;
>  #endif
> -  p = getenv ("COLLECT_GCC_OPTIONS");
> +  char *gcc_options = getenv ("COLLECT_GCC_OPTIONS");
> +  p = gcc_options;
>    while (p && *p)
>      {
>        const char *q = extract_string (&p);
> @@ -1231,7 +1232,8 @@ main (int argc, char **argv)
>       AIX support needs to know if -shared has been specified before
>       parsing commandline arguments.  */
>
> -  p = getenv ("COLLECT_GCC_OPTIONS");
> +  int add_fsymbolic = -1;
> +  p = gcc_options;
>    while (p && *p)
>      {
>        const char *q = extract_string (&p);
> @@ -1241,6 +1243,9 @@ main (int argc, char **argv)
>         *c_ptr++ = xstrdup (q);
>        if (strcmp (q, "-shared") == 0)
>         shared_obj = 1;
> +      else if (strcmp (q, "-fsymbolic") == 0
> +              || strcmp (q, "-fno-symbolic") == 0)
> +       add_fsymbolic = 0;
>        if (*q == '-' && q[1] == 'B')
>         {
>           *c_ptr++ = xstrdup (q);
> @@ -1278,6 +1283,13 @@ main (int argc, char **argv)
>         {
>           switch (arg[1])
>             {
> +           case 'B':
> +             /* Add -fsymbolic to COLLECT_GCC_OPTIONS if -Bsymbolic is
> +                used.  */
> +             if (add_fsymbolic == -1 && !strcmp (arg + 2, "symbolic"))
> +               add_fsymbolic = 1;
> +             break;
> +
>             case 'd':
>               if (!strcmp (arg, "-debug"))
>                 {
> @@ -1495,6 +1507,41 @@ main (int argc, char **argv)
>         }
>      }
>
> +  if (add_fsymbolic > 0)
> +    {
> +      /* Add -fsymbolic to COLLECT_GCC_OPTIONS.  */
> +      size_t sizeof_env = sizeof "COLLECT_GCC_OPTIONS=";
> +      size_t sizeof_fsymbolic = sizeof "\'-fsymbolic\' ";
> +      size_t len = strlen (gcc_options);
> +      size_t next, start;
> +      char *first;
> +      char *options = (char *) xmalloc (sizeof_env + len +
> +                                       sizeof_fsymbolic - 1);
> +      memcpy (options, "COLLECT_GCC_OPTIONS=", sizeof_env - 1);
> +      first = strchr (gcc_options, '\'');
> +      if (first == NULL)
> +       fatal_error (input_location, "malformed COLLECT_GCC_OPTIONS: %s",
> +                    gcc_options);
> +      next = sizeof_env - 1;
> +      if (first != gcc_options)
> +       {
> +         size_t first_len = first - gcc_options;
> +         memcpy (options + next, gcc_options, first_len);
> +         next += first_len;
> +         start = first_len;
> +       }
> +      else
> +       start = 0;
> +      memcpy (options + next, "\'-fsymbolic\' ", sizeof_fsymbolic - 1);
> +      next += sizeof_fsymbolic - 1;
> +      memcpy (options + next, gcc_options + start, len);
> +      next += len;
> +      options[next] = '\0';
> +      putenv (options);
> +      if (verbose)
> +       fprintf (stderr, "%s\n", options);
> +    }
> +
>  #ifdef COLLECT_EXPORT_LIST
>    /* This is added only for debugging purposes.  */
>    if (debug)
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 5293a25..47baaa3 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -23952,7 +23952,8 @@ which controls how references to global symbols are bound.  The
>  local definitions and external references globally.  This option
>  avoids copy relocations in position-independent executables and
>  optimizes global symbol references in shared library created by
> -linker option, @option{-Bsymbolic}.
> +linker option, @option{-Bsymbolic}.  This option is enabled by default
> +with @option{-flto} when @option{-Bsymbolic} is used.
>
>  @item -fno-ident
>  @opindex fno-ident
> --
> 2.4.3
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/5] Enable -fsymbolic in LTO if -Bsymbolic is used
  2015-10-23  8:57   ` Richard Biener
@ 2015-10-23 17:36     ` H.J. Lu
  0 siblings, 0 replies; 8+ messages in thread
From: H.J. Lu @ 2015-10-23 17:36 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

On Fri, Oct 23, 2015 at 1:52 AM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Thu, Oct 22, 2015 at 7:09 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> When -Bsymbolic is passed to linker, references to global symbols
>> defined in the shared library are resolved locally.  We should pass
>> -fsymbolic to GCC in this case.
>
> Hmm, I think this info should come via the linker plugin, otherwise it
> won't work
> with using plain 'ld' for linking and plugin auto-loading for example.  Maybe
> a special symbol resultion can be used for this?
>

If we do this, change may be very intrusive.  For each defined enum
in ld_plugin_symbol_resolution, we may need another one to indicate
that the definition will be bound symbolically into the shared library for
-Bsymbolic.

-- 
H.J.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-10-23 17:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-22 17:09 [PATCH 0/5] Improve x86 Position-Independent codegen H.J. Lu
2015-10-22 17:09 ` [PATCH 3/5] Properly handle -fno-plt in ix86_expand_call H.J. Lu
2015-10-22 17:09 ` [PATCH 1/5] X86: Optimize access to globals in PIE with copy reloc H.J. Lu
2015-10-22 17:09 ` [PATCH 4/5] Check if x86 binutils supports R_386_GOT32X/R_X86_64_GOTPCRELX H.J. Lu
2015-10-22 17:09 ` [PATCH 5/5] Generate R_386_GOT32x relocation for -fno-plt -fno-pic H.J. Lu
2015-10-22 17:13 ` [PATCH 2/5] Enable -fsymbolic in LTO if -Bsymbolic is used H.J. Lu
2015-10-23  8:57   ` Richard Biener
2015-10-23 17:36     ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).