From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14299 invoked by alias); 14 Jan 2008 10:16:06 -0000 Received: (qmail 14242 invoked by uid 22791); 14 Jan 2008 10:16:06 -0000 X-Spam-Check-By: sourceware.org Received: from ics.u-strasbg.fr (HELO ics.u-strasbg.fr) (130.79.112.250) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 14 Jan 2008 10:15:46 +0000 Received: from ICSMULLER (laocoon.u-strasbg.fr [130.79.112.72]) by ics.u-strasbg.fr (Postfix) with ESMTP id 34605187021; Mon, 14 Jan 2008 11:19:29 +0100 (CET) From: "Pierre Muller" To: "'Mark Kettenis'" Cc: References: <000001c83b4a$573b4560$05b1d020$@u-strasbg.fr> <200712101854.lBAIs91J031646@brahms.sibelius.xs4all.nl> <002701c83be2$ac2a9a60$047fcf20$@u-strasbg.fr> In-Reply-To: <002701c83be2$ac2a9a60$047fcf20$@u-strasbg.fr> Subject: [RFC-v2] Enhance backtrace for microsoft system DLL calls Date: Mon, 14 Jan 2008 10:16:00 -0000 Message-ID: <003101c85696$6f4d9e20$4de8da60$@u-strasbg.fr> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Mailer: Microsoft Office Outlook 12.0 Content-Language: en-us 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: 2008-01/txt/msg00325.txt.bz2 I wrote a i386_skip_noop function. It currently only tests for 'nop' and 'mov %edi,%edi' instructions, but the way it is written, other instructions should be easy to add. I also tried to explain the reason of the presence of the 'mov %edi,%edi' instruction in the win32 system DLL prologue, as explained by Pedro. Tested on cygwin target, no regressions found. The patch allows to get the backtrace of the main thread of gdb to come up to the functions that called the systems DLL. If I use ./gdb ./gdb with 'set new-console on' and use Ctrl-C on the debuggee gdb window. Without the patch, the backtrace only shows 3 levels in ntdll.dll and kernel32.dll Questions: 1) Is the 'nop' test useful or should it be removed? 2) Should we add other possible no-ops? As said in my previous email, the number of possible no-ops is big, and it is probably not wise to test all of them. 3) this call is used for all i386 targets, but it is probably useless for all operating systems but Microsoft Windows, so should it be called only for that OS, and if yes, how should we code this? 4) Any suggestions to make the comment clearer will be most appreciated. Pierre Muller ChangeLog entry: 2008-01-14 Pierre Muller * i386-tdep.c (i386_skip_noop): New function. (i386_analyze_prologue): Call i386_skip_noop function. Index: gdb/i386-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386-tdep.c,v retrieving revision 1.248 diff -u -p -r1.248 i386-tdep.c --- gdb/i386-tdep.c 11 Jan 2008 13:20:00 -0000 1.248 +++ gdb/i386-tdep.c 14 Jan 2008 08:11:27 -0000 @@ -632,6 +632,51 @@ struct i386_insn i386_frame_setup_skip_i { 0 } }; + +/* Check whether PC points to a no-op instruction. */ +static CORE_ADDR +i386_skip_noop (CORE_ADDR pc) +{ + gdb_byte op; + int check = 1; + + read_memory_nobpt (pc, &op, 1); + + while (check) + { + check = 0; + /* Ignore `nop' instruction. */ + if (op == 0x90) + { + pc += 1; + read_memory_nobpt (pc, &op, 1); + check = 1; + } + /* Ignore no-op instruction `mov %edi, %edi'. + Microsoft system dlls often start with + a `mov %edi,%edi' instruction. + The 5 bytes before the function start are + filled with `nop' instructions. + This pattern can be used for hot-patching: + The `mov %edi, %edi' instruction can be replaced by a + near jump to the location of the 5 `nop' instructions + which can be replaced by a 32-bit jump to anywhere + in the 32-bit address space. */ + + else if (op == 0x8b) + { + read_memory_nobpt (pc + 1, &op, 1); + if (op == 0xff) + { + pc += 2; + read_memory_nobpt (pc, &op, 1); + check = 1; + } + } + } + return pc; +} + /* Check whether PC points at a code that sets up a new stack frame. If so, it updates CACHE and returns the address of the first instruction after the sequence that sets up the frame or LIMIT, @@ -817,6 +862,7 @@ static CORE_ADDR i386_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc, struct i386_frame_cache *cache) { + pc = i386_skip_noop (pc); pc = i386_follow_jump (pc); pc = i386_analyze_struct_return (pc, current_pc, cache); pc = i386_skip_probe (pc);