From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4907 invoked by alias); 2 Feb 2007 17:34:07 -0000 Received: (qmail 4887 invoked by uid 22791); 2 Feb 2007 17:34:05 -0000 X-Spam-Check-By: sourceware.org Received: from nile.gnat.com (HELO nile.gnat.com) (205.232.38.5) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 02 Feb 2007 17:33:57 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-nile.gnat.com (Postfix) with ESMTP id 497C448CBE9; Fri, 2 Feb 2007 12:33:55 -0500 (EST) Received: from nile.gnat.com ([127.0.0.1]) by localhost (nile.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 24769-01-8; Fri, 2 Feb 2007 12:33:54 -0500 (EST) Received: from takamaka.act-europe.fr (unknown [70.71.0.212]) by nile.gnat.com (Postfix) with ESMTP id 4B6E748CE01; Fri, 2 Feb 2007 12:33:54 -0500 (EST) Received: by takamaka.act-europe.fr (Postfix, from userid 1000) id 4505E34C099; Fri, 2 Feb 2007 09:34:56 -0800 (PST) Date: Fri, 02 Feb 2007 17:34:00 -0000 From: Joel Brobecker To: Robert Dewar , Wiljan Derks , gdb@sourceware.org, Mark Kettenis Subject: Re: How to tell gdb about dlls using remote protocol Message-ID: <20070202173456.GT17864@adacore.com> References: <003f01c7457c$0f2d8090$9600000a@kamer> <20070131223113.GA15122@nevyn.them.org> <20070201175311.GG17864@adacore.com> <20070201225437.GA13740@nevyn.them.org> <20070201230301.GM17864@adacore.com> <20070201235944.GA16114@nevyn.them.org> <45C2D80E.2050403@adacore.com> <20070202114312.GA15239@nevyn.them.org> <20070202165155.GS17864@adacore.com> <20070202165619.GA30801@nevyn.them.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="9Ek0hoCL9XbhcSqy" Content-Disposition: inline In-Reply-To: <20070202165619.GA30801@nevyn.them.org> User-Agent: Mutt/1.4.2.2i Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2007-02/txt/msg00018.txt.bz2 --9Ek0hoCL9XbhcSqy Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 592 > Hmm, perhaps it successfully gets you out and only misses frames. I'm > pretty sure I remember that when debugging a Windows build of GDB, the > select helper threads live somewhere in NTDLL without a valid frame. I am not sure about that particular thread. But for the other ones, we are indeed counting on the fact that all we lose is skipping one frame. > I'd be curious to see it, at least, but I'm not sure what we can do. Here it is. The diff is probably malformed, because I had to remove a couple of patches we backported from head, but that should give you the idea. -- Joel --9Ek0hoCL9XbhcSqy Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="ebp.diff" Content-length: 3459 +/* Return non-zero if the function starting at START_PC has a prologue + that sets up a standard frame. */ + +static int +i386_function_has_frame (CORE_ADDR start_pc) +{ + struct i386_frame_cache cache; + + cache.locals = -1; + i386_analyze_prologue (start_pc, 0xffffffff, &cache); + + return (cache.locals >= 0); +} + +/* Return non-zero if PC is inside one of the inferior's DLLs. */ + +static int +i386_in_dll (CORE_ADDR pc) +{ + char *so_name = solib_address (pc); + int len; + + if (so_name == NULL) + return 0; + + len = strlen (so_name); + if (len < 5) + return 0; + + return ((so_name[len - 1] == 'l' || so_name[len - 1] == 'L') + && (so_name[len - 2] == 'l' || so_name[len - 2] == 'L') + && (so_name[len - 3] == 'd' || so_name[len - 3] == 'D') + && so_name[len - 4] == '.'); +} + /* Normal frames. */ static struct i386_frame_cache * @@ -954,20 +1159,49 @@ i386_frame_cache (struct frame_info *nex frame by looking at the stack pointer. For truly "frameless" functions this might work too. */ - if (cache->stack_align) - { - /* We're halfway aligning the stack. */ - cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4; - cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4; + if (i386_in_dll (cache->pc) + && !i386_function_has_frame (cache->pc)) + { + /* Functions in DLL for which do not seem to create a standard + frame are unwound using %ebp. This is actually the caller's + frame base instead of our own, but there are some functions + such as WaitForSingleObjectEx in one of the Windows system + DLLs for which the frame base cannot possibly be determined + from the stack pointer. As a consequence, our caller will be + missing from the backtrace, but this is better than having + an aborted backtrace due to a bogus frame base. + + We use this approach only for functions in DLLs because + this is the only place where we have seen the type of + highly optimized code that cause us trouble. In other + cases, we expect the code to come with frame debugging + information, making prologue scanning unnecessary. + + We also avoid blindly following %ebp if we are midway through + setting up a standard frame. In that case, we know how to + determine the frame base using the stack pointer. */ - /* This will be added back below. */ - cache->saved_regs[I386_EIP_REGNUM] -= cache->base; - } + cache->saved_regs[I386_EBP_REGNUM] = 0; + } else - { - frame_unwind_register (next_frame, I386_ESP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset; - } + { + if (cache->stack_align) + { + /* We're halfway aligning the stack. */ + cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4; + cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4; + + /* This will be added back below. */ + cache->saved_regs[I386_EIP_REGNUM] -= cache->base; + } + else + { + frame_unwind_register (next_frame, I386_ESP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset; + } + } } /* Now that we have the base address for the stack frame we can --9Ek0hoCL9XbhcSqy--