summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-07-23 13:09:27 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-08-31 09:53:43 -0700
commit2de751f8984eb9df592269ef0b2d02b5d0439811 (patch)
tree909e548044a4a586b944baa1cd10bd6801e379a6
parenta3a53a392e1c45d58013f472963ce27e76b071b5 (diff)
downloadgcc-2de751f8984eb9df592269ef0b2d02b5d0439811.tar.gz
Generate indirect branch relocation via GOT
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" with a new relocation different from R_386_GOT32 to indicate that this relocation applies to indirect branches via GOT. gcc/ * config/i386/i386.c (ix86_nopic_noplt_attribute_p): Check HAVE_LD_IX86_INDBR_RELOC == 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_indbr_reloc): New.
-rw-r--r--gcc/config/i386/i386.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66232-10.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66232-11.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66232-12.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66232-13.c13
-rw-r--r--gcc/testsuite/lib/target-supports.exp52
6 files changed, 121 insertions, 3 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 91e9e29e3a6..43de76ab374 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -25804,7 +25804,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_IX86_INDBR_RELOC == 0)
+ || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF
|| SYMBOL_REF_LOCAL_P (call_op))
return false;
@@ -25829,8 +25830,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
@@ -25874,8 +25881,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 00000000000..078f9560385
--- /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 && indbr_reloc } } } } */
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 00000000000..9a9ccd419a3
--- /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 && indbr_reloc } } } } */
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 00000000000..ee26f5f81a7
--- /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 && indbr_reloc } } } } */
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 00000000000..eb5d6027e2c
--- /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 && indbr_reloc } } } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 363f7fe3877..dff07cbc9d4 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -6395,6 +6395,58 @@ proc check_effective_target_pie_copyreloc { } {
return $pie_copyreloc_available_saved
}
+# Return 1 if the x86 target supports "call *foo@GOT", 0 otherwise.
+# Cache the result.
+
+proc check_effective_target_indbr_reloc { } {
+ global indbr_reloc_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 indbr_reloc_available_saved] {
+ verbose "check_effective_target_indbr_reloc returning saved $indbr_reloc_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_IX86_INDBR_RELOC == 0"
+ puts $f "# error Assembler does not support call *foo@GOT."
+ puts $f "#endif"
+ close $f
+
+ verbose "check_effective_target_indbr_reloc 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_indbr_reloc testfile compilation passed" 2
+ set indbr_reloc_available_saved 1
+ } else {
+ verbose "check_effective_target_indbr_reloc testfile compilation failed" 2
+ set indbr_reloc_available_saved 0
+ }
+ }
+
+ return $indbr_reloc_available_saved
+}
+
# Return 1 if the target uses comdat groups.
proc check_effective_target_comdat_group {} {