From patchwork Wed Nov 2 17:08:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Preudhomme X-Patchwork-Id: 80516 Delivered-To: patch@linaro.org Received: by 10.140.97.247 with SMTP id m110csp234203qge; Wed, 2 Nov 2016 10:09:07 -0700 (PDT) X-Received: by 10.98.61.152 with SMTP id x24mr8627622pfj.88.1478106547769; Wed, 02 Nov 2016 10:09:07 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id j8si4095580pgc.227.2016.11.02.10.09.07 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 Nov 2016 10:09:07 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-440236-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-440236-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-440236-patch=linaro.org@gcc.gnu.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=RKM5quyGNCfwUCyJNcsSGyg39AhsHWKqLoa1gC2acz9t0VUmIf A89GpJRE9gHMEuO8ov/VMcFDXAcV4dKk7fAdlpa10w+7aQKBFNesXPST+Ki4dwo7 Xgme+unsl9pMqSZVwGmC6zsI5re+06ooGBn9XmveQqeTbYewIBlIJxibg= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=3N0/7BGggAEKDwDfyY9Vq/fhGeA=; b=F8x/MaXuHVGv00vVlml0 K37xpjEnrLrj6wiavw1HCas62kJRb7o9jTJhNXpVY5Z4z3+eIPKqX27rwzU+xD9M BdG/NHobNQ8Q+d1aK2Nlj7r827YgUswmS7775t3k1DtFZTZ4p0YRZjwtEDY2x16F 5jDQ7YpwejV2h26WWV9X94s= Received: (qmail 67573 invoked by alias); 2 Nov 2016 17:08:49 -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 67018 invoked by uid 89); 2 Nov 2016 17:08:48 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.2 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=Hx-languages-length:2504, LR_REGNUM, lr_regnum X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 02 Nov 2016 17:08:38 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9A42229; Wed, 2 Nov 2016 10:08:36 -0700 (PDT) Received: from [10.2.206.52] (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DADDF3F318; Wed, 2 Nov 2016 10:08:35 -0700 (PDT) To: Kyrill Tkachov , Ramana Radhakrishnan , Richard Earnshaw , "gcc-patches@gcc.gnu.org" From: Thomas Preudhomme Subject: [PATCH, GCC/ARM] Fix PR77933: stack corruption on ARM when using high registers and lr Message-ID: <34d1835c-9eea-1f86-0c93-30aeace74762@foss.arm.com> Date: Wed, 2 Nov 2016 17:08:34 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 X-IsSubscribed: yes Hi, When saving registers, function thumb1_expand_prologue () aims at minimizing the number of push instructions. One of the optimization it does is to push lr alongside high register(s) (after having moved them to low register(s)) when there is no low register to save. The way this is implemented is to add lr to the list of registers that can be pushed just before the push happens. This would then push lr and allows it to be used for further push if there was not enough registers to push all high registers to be pushed. However, the logic that decides what register to move high registers to before being pushed only looks at low registers (see for loop initialization). This means not only that lr is not used for pushing high registers but also that lr is not removed from the list of registers to be pushed when it's not used. This extra lr push is not poped in epilogue leading in stack corruption. This patch changes the loop to iterate over register r0 to lr so as to both fix the stack corruption and reuse lr to push some high register when possible. ChangeLog entry are as follow: *** gcc/ChangeLog *** 2016-11-01 Thomas Preud'homme PR target/77933 * config/arm/arm.c (thumb1_expand_prologue): Also check for lr being a pushable register. *** gcc/testsuite/ChangeLog *** 2016-11-01 Thomas Preud'homme PR target/77933 * gcc.target/arm/pr77933.c: New test. Testing: no regression on arm-none-eabi GCC cross-compiler targeting Cortex-M0 Is this ok for trunk? Best regards, Thomas diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index dd8d5e5db8ca50daab648e58df290969aa794862..22a20caf42389748fc64ee0a3f880c6bea4c8f49 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -24990,7 +24990,7 @@ thumb1_expand_prologue (void) { unsigned long real_regs_mask = 0; - for (regno = LAST_LO_REGNUM; regno >= 0; regno --) + for (regno = LR_REGNUM; regno >= 0; regno --) { if (pushable_regs & (1 << regno)) { diff --git a/gcc/testsuite/gcc.target/arm/pr77933.c b/gcc/testsuite/gcc.target/arm/pr77933.c new file mode 100644 index 0000000000000000000000000000000000000000..cba7e9bb9aa57c6755f79b5ec2ea1a8744e23599 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr77933.c @@ -0,0 +1,9 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +int +main (void) +{ + __asm__ volatile ("" : : : "r8", "r9", "lr"); + return 0; +}