From patchwork Sun Mar 1 22:22:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 444968 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 9783F140172 for ; Mon, 2 Mar 2015 19:41:52 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass reason="1024-bit key; unprotected key" header.d=sourceware.org header.i=@sourceware.org header.b=WmhkuJ96; dkim-adsp=none (unprotected policy); dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:in-reply-to:references:from:date :subject:to; q=dns; s=default; b=g3L/UxobE7mi//sA0/B0+mZqpD3WT9/ N2kq82TrehkwjdlqfLEFSXz6pHgCBfRZkzrCYUTGcEnvCVZATiBtkfbDJw4vlEpk +RVwic1eZ00IbVPnuaYguvrzlcjP3kocLtpU/e4qKIDioOB6A91z3fE2MxQ94waz gb9ggVKZzZ/w= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:in-reply-to:references:from:date :subject:to; s=default; bh=2k+C/71yjPYbhVsjUma1VX2SwcA=; b=Wmhku J965e3ZaGqD/FxuhscIn2dqvIlFmfUcPnM5FYqWUd9g+HC2hlypGvM7xtpnldlU4 V9S9s6uAUpFc6EpWzdwI+70g6WBJ6QGJeELPY4z1pE5mJAXJH30NMhiB13qr4vmY syrdS6l8wTyIdQnox8hqXeX7seJ/ZoYWp8SFgc= Received: (qmail 78920 invoked by alias); 2 Mar 2015 08:40:38 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 78813 invoked by uid 89); 2 Mar 2015 08:40:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL, BAYES_00, DATE_IN_PAST_06_12, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Message-Id: In-Reply-To: References: From: Florian Weimer Date: Sun, 1 Mar 2015 23:22:45 +0100 Subject: [PATCH 25/25] Remove macros extend_alloca, extend_alloca_account [BZ #18023] To: libc-alpha@sourceware.org And also the helper macro stackinfo_alloca_round. extend_alloca simply does not work on x86_64 and current i386 because its peculiar stack alignment rules. Here's an analysis of the _dl_fini situation (before the removal of extend_alloca). Dump of assembler code for function _dl_fini: <+0>: push %rbp <+1>: mov %rsp,%rbp <+4>: push %r15 <+6>: push %r14 <+8>: push %r13 <+10>: push %r12 <+12>: push %rbx <+13>: sub $0x38,%rsp The function pushes 6 registers on the stack and allocates 0x38 bytes, which means that %rsp is a multiple of 16 after function prologue. The initial alloca allocation does not change %rsp alignment: <+210>: shr $0x4,%rcx <+214>: shl $0x4,%rcx <+218>: sub %rcx,%rsp %r15 is the address of the previous stack allocation, it is used below. This is the extend_alloca reallocation branch: <+734>: add $0xf,%rdx <+738>: and $0xfffffffffffffff0,%rdx <+742>: lea 0x1e(%rdx),%rcx <+746>: shr $0x4,%rcx <+750>: shl $0x4,%rcx <+754>: sub %rcx,%rsp <+757>: lea 0xf(%rsp),%rcx <+762>: and $0xfffffffffffffff0,%rcx <+766>: lea (%rcx,%rdx,1),%rsi <+770>: cmp %rsi,%r15 <+773>: je 0x7f963940b673 <_dl_fini+787> <+775>: mov %rdx,-0x58(%rbp) <+787>: add %rdx,-0x58(%rbp) (a) %rdx, the new requested size, is rounded up to a multiple of 16 (+734, %+738), and the result is stored in %rdx@738. (b) %rdx@738 + 31 is rounded down to a multiple of 16, the result is stored in rcx@750 (+742, +746, +750). So %rcx@750 == %rdx@738 + 16. (c) %rcx@750 bytes are allocated on the stack (+754). %rsp is rounded upwards to a multiple of 16, result is stored in %rcx@762 (+757, +762). This does not change the value of %rsp because it already was a multiple of 16. (d) %rsi@766 == %rcx@762 + %rdx@738 is compared against %r15. But this comparison is always false because we allocated 16 extra bytes on the stack in (b), which were reserved for the alignment in (c), but in fact unused. We are left with a gap in stack usage, and the comparison is always false. (@XXX refers to register values after executing the instruction at offset +XXX.) If the alignment gap was actually used because of different alignment for %rsp, then the comparison failure would still occur because the gap would not have been added after this reallocation, but before the previous allocation. As a result, extend_alloca is never able to merge allocations. It also turns out that the interface is difficult to use, especially in cojunction with alloca account (which is rarely optional). --- include/alloca.h | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/include/alloca.h b/include/alloca.h index 0150025..f190b87 100644 --- a/include/alloca.h +++ b/include/alloca.h @@ -20,57 +20,17 @@ libc_hidden_proto (__libc_alloca_cutoff) #include -#ifndef stackinfo_alloca_round -# define stackinfo_alloca_round(l) (((l) + 15) & -16) -#endif - -#if _STACK_GROWS_DOWN -# define extend_alloca(buf, len, newlen) \ - (__typeof (buf)) ({ size_t __newlen = stackinfo_alloca_round (newlen); \ - char *__newbuf = __alloca (__newlen); \ - if (__newbuf + __newlen == (char *) (buf)) \ - len += __newlen; \ - else \ - len = __newlen; \ - __newbuf; }) -#elif _STACK_GROWS_UP -# define extend_alloca(buf, len, newlen) \ - (__typeof (buf)) ({ size_t __newlen = stackinfo_alloca_round (newlen); \ - char *__newbuf = __alloca (__newlen); \ - char *__buf = (char *) (buf); \ - if (__buf + len == __newbuf) \ - { \ - len += __newlen; \ - __newbuf = __buf; \ - } \ - else \ - len = __newlen; \ - __newbuf; }) -#else -# define extend_alloca(buf, len, newlen) \ - __alloca (((len) = (newlen))) -#endif - #if defined stackinfo_get_sp && defined stackinfo_sub_sp # define alloca_account(size, avar) \ ({ void *old__ = stackinfo_get_sp (); \ void *m__ = __alloca (size); \ avar += stackinfo_sub_sp (old__); \ m__; }) -# define extend_alloca_account(buf, len, newlen, avar) \ - ({ void *old__ = stackinfo_get_sp (); \ - void *m__ = extend_alloca (buf, len, newlen); \ - avar += stackinfo_sub_sp (old__); \ - m__; }) #else # define alloca_account(size, avar) \ ({ size_t s__ = (size); \ avar += s__; \ __alloca (s__); }) -# define extend_alloca_account(buf, len, newlen, avar) \ - ({ size_t s__ = (newlen); \ - avar += s__; \ - extend_alloca (buf, len, s__); }) #endif #endif