diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-10-24 05:24:58 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-12-08 05:01:04 -0800 |
commit | 7a2bea21f2854f1a7ad44c90fbb687f70c039144 (patch) | |
tree | 14e1d6368cc4e2c6d2f87ae5b8a0cdcd658713e3 | |
parent | 6dbe66991c8e91806e5e666b400bfce918f618a3 (diff) | |
download | gcc-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.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81780-1.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81780-2.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81780-3.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr81780-4.c | 14 |
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" } } */ |