summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-10-24 05:24:58 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-12-08 05:01:04 -0800
commit7a2bea21f2854f1a7ad44c90fbb687f70c039144 (patch)
tree14e1d6368cc4e2c6d2f87ae5b8a0cdcd658713e3
parent6dbe66991c8e91806e5e666b400bfce918f618a3 (diff)
downloadgcc-hjl/pr81780.tar.gz
i386: Avoid PLT when shadow stack is enabledhjl/pr81780
PLT should be avoided with shadow stack in 32-bit mode if more than 2 parameters are passed in registers since only 2 parameters can be passed in registers for external function calls via PLT with shadow stack enabled. gcc/ PR target/81780 * config/i386/i386.c (ix86_noplt_attribute_p): New function. (ix86_expand_call): Use it. (ix86_nopic_noplt_attribute_p): Likewise. gcc/testsuite/ PR target/81780 * gcc.target/i386/pr81780-1.c: New test. * gcc.target/i386/pr81780-2.c: Likewise. * gcc.target/i386/pr81780-3.c: Likewise. * gcc.target/i386/pr81780-4.c: Likewise.
-rw-r--r--gcc/config/i386/i386.c38
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81780-1.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81780-2.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81780-3.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81780-4.c14
5 files changed, 82 insertions, 12 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e323102cef5..a7df509a43e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -102,6 +102,7 @@ static bool ix86_save_reg (unsigned int, bool, bool);
static bool ix86_function_naked (const_tree);
static bool ix86_notrack_prefixed_insn_p (rtx);
static void ix86_emit_restore_reg_using_pop (rtx);
+static bool ix86_noplt_attribute_p (rtx);
#ifndef CHECK_STACK_LIMIT
@@ -27880,10 +27881,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
&& GET_CODE (addr) == SYMBOL_REF
&& !SYMBOL_REF_LOCAL_P (addr))
{
- if (flag_plt
- && (SYMBOL_REF_DECL (addr) == NULL_TREE
- || !lookup_attribute ("noplt",
- DECL_ATTRIBUTES (SYMBOL_REF_DECL (addr)))))
+ if (!ix86_noplt_attribute_p (addr))
{
if (!TARGET_64BIT
|| (ix86_cmodel == CM_LARGE_PIC
@@ -28061,6 +28059,29 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
}
/* Return true if the function being called was marked with attribute
+ "noplt" or using -fno-plt. PLT should be avoided with shadow stack
+ if more than 2 parameters are passed in registers since only 2
+ parameters can be passed in registers for external function calls
+ via PLT with shadow stack enabled. */
+
+static bool
+ix86_noplt_attribute_p (rtx call_op)
+{
+ if (!flag_plt)
+ return true;
+
+ tree decl = SYMBOL_REF_DECL (call_op);
+ if (!decl)
+ return false;
+
+ return (lookup_attribute ("noplt", DECL_ATTRIBUTES (decl))
+ || (!TARGET_64BIT
+ && (flag_cf_protection & CF_RETURN)
+ && TARGET_SHSTK
+ && ix86_function_regparm (TREE_TYPE (decl), decl) > 2));
+}
+
+/* Return true if the function being called was marked with attribute
"noplt" or using -fno-plt and we are compiling for non-PIC. We need
to handle the non-PIC case in the backend because there is no easy
interface for the front-end to force non-PLT calls to use the GOT.
@@ -28076,14 +28097,7 @@ ix86_nopic_noplt_attribute_p (rtx call_op)
|| SYMBOL_REF_LOCAL_P (call_op))
return false;
- tree symbol_decl = SYMBOL_REF_DECL (call_op);
-
- if (!flag_plt
- || (symbol_decl != NULL_TREE
- && lookup_attribute ("noplt", DECL_ATTRIBUTES (symbol_decl))))
- return true;
-
- return false;
+ return ix86_noplt_attribute_p (call_op);
}
/* Output the assembly for a call instruction. */
diff --git a/gcc/testsuite/gcc.target/i386/pr81780-1.c b/gcc/testsuite/gcc.target/i386/pr81780-1.c
new file mode 100644
index 00000000000..f5a28020782
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81780-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { *-*-linux* && ia32 } } } */
+/* { dg-require-effective-target got32x_reloc } */
+/* { dg-options "-fcf-protection -mcet -O2 -fno-pic -fplt" } */
+
+extern void bar (int) __attribute__ ((regparm (3)));
+
+int
+foo (int i)
+{
+ bar (i);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81780-2.c b/gcc/testsuite/gcc.target/i386/pr81780-2.c
new file mode 100644
index 00000000000..59f4c5f4d70
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81780-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { *-*-linux* && ia32 } } } */
+/* { dg-require-effective-target got32x_reloc } */
+/* { dg-options "-fcf-protection -mcet -O2 -fno-pic -fplt -mregparm=3" } */
+
+extern void bar (int);
+
+int
+foo (int i)
+{
+ bar (i);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81780-3.c b/gcc/testsuite/gcc.target/i386/pr81780-3.c
new file mode 100644
index 00000000000..3bc0c197fbe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81780-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { *-*-linux* && ia32 } } } */
+/* { dg-require-effective-target got32x_reloc } */
+/* { dg-options "-fcf-protection -mcet -O2 -fplt -fpic" } */
+
+extern void bar (int) __attribute__ ((regparm (3)));
+
+int
+foo (int i)
+{
+ bar (i);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81780-4.c b/gcc/testsuite/gcc.target/i386/pr81780-4.c
new file mode 100644
index 00000000000..875dff1765c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81780-4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { *-*-linux* && ia32 } } } */
+/* { dg-require-effective-target got32x_reloc } */
+/* { dg-options "-fcf-protection -mcet -O2 -fpic -fplt -mregparm=3" } */
+
+extern void bar (int);
+
+int
+foo (int i)
+{
+ bar (i);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" } } */