From patchwork Fri Nov 5 23:48:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 70309 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id DF752B7108 for ; Sat, 6 Nov 2010 10:48:55 +1100 (EST) Received: (qmail 23622 invoked by alias); 5 Nov 2010 23:48:53 -0000 Received: (qmail 23570 invoked by uid 22791); 5 Nov 2010 23:48:50 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, TW_AV, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 05 Nov 2010 23:48:44 +0000 Received: from kpbe16.cbf.corp.google.com (kpbe16.cbf.corp.google.com [172.25.105.80]) by smtp-out.google.com with ESMTP id oA5Nmgqn021922 for ; Fri, 5 Nov 2010 16:48:42 -0700 Received: from pva4 (pva4.prod.google.com [10.241.209.4]) by kpbe16.cbf.corp.google.com with ESMTP id oA5NmZYX032653 for ; Fri, 5 Nov 2010 16:48:35 -0700 Received: by pva4 with SMTP id 4so1313767pva.37 for ; Fri, 05 Nov 2010 16:48:35 -0700 (PDT) Received: by 10.142.217.16 with SMTP id p16mr1871819wfg.279.1289000915319; Fri, 05 Nov 2010 16:48:35 -0700 (PDT) Received: from coign.google.com ([67.218.104.238]) by mx.google.com with ESMTPS id v19sm2544080wfh.0.2010.11.05.16.48.32 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 05 Nov 2010 16:48:34 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org Subject: PATCH COMMITTED: Fix PR 46084: Allow for alignment with split stack Date: Fri, 05 Nov 2010 16:48:28 -0700 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true X-IsSubscribed: yes 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 When doing dynamic stack allocation when using -fsplit-stack, the new space is allocated using malloc. The alignment returned by malloc may be less than the expected alignment of the stack, as is indeed the case on x86. Since the dynamic stack allocator aligns the address it receives, this can cause the code to overrun the end of the buffer allocated by malloc. This is the problem behind PR 46084. This patch fixes the problem by simply requesting extra space when allocating from the heap, enough extra space to ensure that the alignment will not cause a buffer overrun. Bootstrapped and tested on x86_64-unknown-linux-gnu. Committed to mainline. Ian gcc/: 2010-11-05 Ian Lance Taylor PR target/46084 * explow.c (allocate_dynamic_stack_space): If flag_split_stack, request enough additional space for alignment, and force alignment. gcc/testsuite: 2010-11-05 Ian Lance Taylor PR target/46084 * gcc.target/i386/pr46084.c: New test. Index: gcc/explow.c =================================================================== --- gcc/explow.c (revision 166300) +++ gcc/explow.c (working copy) @@ -1340,7 +1340,7 @@ allocate_dynamic_stack_space (rtx size, least it doesn't cause a stack overflow. */ if (flag_split_stack) { - rtx available_label, space, func; + rtx available_label, ask, space, func; available_label = NULL_RTX; @@ -1355,10 +1355,19 @@ allocate_dynamic_stack_space (rtx size, } #endif + /* The __morestack_allocate_stack_space function will allocate + memory using malloc. We don't know that the alignment of the + memory returned by malloc will meet REQUIRED_ALIGN. Increase + SIZE to make sure we allocate enough space. */ + ask = expand_binop (Pmode, add_optab, size, + GEN_INT (required_align / BITS_PER_UNIT - 1), + NULL_RTX, 1, OPTAB_LIB_WIDEN); + must_align = true; + func = init_one_libfunc ("__morestack_allocate_stack_space"); space = emit_library_call_value (func, target, LCT_NORMAL, Pmode, - 1, size, Pmode); + 1, ask, Pmode); if (available_label == NULL_RTX) return space; Index: gcc/testsuite/gcc.target/i386/pr46084.c =================================================================== --- gcc/testsuite/gcc.target/i386/pr46084.c (revision 0) +++ gcc/testsuite/gcc.target/i386/pr46084.c (revision 0) @@ -0,0 +1,69 @@ +/* This test needs to use setrlimit to set the stack size, so it can + only run on Unix. */ +/* { dg-do run { target *-*-linux* *-*-solaris* *-*-darwin* } } */ +/* { dg-require-effective-target avx } */ +/* { dg-require-effective-target split_stack } */ +/* { dg-options "-fsplit-stack -O2 -mavx" } */ + +#include +#include +#include +#include + +/* Use a noinline function to ensure that the buffer is not removed + from the stack. */ +static void use_buffer (char *buf, size_t) __attribute__ ((noinline)); +static void +use_buffer (char *buf, size_t c) +{ + size_t i; + + for (i = 0; i < c; ++i) + buf[i] = (char) i; +} + +/* Each recursive call uses 10 * i bytes. We call it 1000 times, + using a total of 5,000,000 bytes. If -fsplit-stack is not working, + that will overflow our stack limit. */ + +static void +down1 (int i) +{ + char buf[10 * i]; + + if (i > 0) + { + use_buffer (buf, 10 * i); + down1 (i - 1); + } +} + +/* Same thing, using alloca. */ + +static void +down2 (int i) +{ + char *buf = alloca (10 * i); + + if (i > 0) + { + use_buffer (buf, 10 * i); + down2 (i - 1); + } +} + +int +main (void) +{ + struct rlimit r; + + /* We set a stack limit because we are usually invoked via make, and + make sets the stack limit to be as large as possible. */ + r.rlim_cur = 8192 * 1024; + r.rlim_max = 8192 * 1024; + if (setrlimit (RLIMIT_STACK, &r) != 0) + abort (); + down1 (1000); + down2 (1000); + return 0; +}