aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2018-07-04 03:01:33 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2018-07-03 20:01:33 -0700
commitebaa4deaf9f3bec32443e60fe74fce14686b4706 (patch)
treefb0135f43e72e4ffd528ad5806930aa0f186f804 /gcc/config
parent7422f0ff39697b53ad599834647c56cb0cb3c3a3 (diff)
downloadgcc-ebaa4deaf9f3bec32443e60fe74fce14686b4706.zip
gcc-ebaa4deaf9f3bec32443e60fe74fce14686b4706.tar.gz
gcc-ebaa4deaf9f3bec32443e60fe74fce14686b4706.tar.bz2
i386: Add indirect_return function attribute
On x86, swapcontext may return via indirect branch when shadow stack is enabled. To support code instrumentation of control-flow transfers with -fcf-protection, add indirect_return function attribute to inform compiler that a function may return via indirect branch. Note: Unlike setjmp, swapcontext only returns once. Mark it return twice will unnecessarily disable compiler optimization as shown in the testcase here. gcc/ PR target/85620 * config/i386/i386.c (rest_of_insert_endbranch): Also generate ENDBRANCH for non-tail call which may return via indirect branch. * doc/extend.texi: Document indirect_return attribute. gcc/testsuite/ PR target/85620 * gcc.target/i386/pr85620-1.c: New test. * gcc.target/i386/pr85620-2.c: Likewise. * gcc.target/i386/pr85620-3.c: Likewise. * gcc.target/i386/pr85620-4.c: Likewise. From-SVN: r262370
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e6d1763..41461d5 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2621,7 +2621,26 @@ rest_of_insert_endbranch (void)
{
if (CALL_P (insn))
{
- if (find_reg_note (insn, REG_SETJMP, NULL) == NULL)
+ bool need_endbr;
+ need_endbr = find_reg_note (insn, REG_SETJMP, NULL) != NULL;
+ if (!need_endbr && !SIBLING_CALL_P (insn))
+ {
+ rtx call = get_call_rtx_from (insn);
+ rtx fnaddr = XEXP (call, 0);
+
+ /* Also generate ENDBRANCH for non-tail call which
+ may return via indirect branch. */
+ if (MEM_P (fnaddr)
+ && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
+ {
+ tree fndecl = SYMBOL_REF_DECL (XEXP (fnaddr, 0));
+ if (fndecl
+ && lookup_attribute ("indirect_return",
+ DECL_ATTRIBUTES (fndecl)))
+ need_endbr = true;
+ }
+ }
+ if (!need_endbr)
continue;
/* Generate ENDBRANCH after CALL, which can return more than
twice, setjmp-like functions. */
@@ -45897,6 +45916,8 @@ static const struct attribute_spec ix86_attribute_table[] =
ix86_handle_fndecl_attribute, NULL },
{ "function_return", 1, 1, true, false, false, false,
ix86_handle_fndecl_attribute, NULL },
+ { "indirect_return", 0, 0, true, false, false, false,
+ ix86_handle_fndecl_attribute, NULL },
/* End element. */
{ NULL, 0, 0, false, false, false, false, NULL, NULL }