From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753700AbdHKQ5S (ORCPT ); Fri, 11 Aug 2017 12:57:18 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52028 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753571AbdHKQ5P (ORCPT ); Fri, 11 Aug 2017 12:57:15 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 1386D40F2A Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=jpoimboe@redhat.com Date: Fri, 11 Aug 2017 11:57:13 -0500 From: Josh Poimboeuf To: Andy Lutomirski Cc: Ingo Molnar , Brian Gerst , Thomas Gleixner , "H. Peter Anvin" , Peter Zijlstra , Arnd Bergmann , Linus Torvalds , Denys Vlasenko , "linux-kernel@vger.kernel.org" , Borislav Petkov , "linux-tip-commits@vger.kernel.org" Subject: Re: [tip:x86/asm] objtool: Track DRAP separately from callee-saved registers Message-ID: <20170811165713.kngoyorynncyabjq@treble> References: <3da23a6d4c5b3c1e21fc2ccc21a73941b97ff20a.1502401017.git.jpoimboe@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.6.0.1 (2016-04-01) X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Fri, 11 Aug 2017 16:57:15 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Aug 11, 2017 at 09:22:11AM -0700, Andy Lutomirski wrote: > On Fri, Aug 11, 2017 at 5:13 AM, tip-bot for Josh Poimboeuf > wrote: > > Commit-ID: bf4d1a83758368c842c94cab9661a75ca98bc848 > > Gitweb: http://git.kernel.org/tip/bf4d1a83758368c842c94cab9661a75ca98bc848 > > Author: Josh Poimboeuf > > AuthorDate: Thu, 10 Aug 2017 16:37:26 -0500 > > Committer: Ingo Molnar > > CommitDate: Fri, 11 Aug 2017 14:06:15 +0200 > > > > objtool: Track DRAP separately from callee-saved registers > > > > When GCC realigns a function's stack, it sometimes uses %r13 as the DRAP > > register, like: > > > > push %r13 > > lea 0x10(%rsp), %r13 > > and $0xfffffffffffffff0, %rsp > > pushq -0x8(%r13) > > push %rbp > > mov %rsp, %rbp > > push %r13 > > ... > > mov -0x8(%rbp),%r13 > > leaveq > > lea -0x10(%r13), %rsp > > pop %r13 > > retq > > > > I have a couple questions, mainly to help me understand. > > Question 1: What does DRAP stand for? Duplicate Return Address > Pointer? Dynamic ReAlignment Pointer? I tried searching and got > nothing. It seems to be a GCC invention which stands for: Dynamic Realign Argument Pointer. I don't think it's documented anywhere, but there's at least some comments about it in the GCC sources if you search for DRAP. > Question 2: What's up with the resulting stack layout? It seems we have: > > caller's last stack slot <-- r13 in function body points here > return address > old r13 > [possible padding for alignment] > return address, duplicated (for naive unwinder's benefit?) > old rbp <-- rbp in body points here > new r13, i.e. pointer to caller's last stack slot > > Now we have the function body, and r13 is free for use in here because > it's saved. > > In the epilogue, we recover r13, use leaveq (hmm, shorter than pop > %rbp but does more work than needed), restore the old r13, and return. > > I don't get it, though. gcc only ever uses that inner r13 with an > offset. The code would be considerably shorter if the second > instruction were just mov %rsp, %r13. That would change the push to > pushq 0x8(%rsp) and the third-to-last instruction to mov %r13, %rsp, > saving something like 8 bytes of code. I don't know why it doesn't do it the way you suggest, but I'm glad it doesn't because I think it would make the DWARF/ORC data even more complicated. Here it's "simple", because r13 == DWARF CFA. > I also don't get why any of this is needed. Couldn't the compiler > just do push %rbp; mov %rsp, %rbp; and $0xfffffffffffffff0, %rsp and > be done with it? Good question. I wish it did just use the frame pointer, because dealing with DRAP has been a headache. > I compiled this: > > void func() > { > int var __attribute__((aligned(32))); > asm volatile ("" :: "m" (var)); > } > > and got: > > func: > leaq 8(%rsp), %r10 > andq $-32, %rsp > pushq -8(%r10) > pushq %rbp > movq %rsp, %rbp > pushq %r10 > popq %r10 > popq %rbp > leaq -8(%r10), %rsp > ret > > Which is better than the crud you pasted, since it at least uses a > caller-saved reg (r10), but we still have the nasty addressing modes > *and* an unnecessary push and pop of r10. > > I filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81825 and maybe > some GCC person has a clue what's going on. I've found that, when it does this DRAP pattern, most of the time it uses r10. The r13 version seems to be more rare. I can provide a real-world r13 example if that would help. -- Josh