aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2022-07-14 10:31:21 -0700
committerH.J. Lu <hjl.tools@gmail.com>2022-07-15 16:58:05 -0700
commit2582080f19e8fe9c1204dfb6fecf744311f00777 (patch)
treeccb21c1bca24976e4f9b669fcddf28c46ada2dec
parentfd3d25d6df1cbd385d2834ff3059dfb6905dd75c (diff)
downloadgcc-2582080f19e8fe9c1204dfb6fecf744311f00777.zip
gcc-2582080f19e8fe9c1204dfb6fecf744311f00777.tar.gz
gcc-2582080f19e8fe9c1204dfb6fecf744311f00777.tar.bz2
x86: Disable sibcall if indirect_return attribute doesn't match
When shadow stack is enabled, function with indirect_return attribute may return via indirect jump. In this case, we need to disable sibcall if caller doesn't have indirect_return attribute and indirect branch tracking is enabled since compiler won't generate ENDBR when calling the caller. gcc/ PR target/85620 * config/i386/i386.cc (ix86_function_ok_for_sibcall): Return false if callee has indirect_return attribute and caller doesn't. gcc/testsuite/ PR target/85620 * gcc.target/i386/pr85620-2.c: Updated. * gcc.target/i386/pr85620-5.c: New test. * gcc.target/i386/pr85620-6.c: Likewise. * gcc.target/i386/pr85620-7.c: Likewise.
-rw-r--r--gcc/config/i386/i386.cc10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85620-2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85620-5.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85620-6.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr85620-7.c14
5 files changed, 53 insertions, 1 deletions
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 3a3c729..e03f86d 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -1024,6 +1024,16 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
return false;
}
+ /* Disable sibcall if callee has indirect_return attribute and
+ caller doesn't since callee will return to the caller's caller
+ via an indirect jump. */
+ if (((flag_cf_protection & (CF_RETURN | CF_BRANCH))
+ == (CF_RETURN | CF_BRANCH))
+ && lookup_attribute ("indirect_return", TYPE_ATTRIBUTES (type))
+ && !lookup_attribute ("indirect_return",
+ TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl))))
+ return false;
+
/* Otherwise okay. That also includes certain types of indirect calls. */
return true;
}
diff --git a/gcc/testsuite/gcc.target/i386/pr85620-2.c b/gcc/testsuite/gcc.target/i386/pr85620-2.c
index b2e680f..14ce0ff 100644
--- a/gcc/testsuite/gcc.target/i386/pr85620-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr85620-2.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fcf-protection" } */
-/* { dg-final { scan-assembler-times {\mendbr} 1 } } */
+/* { dg-final { scan-assembler-times {\mendbr} 2 } } */
+/* { dg-final { scan-assembler-not "jmp" } } */
struct ucontext;
diff --git a/gcc/testsuite/gcc.target/i386/pr85620-5.c b/gcc/testsuite/gcc.target/i386/pr85620-5.c
new file mode 100644
index 0000000..0453770
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85620-5.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection" } */
+/* { dg-final { scan-assembler-not "jmp" } } */
+
+struct ucontext;
+
+extern int (*bar) (struct ucontext *) __attribute__((__indirect_return__));
+
+int
+foo (struct ucontext *oucp)
+{
+ return bar (oucp);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr85620-6.c b/gcc/testsuite/gcc.target/i386/pr85620-6.c
new file mode 100644
index 0000000..0b6a64e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85620-6.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection" } */
+/* { dg-final { scan-assembler "jmp" } } */
+
+struct ucontext;
+
+extern int bar (struct ucontext *) __attribute__((__indirect_return__));
+
+__attribute__((__indirect_return__))
+int
+foo (struct ucontext *oucp)
+{
+ return bar (oucp);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr85620-7.c b/gcc/testsuite/gcc.target/i386/pr85620-7.c
new file mode 100644
index 0000000..fa62d56
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85620-7.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection" } */
+/* { dg-final { scan-assembler "jmp" } } */
+
+struct ucontext;
+
+extern int (*bar) (struct ucontext *) __attribute__((__indirect_return__));
+extern int foo (struct ucontext *) __attribute__((__indirect_return__));
+
+int
+foo (struct ucontext *oucp)
+{
+ return bar (oucp);
+}