From patchwork Wed Jul 11 11:21:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tamar Christina X-Patchwork-Id: 942446 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-481343-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="jiCkxtXk"; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=armh.onmicrosoft.com header.i=@armh.onmicrosoft.com header.b="qzv0StrZ"; 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 41Qc8j4hJMz9s01 for ; Wed, 11 Jul 2018 21:21:41 +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:mime-version:content-type; q=dns; s=default; b=dQYE4OZQUaXKhcPB1u5Yz8bVPNmHGN3KZP4FvkNAQe4CWdX4EA BjY2fblNqHy7BJzSeQmzPUHeHDLaNYWx68bWhrNNXdzU1kIUugk/tMObl2ofENOH HKigfNGfO1lx0/uEsHECQDn2qvs36jBcFhr0c+2AZGZohnA0nPyJBbbUs= 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:mime-version:content-type; s= default; bh=YXDLSWt800amQmoApVr53IIdbO8=; b=jiCkxtXkay+1Xq1l37MY qq2G/Tqe4KFPisipnOo70VrcBJqdONKfSU2qZW7U8lryLjE1UOV1YVuuzOH36gch ETXwja+qPoTPT0zx4x47gtnRGuQhkbCYmvoF30bI/VLQQooCr3V0AzpfpJODLKqY nzyx4g1F8QX14uYUhpOElYQ= Received: (qmail 64520 invoked by alias); 11 Jul 2018 11:21:34 -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 63980 invoked by uid 89); 11 Jul 2018 11:21:33 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_LOTSOFHASH, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=1275 X-HELO: EUR02-AM5-obe.outbound.protection.outlook.com Received: from mail-eopbgr00064.outbound.protection.outlook.com (HELO EUR02-AM5-obe.outbound.protection.outlook.com) (40.107.0.64) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 11 Jul 2018 11:21:30 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector1-arm-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=dK7psCjNk17n6Vb2aYO5xU7wZSUW04lwQZnjDFHNSAg=; b=qzv0StrZPD/H11gyA1IYH/NxQUNSY1QV7FV82t/jcd/tLbg6eSJ2axeU45sOFm8Vyak+izMckztWsIT+86JT8k8wyjdUle9Rc9h3Zz87PCpIeAh5Wpa0/vOBIYf/22X2ymEaT1kDthkFUYHjOBxW6wwdMnxnvQOEpluxEF79KQs= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Tamar.Christina@arm.com; Received: from arm.com (217.140.96.140) by DB5PR08MB0744.eurprd08.prod.outlook.com (2a01:111:e400:599c::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.952.17; Wed, 11 Jul 2018 11:21:26 +0000 Date: Wed, 11 Jul 2018 12:21:24 +0100 From: Tamar Christina To: gcc-patches@gcc.gnu.org Cc: nd@arm.com, james.greenhalgh@arm.com, Richard.Earnshaw@arm.com, Marcus.Shawcroft@arm.com Subject: [PATCH][GCC][AArch64] Ensure that outgoing argument size is at least 8 bytes when alloca and stack-clash. [Patch (3/6)] Message-ID: <20180711112121.GA15812@arm.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) Received-SPF: None (protection.outlook.com: arm.com does not designate permitted sender hosts) X-IsSubscribed: yes Hi All, This patch adds a requirement that the number of outgoing arguments for a function is at least 8 bytes when using stack-clash protection. By using this condition we can avoid a check in the alloca code and so have smaller and simpler code there. A simplified version of the AArch64 stack frames is: +-----------------------+ | | | | | | +-----------------------+ |LR | +-----------------------+ |FP | +-----------------------+ |dynamic allocations | ---- expanding area which will push the outgoing +-----------------------+ args down during each allocation. |padding | +-----------------------+ |outgoing stack args | ---- safety buffer of 8 bytes (aligned) +-----------------------+ By always defining an outgoing argument, alloca(0) effectively is safe to probe at $sp due to the reserved buffer being there. It will never corrupt the stack. This is also safe for alloca(x) where x is 0 or x % page_size == 0. In the former it is the same case as alloca(0) while the latter is safe because any allocation pushes the outgoing stack args down: |FP | +-----------------------+ | | |dynamic allocations | ---- alloca (x) | | +-----------------------+ |padding | +-----------------------+ |outgoing stack args | ---- safety buffer of 8 bytes (aligned) +-----------------------+ Which means when you probe for the residual, if it's 0 you'll again just probe in the outgoing stack args range, which we know is non-zero (at least 8 bytes). Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. Target was tested with stack clash on and off by default. Ok for trunk? Thanks, Tamar gcc/ 2018-07-11 Tamar Christina PR target/86486 * config/aarch64/aarch64.h (STACK_CLASH_OUTGOING_ARGS, STACK_DYNAMIC_OFFSET): New. * config/aarch64/aarch64.c (aarch64_layout_frame): Update outgoing args size. (aarch64_stack_clash_protection_alloca_probe_range, TARGET_STACK_CLASH_PROTECTION_ALLOCA_PROBE_RANGE): New. gcc/testsuite/ 2018-07-11 Tamar Christina PR target/86486 * gcc.target/aarch64/stack-check-alloca-1.c: New. * gcc.target/aarch64/stack-check-alloca-10.c: New. * gcc.target/aarch64/stack-check-alloca-2.c: New. * gcc.target/aarch64/stack-check-alloca-3.c: New. * gcc.target/aarch64/stack-check-alloca-4.c: New. * gcc.target/aarch64/stack-check-alloca-5.c: New. * gcc.target/aarch64/stack-check-alloca-6.c: New. * gcc.target/aarch64/stack-check-alloca-7.c: New. * gcc.target/aarch64/stack-check-alloca-8.c: New. * gcc.target/aarch64/stack-check-alloca-9.c: New. * gcc.target/aarch64/stack-check-alloca.h: New. * gcc.target/aarch64/stack-check-14.c: New. * gcc.target/aarch64/stack-check-15.c: New. diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 1345f0eb171d05e2b833935c0a32f79c3db03f99..e9560b53bd8b5761855561dbf82d9c90cc1c282a 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -88,6 +88,10 @@ before probing has to be done for stack clash protection. */ #define STACK_CLASH_CALLER_GUARD 1024 +/* This value represents the minimum amount of bytes we expect the function's + outgoing arguments to be when stack-clash is enabled. */ +#define STACK_CLASH_OUTGOING_ARGS 8 + /* This value controls how many pages we manually unroll the loop for when generating stack clash probes. */ #define STACK_CLASH_MAX_UNROLL_PAGES 4 @@ -1069,4 +1073,15 @@ extern poly_uint16 aarch64_sve_vg; #define REGMODE_NATURAL_SIZE(MODE) aarch64_regmode_natural_size (MODE) +/* Allocate the minimum of STACK_CLASH_OUTGOING_ARGS if stack clash protection + is enabled for the outgoing arguments. This is essential as the extra args + space allows if to skip a check in alloca. */ +#undef STACK_DYNAMIC_OFFSET +#define STACK_DYNAMIC_OFFSET(FUNDECL) \ + ((flag_stack_clash_protection \ + && cfun->calls_alloca \ + && known_lt (crtl->outgoing_args_size, STACK_CLASH_OUTGOING_ARGS)) \ + ? ROUND_UP (STACK_CLASH_OUTGOING_ARGS, STACK_BOUNDARY / BITS_PER_UNIT) \ + : (crtl->outgoing_args_size + STACK_POINTER_OFFSET)) + #endif /* GCC_AARCH64_H */ diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 2f90ec624df89488489ce203022619d5484674e8..ae3c2fb85256b1e95e2242f3f16a027e918ba368 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -4043,6 +4043,10 @@ aarch64_layout_frame (void) cfun->machine->frame.emit_frame_chain = aarch64_needs_frame_chain (); + /* Adjust the outgoing arguments size if required. Keep it in sync with what + the mid-end is doing. */ + crtl->outgoing_args_size = STACK_DYNAMIC_OFFSET (cfun); + #define SLOT_NOT_REQUIRED (-2) #define SLOT_REQUIRED (-1) @@ -4810,6 +4814,16 @@ aarch64_set_handled_components (sbitmap components) cfun->machine->reg_is_wrapped_separately[regno] = true; } +/* On AArch64 we have an ABI defined safe buffer for which we have to do no + probing. */ + +static HOST_WIDE_INT +aarch64_stack_clash_protection_alloca_probe_range (void) +{ + return STACK_CLASH_CALLER_GUARD; +} + + /* Allocate POLY_SIZE bytes of stack space using TEMP1 and TEMP2 as scratch registers. If POLY_SIZE is not large enough to require a probe this function will only adjust the stack. When allocation the stack space @@ -18359,6 +18373,10 @@ aarch64_libgcc_floating_mode_supported_p #undef TARGET_CONSTANT_ALIGNMENT #define TARGET_CONSTANT_ALIGNMENT aarch64_constant_alignment +#undef TARGET_STACK_CLASH_PROTECTION_ALLOCA_PROBE_RANGE +#define TARGET_STACK_CLASH_PROTECTION_ALLOCA_PROBE_RANGE \ + aarch64_stack_clash_protection_alloca_probe_range + #undef TARGET_COMPUTE_PRESSURE_CLASSES #define TARGET_COMPUTE_PRESSURE_CLASSES aarch64_compute_pressure_classes diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-14.c b/gcc/testsuite/gcc.target/aarch64/stack-check-14.c new file mode 100644 index 0000000000000000000000000000000000000000..a573d108a0ce0243e038411aa01eb65dfd81a460 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-14.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +int t1(int); + +int t2(int x) +{ + char *p = __builtin_alloca (4050); + x = t1 (x); + return p[x]; +} + + +/* This test has a constant sized alloca that is smaller than the + probe interval. Only one probe is required since the value is larger + than 1024 bytes but smaller than 63k. + + The form can change quite a bit so we just check for two + probes without looking at the actual address. */ +/* { dg-final { scan-assembler-times "str\\txzr," 1 } } */ + + + diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-15.c b/gcc/testsuite/gcc.target/aarch64/stack-check-15.c new file mode 100644 index 0000000000000000000000000000000000000000..497d83e6596a3cbfce898ca6cda1a65d5fe76d0b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-15.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +int t1(int); + +int t2(int x) +{ + char *p = __builtin_alloca (x); + x = t1 (x); + return p[x]; +} + + +/* This test has a variable sized alloca. It requires 3 probes. + One in the loop, one for the residual, one for when it's < 1024 and one for + when it's not. + + The form can change quite a bit so we just check for two + probes without looking at the actual address. */ +/* { dg-final { scan-assembler-times "str\\txzr," 3 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-1.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-1.c new file mode 100644 index 0000000000000000000000000000000000000000..524713a2c17f51eef0c58851661f9275f24212c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE y +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp, 1024\]} 2 } } */ +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp\]} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-10.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-10.c new file mode 100644 index 0000000000000000000000000000000000000000..24553daf9eedd372c1766b884fd48bebd42de9b2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-10.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 127.5 * 64 * 1024 +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp, 1024\]} 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-2.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-2.c new file mode 100644 index 0000000000000000000000000000000000000000..086fa86a4d2d6bffdca6474afa93c6a508000d58 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-2.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 0 +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-not {str\s+xzr,} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-3.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-3.c new file mode 100644 index 0000000000000000000000000000000000000000..f5c20dad7ace049da0da6bfaafb5ec5e0b985e6e --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-3.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 100 +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp, 8\]} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-4.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-4.c new file mode 100644 index 0000000000000000000000000000000000000000..729d1184bc981a7fb00bc14d118ef526f96360b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-4.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 2 * 1024 +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp, 1024\]} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-5.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-5.c new file mode 100644 index 0000000000000000000000000000000000000000..2c08aa13dcf5cee5fedbd931535ae2776e422ad6 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-5.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 63 * 1024 +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp, 1024\]} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-6.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-6.c new file mode 100644 index 0000000000000000000000000000000000000000..2881e9666cebb1f5f3d5867d23ade5d4b9d8366c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-6.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 63.5 * 1024 +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp, 1024\]} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-7.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-7.c new file mode 100644 index 0000000000000000000000000000000000000000..60f91c1c4dbc13c6f281e5d9ff2d89688dc942c7 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-7.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 64 * 1024 +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp, 1024\]} 1 } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-8.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-8.c new file mode 100644 index 0000000000000000000000000000000000000000..f1da22ccfecda1deb8a8611618b03debedf14426 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-8.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 65 * 1024 +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp, 1024\]} 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-9.c b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-9.c new file mode 100644 index 0000000000000000000000000000000000000000..4b4da189b782c61438715bf5a8f0b791de4e29dd --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca-9.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 127 * 64 * 2014 +#include "stack-check-alloca.h" + +/* { dg-final { scan-assembler-times {str\s+xzr, \[sp, 1024\]} 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-alloca.h b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca.h new file mode 100644 index 0000000000000000000000000000000000000000..a4f7fa2dd351cc7b76784103fc645a066c5ba6e3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-alloca.h @@ -0,0 +1,13 @@ +#include + +__attribute__((noinline, noipa)) +void g (char* ptr, int y) +{ + ptr[y] = '\0'; +} + +void f_caller (int y) +{ + char* pStr = alloca(SIZE); + g (pStr, y); +} \ No newline at end of file