From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10070 invoked by alias); 9 Jan 2013 20:07:27 -0000 Received: (qmail 10054 invoked by uid 22791); 9 Jan 2013 20:07:24 -0000 X-SWARE-Spam-Status: No, hits=-2.8 required=5.0 tests=AWL,BAYES_00,KHOP_THREADED,TW_QW X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (194.98.77.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 09 Jan 2013 20:07:17 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id A354D290057; Wed, 9 Jan 2013 21:07:25 +0100 (CET) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id arKTHIldSFNQ; Wed, 9 Jan 2013 21:07:25 +0100 (CET) Received: from [192.168.0.14] (mtg95-3-82-238-192-125.fbx.proxad.net [82.238.192.125]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id 2C619290016; Wed, 9 Jan 2013 21:07:23 +0100 (CET) Subject: Re: [RFA/commit+doco 2/2] Windows x64 SEH unwinder. Mime-Version: 1.0 (Apple Message framework v1283) Content-Type: text/plain; charset=iso-8859-1 From: Tristan Gingold In-Reply-To: <50EDA48E.2030406@redhat.com> Date: Wed, 09 Jan 2013 20:07:00 -0000 Cc: Joel Brobecker , gdb-patches@sourceware.org Content-Transfer-Encoding: 7bit Message-Id: <66611BA9-4536-42B2-A65C-4EA5DA219E22@adacore.com> References: <1357728781-15073-1-git-send-email-brobecker@adacore.com> <1357728781-15073-3-git-send-email-brobecker@adacore.com> <50ED9221.1050504@redhat.com> <9E84DF2D-7AF8-4AA1-A5DF-171EF189A6E7@adacore.com> <50EDA48E.2030406@redhat.com> To: Pedro Alves X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2013-01/txt/msg00185.txt.bz2 On Jan 9, 2013, at 6:10 PM, Pedro Alves wrote: > On 01/09/2013 04:28 PM, Tristan Gingold wrote: > >>>> I don't really see a real way of supporting both old and new versions >>>> of GCC, unless we have a way of more finely ordering the unwinders. >>> >>> What specific finer order where you considering would be needed to >>> fix this? >> >> Joel once proposed to activate this unwinder if the CU is compiled >> by gcc 4.6 or older. > > I don't think you need to have a way of more finely ordering > the unwinders for that. AFAICS, we can make the sniffer > return false in that case. I had understood him > as meaning something about making the whole prepend/append > mechanisms more finer grained somehow. > > Checking the CU/producer is kind of the obvious choice. > It requires debug info though. Yes, but without debug info, unwinding doesn't work much better. AFAIK, zero-cost exception was not supported on Windows64. >>> Maybe detect if the whole module (exe/dll) the PC points at >>> contains any SEH (even if not for PC), and skip the SEH unwinder >>> if not? Is that possible? >> >> Yes, but useless. There are SEH info in crt0. > > You mean, the parts that are in mingw, right? I'd assume > any bits in gcc to only contain SEH in >=4.7. No, there is some SEH entries manually created. > Yeah, > seems like that wouldn't work for static binaries. > >>>> + http://msdn.microsoft.com/en-us/library/tawsa7cb.aspx >>>> + Furthermore, according to RtlVirtualUnwind, the complete list of >>>> + epilog marker is: >>>> + - ret [c3] >>>> + - ret n [c2 imm16] >>>> + - rep ret [f3 c3] >>>> + - jmp imm8 | imm32 [eb rel8] or [e9 rel32] >>>> + - jmp qword ptr imm32 - not handled >>>> + - rex jmp reg [4X ff eY] >>>> + I would add: >>>> + - pop reg [41 58-5f] or [58-5f] >>> >>> If you add "pop", and you'd add "add" and "lea" as well, >>> right? It's not super clear what "marker" means, but all >>> the instructions listed by RtlVirtualUnwind's docs are >>> control flow instructions. And then, in the url you point >>> above, we see: >>> >>> "These are the only legal forms for an epilog. It must consist of either >>> an add RSP,constant or lea RSP,constant[FPReg], followed by a series >>> of zero or more 8-byte register pops and a return or a jmp. (Only >>> a subset of jmp statements are allowable in the epilog." >>> >>> So from both docs it seems to me that "marker" is always the >>> last instruction of the epilogue, and that "pop" is not called >>> a marker. >> >> This is in fact an optimization. If we found a pop, followed by >> an epilog marker, there is not need to decode unwind info. > > I don't understand. pops will always be followed by a marker. > How can that be an optimization? If pop weren't in this list, then if pc points to a pop the unwinder will consider that the pc is in the body and need to decode unwind infos. Now, if pop is in the list, the unwinder will continue to decode until a ret and if a ret is found, it will consider that the pc is in the epilogue, avoiding decoding unwind infos. >>> Furthermore, >>> >>>> + >>>> + We don't care about the instruction deallocating the frame: >>>> + if it hasn't been executed, we can safely decode the insns; >>>> + if it has been executed, the following epilog decoding will >>>> + work. */ >>>> + CORE_ADDR pc = cache->pc; >>>> + CORE_ADDR cur_sp = cache->sp; >>>> + struct gdbarch *gdbarch = get_frame_arch (this_frame); >>>> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); >>>> + >>>> + while (1) >>>> + { >>>> + gdb_byte op; >>>> + gdb_byte rex; >>>> + >>>> + if (target_read_memory (pc, &op, 1) != 0) >>>> + return -1; >>>> + >>>> + if (op == 0xc3) >>>> + { >>>> + /* Ret. */ >>>> + cache->prev_rip_addr = cur_sp; >>>> + cache->prev_sp = cur_sp + 8; >>>> + return 1; >>>> + } >>>> + else if (op == 0xeb) >>>> + { >>>> + /* jmp rel8 */ >>>> + gdb_byte rel8; >>>> + >>>> + if (target_read_memory (pc + 1, &rel8, 1) != 0) >>>> + return -1; >>>> + pc = pc + 2 + (signed char) rel8; >>> >>> this implementation follows jumps, and keeps looping >>> at the jump destination. >> >> Right. >> >>> I see no hint that such thing >>> as an epilogue with a jump is a valid epilogue, only that >>> a jmp is only valid as replacement for ret. >>> Can you show an example where following the jmp until >>> you see a ret is necessary? >> >> Interesting remark. First attempt to answer is the case of a >> jump to an epilogue. > > The jump to an epilogue would not be part of the epilogue. Doesn't really matter. The point is that if the current instruction is a jump to the epilogue, there is no need to decode unwind infs. >> But I may miss your point. > > My point is that the docs say the epilogue has this rigid > format that always ends in a marker, and that a marker is > a ret or a jmp (therefore calling "pop" a marker as in the > "I would add" comment seems to me misleading). The code > continues following the jmp, so it makes me believe the code > is erroneously decoding something after the jmp that is > not an epilogue (the caller or perhaps a tailcall). No, it doesn't say that it ends in a marker. The epilogue ends by a ret. But the above instructions are considered to be part of the epilogue. Tristan.