PING [PATCH] i386: Avoid PLT when shadow stack is enabled directly

Message ID CAMe9rOramri685hg_miUqjonaEVBgqk7PF5k-ojzdrq8Y=AXnQ@mail.gmail.com
State New
Headers show
Series
  • PING [PATCH] i386: Avoid PLT when shadow stack is enabled directly
Related show

Commit Message

H.J. Lu Dec. 8, 2017, 1:02 p.m.
On Tue, Oct 24, 2017 at 5:31 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> 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.

>

> OK for trunk if there is no regressions?


Here is the updated patch.

PING.

-- 
H.J.

Patch

From 7a2bea21f2854f1a7ad44c90fbb687f70c039144 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Tue, 24 Oct 2017 05:24:58 -0700
Subject: [PATCH] i386: Avoid PLT when shadow stack is enabled

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.
---
 gcc/config/i386/i386.c                    | 38 +++++++++++++++++++++----------
 gcc/testsuite/gcc.target/i386/pr81780-1.c | 14 ++++++++++++
 gcc/testsuite/gcc.target/i386/pr81780-2.c | 14 ++++++++++++
 gcc/testsuite/gcc.target/i386/pr81780-3.c | 14 ++++++++++++
 gcc/testsuite/gcc.target/i386/pr81780-4.c | 14 ++++++++++++
 5 files changed, 82 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr81780-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr81780-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr81780-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr81780-4.c

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
@@ -28060,6 +28058,29 @@  ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
   return call;
 }
 
+/* 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
@@ -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" } } */
-- 
2.14.3