This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 5/5] Generate R_386_GOT32x relocation for -fno-plt -fno-pic


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]