This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Extend -fno-plt to normal non-PIC branches on x86
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Uros Bizjak <ubizjak at gmail dot com>
- Date: Thu, 28 May 2015 10:37:53 -0700
- Subject: [PATCH] Extend -fno-plt to normal non-PIC branches on x86
- Authentication-results: sourceware.org; auth=none
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
This patch extends -fno-plt to normal non-PIC calls 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. A configure time check is
added to verify that 32-bit assembler generates a known relocation
which is different from R_386_GOT32. A new 32-bit relocaton is needed
since "call/jmp *foo@GOT" requires a different relocation from R_386_GOT32
which is used together with a GOT register in "call/jmp *foo@GOT(%reg)".
OK for master?
Thanks.
H.J.
---
* configure.ac (HAVE_AS_INDIRECT_BRANCH_VIA_GOT): New. Defined
if 32-bit assembler generates a known relocation which is
different from R_386_GOT32.
* config.in: Regenerated.
* configure: Likewise.
* config/i386/i386.c (ix86_output_call_insn): Extend -fno-plt
to normal non-PIC branches.
---
gcc/config.in | 14 ++++++++++----
gcc/config/i386/i386.c | 42 ++++++++++++++++++++++++++++++++++++++++--
gcc/configure | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
gcc/configure.ac | 18 +++++++++++++++++-
4 files changed, 113 insertions(+), 8 deletions(-)
diff --git a/gcc/config.in b/gcc/config.in
index daaf906..0ee5c38 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -363,6 +363,12 @@
#endif
+/* Define true if the assembler supports 'call *foo@GOT'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_INDIRECT_BRANCH_VIA_GOT
+#endif
+
+
/* Define if your assembler supports the Sun syntax for cmov. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_IX86_CMOV_SUN_SYNTAX
@@ -686,8 +692,8 @@
#endif
-/* Define to 1 if we found a declaration for 'basename', otherwise define to
- 0. */
+/* Define to 1 if you have the declaration of `basename(const char*)', and to
+ 0 if you don't. */
#ifndef USED_FOR_TARGET
#undef HAVE_DECL_BASENAME
#endif
@@ -963,8 +969,8 @@
#endif
-/* Define to 1 if we found a declaration for 'strstr', otherwise define to 0.
- */
+/* Define to 1 if you have the declaration of `strstr(const char*,const
+ char*)', and to 0 if you don't. */
#ifndef USED_FOR_TARGET
#undef HAVE_DECL_STRSTR
#endif
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e77cd04..5ca19f2 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -25611,7 +25611,26 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
if (SIBLING_CALL_P (insn))
{
if (direct_p)
- xasm = "%!jmp\t%P0";
+ {
+ if (!flag_plt
+ && !flag_pic
+ && !TARGET_MACHO
+ && !TARGET_SEH
+ && !TARGET_PECOFF)
+ {
+ /* Avoid PLT. */
+ if (TARGET_64BIT)
+ xasm = "%!jmp\t*%p0@GOTPCREL(%%rip)";
+ else
+#ifdef HAVE_AS_INDIRECT_BRANCH_VIA_GOT
+ xasm = "%!jmp\t*%p0@GOT";
+#else
+ xasm = "%!jmp\t%P0";
+#endif
+ }
+ else
+ xasm = "%!jmp\t%P0";
+ }
/* SEH epilogue detection requires the indirect branch case
to include REX.W. */
else if (TARGET_SEH)
@@ -25654,7 +25673,26 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
}
if (direct_p)
- xasm = "%!call\t%P0";
+ {
+ if (!flag_plt
+ && !flag_pic
+ && !TARGET_MACHO
+ && !TARGET_SEH
+ && !TARGET_PECOFF)
+ {
+ /* Avoid PLT. */
+ if (TARGET_64BIT)
+ xasm = "%!call\t*%p0@GOTPCREL(%%rip)";
+ else
+#ifdef HAVE_AS_INDIRECT_BRANCH_VIA_GOT
+ xasm = "%!call\t*%p0@GOT";
+#else
+ xasm = "%!call\t%P0";
+#endif
+ }
+ else
+ xasm = "%!call\t%P0";
+ }
else
xasm = "%!call\t%A0";
diff --git a/gcc/configure b/gcc/configure
index a9a76d6..4419035 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -25361,7 +25361,7 @@ $as_echo "#define HAVE_AS_IX86_DIFF_SECT_DELTA 1" >>confdefs.h
fi
- # These two are used unconditionally by i386.[ch]; it is to be defined
+ # These three are used unconditionally by i386.[ch]; it is to be defined
# to 1 if the feature is present, 0 otherwise.
as_ix86_gotoff_in_data_opt=
if test x$gas = xyes; then
@@ -25407,6 +25407,51 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+ as_ix86_indirect_branch_via_got_opt=
+ if test x$gas = xyes; then
+ as_ix86_indirect_branch_via_got_opt="--32"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for call *foo@GOT" >&5
+$as_echo_n "checking assembler for call *foo@GOT... " >&6; }
+if test "${gcc_cv_as_ix86_indirect_branch_via_got+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_indirect_branch_via_got=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 26 \) \* 1000 + 0`
+ then gcc_cv_as_ix86_indirect_branch_via_got=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo ' .text
+ call *foo@GOT' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_indirect_branch_via_got_opt -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ if test x$gcc_cv_readelf != x \
+ && $gcc_cv_readelf -r conftest.o | grep R_386_ | grep -v R_386_GOT32 > /dev/null 2>&1; then
+ gcc_cv_as_ix86_indirect_branch_via_got=yes
+ fi
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_ix86_indirect_branch_via_got" >&5
+$as_echo "$gcc_cv_as_ix86_indirect_branch_via_got" >&6; }
+if test $gcc_cv_as_ix86_indirect_branch_via_got = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AS_INDIRECT_BRANCH_VIA_GOT 1
+_ACEOF
+
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for rep and lock prefix" >&5
$as_echo_n "checking assembler for rep and lock prefix... " >&6; }
if test "${gcc_cv_as_ix86_rep_lock_prefix+set}" = set; then :
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 83f9c09..543e650 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3953,7 +3953,7 @@ foo: nop
[AC_DEFINE(HAVE_AS_IX86_DIFF_SECT_DELTA, 1,
[Define if your assembler supports the subtraction of symbols in different sections.])])
- # These two are used unconditionally by i386.[ch]; it is to be defined
+ # These three are used unconditionally by i386.[ch]; it is to be defined
# to 1 if the feature is present, 0 otherwise.
as_ix86_gotoff_in_data_opt=
if test x$gas = xyes; then
@@ -3971,6 +3971,22 @@ foo: nop
[`if test $gcc_cv_as_ix86_gotoff_in_data = yes; then echo 1; else echo 0; fi`],
[Define true if the assembler supports '.long foo@GOTOFF'.])
+ as_ix86_indirect_branch_via_got_opt=
+ if test x$gas = xyes; then
+ as_ix86_indirect_branch_via_got_opt="--32"
+ fi
+ gcc_GAS_CHECK_FEATURE([call *foo@GOT],
+ gcc_cv_as_ix86_indirect_branch_via_got, [2,26,0],
+ [$as_ix86_indirect_branch_via_got_opt],
+[ .text
+ call *foo@GOT],
+ [if test x$gcc_cv_readelf != x \
+ && $gcc_cv_readelf -r conftest.o | grep R_386_ | grep -v R_386_GOT32 > /dev/null 2>&1; then
+ gcc_cv_as_ix86_indirect_branch_via_got=yes
+ fi],
+ [AC_DEFINE_UNQUOTED(HAVE_AS_INDIRECT_BRANCH_VIA_GOT, 1,
+ [Define true if the assembler supports 'call *foo@GOT'.])])
+
gcc_GAS_CHECK_FEATURE([rep and lock prefix],
gcc_cv_as_ix86_rep_lock_prefix,,,
[rep movsl
--
1.9.3