From patchwork Sun Apr 15 10:57:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 898238 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-476400-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=intel.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="XktLav7O"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40P7lZ03sHz9s0t for ; Sun, 15 Apr 2018 20:58:01 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=xIVMlyEhnxgGNfLiPt+LRfk/epTs+ OUNRl+miIZyMYEgAqdoA59OcSCvhRdqhJpRGO3nx6KAl4eUIdLtJTOWHQYZNQ4+y bvNcCxme+0aqnvALhI7/p12Pm9BVCaMPiNSaHfg0oFC6rzDqL47DeRrrsXcnV+hj /nMRwNzWSs2FII= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=FdWQWaQYoHOa9r2sMhVLxsjq/kk=; b=Xkt Lav7OZwMTQ1qSTDdOabmp6B3wvElQlYdDjqrOKBrtHMwllFn2MDx1axIY1Zm3PEN vmsYap79HnzfB7VuiDO6TxkyGGZ/7G9fBqxtljqOLFwmiYmkdH3lj5WfiYfnlQ1g Q+Mg+tGl21UGqgemWgYCDxo6c9yZ1RmLgcQRvBH4= Received: (qmail 129903 invoked by alias); 15 Apr 2018 10:57:54 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 129893 invoked by uid 89); 15 Apr 2018 10:57:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, NO_DNS_FOR_FROM autolearn=ham version=3.3.2 spammy=mx32, multi, a1, sk:stack_p X-HELO: mga02.intel.com Received: from mga02.intel.com (HELO mga02.intel.com) (134.134.136.20) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 15 Apr 2018 10:57:51 +0000 X-Amp-Result: UNSCANNABLE X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Apr 2018 03:57:49 -0700 X-ExtLoop1: 1 Received: from gnu-cfl-1.sc.intel.com ([172.25.70.237]) by orsmga004.jf.intel.com with ESMTP; 15 Apr 2018 03:57:49 -0700 Received: by gnu-cfl-1.sc.intel.com (Postfix, from userid 1000) id 5E255440ADC; Sun, 15 Apr 2018 03:57:49 -0700 (PDT) Date: Sun, 15 Apr 2018 03:57:49 -0700 From: "H.J. Lu" To: gcc-patches@gcc.gnu.org Cc: Uros Bizjak , Igor Tsimbalist Subject: [PATCH] i386: Add save_stack_nonlocal and restore_stack_nonlocal Message-ID: <20180415105749.GA26549@intel.com> Reply-To: "H.J. Lu" MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.2 (2017-12-15) Define STACK_SAVEAREA_MODE to hold both shadow stack and stack pointers. Replace builtin_setjmp_setup and builtin_longjmp with save_stack_nonlocal and restore_stack_nonlocal to support both builtin setjmp/longjmp as well as non-local goto in nested functions. OK for trunk? H.J. ---- gcc/ PR target/85397 * config/i386/i386.h (STACK_SAVEAREA_MODE): New. * config/i386/i386.md (builtin_setjmp_setup): Removed. (builtin_longjmp): Likewise. (save_stack_nonlocal): New pattern. (restore_stack_nonlocal): Likewise. gcc/testsuite/ PR target/85397 * gcc.dg/torture/pr85397-1.c: New test. * gcc.target/i386/cet-sjlj-6a.c: Adjusted. * gcc.target/i386/cet-sjlj-6b.c: Likewise. --- gcc/config/i386/i386.h | 11 +++ gcc/config/i386/i386.md | 107 +++++++++++++--------------- gcc/testsuite/gcc.dg/torture/pr85397-1.c | 29 ++++++++ gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c | 4 +- gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c | 4 +- 5 files changed, 92 insertions(+), 63 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr85397-1.c diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index c7f9b4551b3..c45d22cae98 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1943,6 +1943,17 @@ do { \ between pointers and any other objects of this machine mode. */ #define Pmode (ix86_pmode == PMODE_DI ? DImode : SImode) +/* Supply a definition of STACK_SAVEAREA_MODE for emit_stack_save. + NONLOCAL needs space to save both shadow stack and stack pointers. + + FIXME: We only need to save and restore stack pointer in ptr_mode. + But expand_builtin_setjmp_setup and expand_builtin_longjmp use Pmode + to save and restore stack pointer. See + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84150 + */ +#define STACK_SAVEAREA_MODE(LEVEL) \ + ((LEVEL) == SAVE_NONLOCAL ? (TARGET_64BIT ? TImode : DImode) : Pmode) + /* Specify the machine mode that bounds have. */ #define BNDmode (ix86_pmode == PMODE_DI ? BND64mode : BND32mode) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 352212094ec..841d0a77ecc 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -18485,29 +18485,6 @@ "* return output_probe_stack_range (operands[0], operands[2]);" [(set_attr "type" "multi")]) -/* Additional processing for builtin_setjmp. Store the shadow stack pointer - as a forth element in jmpbuf. */ -(define_expand "builtin_setjmp_setup" - [(match_operand 0 "address_operand")] - "TARGET_SHSTK" -{ - if (flag_cf_protection & CF_RETURN) - { - rtx mem, reg_ssp; - - mem = gen_rtx_MEM (word_mode, - plus_constant (Pmode, operands[0], - 3 * GET_MODE_SIZE (ptr_mode))); - reg_ssp = gen_reg_rtx (word_mode); - emit_insn (gen_rtx_SET (reg_ssp, const0_rtx)); - emit_insn ((word_mode == SImode) - ? gen_rdsspsi (reg_ssp) - : gen_rdsspdi (reg_ssp)); - emit_move_insn (mem, reg_ssp); - } - DONE; -}) - (define_expand "builtin_setjmp_receiver" [(label_ref (match_operand 0))] "!TARGET_64BIT && flag_pic" @@ -18528,19 +18505,46 @@ DONE; }) -(define_expand "builtin_longjmp" - [(match_operand 0 "address_operand")] - "TARGET_SHSTK" +(define_expand "save_stack_nonlocal" + [(set (match_operand 0 "memory_operand") + (match_operand 1 "register_operand"))] + "" { - rtx fp, lab, stack; - rtx flags, jump, noadj_label, inc_label, loop_label; - rtx reg_adj, reg_ssp, mem_buf, tmp, clob; - machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); + rtx stack_slot; + if (TARGET_SHSTK && (flag_cf_protection & CF_RETURN)) + { + /* Copy shadow stack pointer to the first slot and stack ppointer + to the second slot. */ + rtx ssp_slot = adjust_address (operands[0], word_mode, 0); + stack_slot = adjust_address (operands[0], Pmode, UNITS_PER_WORD); + rtx ssp = gen_reg_rtx (word_mode); + emit_insn ((word_mode == SImode) + ? gen_rdsspsi (ssp) + : gen_rdsspdi (ssp)); + emit_move_insn (ssp_slot, ssp); + } + else + stack_slot = adjust_address (operands[0], Pmode, 0); + emit_move_insn (stack_slot, operands[1]); + DONE; +}) - /* Adjust the shadow stack pointer (ssp) to the value saved in the - jmp_buf. The saving was done in the builtin_setjmp_setup. */ - if (flag_cf_protection & CF_RETURN) +(define_expand "restore_stack_nonlocal" + [(set (match_operand 0 "register_operand" "") + (match_operand 1 "memory_operand" ""))] + "" +{ + rtx stack_slot; + if (TARGET_SHSTK && (flag_cf_protection & CF_RETURN)) { + /* Restore shadow stack pointer from the first slot and stack + pointer from the second slot. */ + rtx ssp_slot = adjust_address (operands[1], word_mode, 0); + stack_slot = adjust_address (operands[1], Pmode, UNITS_PER_WORD); + + rtx flags, jump, noadj_label, inc_label, loop_label; + rtx reg_adj, reg_ssp, tmp, clob; + /* Get the current shadow stack pointer. The code below will check if SHSTK feature is enabled. If it is not enabled the RDSSP instruction is a NOP. */ @@ -18549,13 +18553,11 @@ emit_insn ((word_mode == SImode) ? gen_rdsspsi (reg_ssp) : gen_rdsspdi (reg_ssp)); - mem_buf = gen_rtx_MEM (word_mode, - plus_constant (Pmode, operands[0], - 3 * GET_MODE_SIZE (ptr_mode))); /* Compare through substraction the saved and the current ssp to decide if ssp has to be adjusted. */ - tmp = gen_rtx_SET (reg_ssp, gen_rtx_MINUS (word_mode, reg_ssp, mem_buf)); + tmp = gen_rtx_SET (reg_ssp, gen_rtx_MINUS (word_mode, reg_ssp, + ssp_slot)); clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob)); emit_insn (tmp); @@ -18595,14 +18597,17 @@ jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); JUMP_LABEL (jump) = inc_label; + rtx reg_255 = gen_reg_rtx (word_mode); + emit_move_insn (reg_255, GEN_INT (255)); + /* Adjust the ssp in a loop. */ loop_label = gen_label_rtx (); emit_label (loop_label); LABEL_NUSES (loop_label) = 1; emit_insn ((word_mode == SImode) - ? gen_incsspsi (reg_ssp) - : gen_incsspdi (reg_ssp)); + ? gen_incsspsi (reg_255) + : gen_incsspdi (reg_255)); tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (ptr_mode, reg_adj, GEN_INT (255))); @@ -18631,26 +18636,10 @@ emit_label (noadj_label); LABEL_NUSES (noadj_label) = 1; } - - /* This code is the same as in expand_buildin_longjmp. */ - fp = gen_rtx_MEM (ptr_mode, operands[0]); - lab = gen_rtx_MEM (ptr_mode, plus_constant (Pmode, operands[0], - GET_MODE_SIZE (ptr_mode))); - stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, operands[0], - 2 * GET_MODE_SIZE (ptr_mode))); - lab = copy_to_reg (lab); - - emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); - emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); - - if (GET_MODE (fp) != Pmode) - fp = convert_to_mode (Pmode, fp, 1); - emit_move_insn (hard_frame_pointer_rtx, fp); - emit_stack_restore (SAVE_NONLOCAL, stack); - - emit_use (hard_frame_pointer_rtx); - emit_use (stack_pointer_rtx); - emit_indirect_jump (lab); + else + stack_slot = adjust_address (operands[1], Pmode, 0); + emit_move_insn (operands[0], stack_slot); + DONE; }) diff --git a/gcc/testsuite/gcc.dg/torture/pr85397-1.c b/gcc/testsuite/gcc.dg/torture/pr85397-1.c new file mode 100644 index 00000000000..65085240266 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr85397-1.c @@ -0,0 +1,29 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target cet } */ +/* { dg-additional-options "-fcf-protection -mcet" } */ + +#define DEPTH 1000 + +int +x(int a) +{ + __label__ xlab; + void y(int a) + { + if (a==0) + goto xlab; + y (a-1); + } + y (a); + xlab:; + return a; +} + +int +main () +{ + if (x (DEPTH) != DEPTH) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c index 8410ff99b47..87fe2e6dc67 100644 --- a/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c +++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c @@ -2,8 +2,8 @@ /* { dg-require-effective-target maybe_x32 } */ /* { dg-options "-O -maddress-mode=short -fcf-protection -mcet -mx32" } */ /* { dg-final { scan-assembler-times "endbr64" 2 } } */ -/* { dg-final { scan-assembler-times "movq\t.*buf\\+12" 1 } } */ -/* { dg-final { scan-assembler-times "subq\tbuf\\+12" 1 } } */ +/* { dg-final { scan-assembler-times "movq\t.*buf\\+8" 1 } } */ +/* { dg-final { scan-assembler-times "subq\tbuf\\+8" 1 } } */ /* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */ /* { dg-final { scan-assembler-times "rdsspq" 2 } } */ /* { dg-final { scan-assembler-times "incsspq" 2 } } */ diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c index ce111631ac1..b3866d52946 100644 --- a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c +++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c @@ -1,8 +1,8 @@ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-O -maddress-mode=long -fcf-protection -mcet -mx32" } */ /* { dg-final { scan-assembler-times "endbr64" 2 } } */ -/* { dg-final { scan-assembler-times "movq\t.*buf\\+12" 1 } } */ -/* { dg-final { scan-assembler-times "subq\tbuf\\+12" 1 } } */ +/* { dg-final { scan-assembler-times "movq\t.*buf\\+16" 1 } } */ +/* { dg-final { scan-assembler-times "subq\tbuf\\+16" 1 } } */ /* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */ /* { dg-final { scan-assembler-times "rdsspq" 2 } } */ /* { dg-final { scan-assembler-times "incsspq" 2 } } */