From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5071 invoked by alias); 25 Jan 2008 13:07:28 -0000 Received: (qmail 4850 invoked by uid 22791); 25 Jan 2008 13:07:27 -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; Fri, 25 Jan 2008 13:07:07 +0000 Received: from ICSMULLER (laocoon.u-strasbg.fr [130.79.112.72]) by ics.u-strasbg.fr (Postfix) with ESMTP id A56E918701B; Fri, 25 Jan 2008 14:13:31 +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> <003101c85696$6f4d9e20$4de8da60$@u-strasbg.fr> <200801241750.m0OHoD5k007103@brahms.sibelius.xs4all.nl> In-Reply-To: <200801241750.m0OHoD5k007103@brahms.sibelius.xs4all.nl> Subject: [RFA] i386-tdep.c: Add i386_skip_noop function Date: Fri, 25 Jan 2008 14:16:00 -0000 Message-ID: <004701c85f53$2ef82dc0$8ce88940$@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/msg00608.txt.bz2 I tried to conciliate Pedro's and Mark's remarks in a new patch. As this patch only tries to catch no-op instruction added on purpose at the start of a function to allow hot-patching, I removed the 'check' variable of my previous patch that allowed to check several different patterns as in the optics of 'on purpose no-op', looking for several patterns is a non-sense. As I also directly read 2 bytes, I added a check that returns pc in case the call to read_memory_nobpt fails. ChangeLog entry: 2008-01-25 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 25 Jan 2008 10:29:09 -0000 @@ -632,6 +632,41 @@ 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[2]; + + if (read_memory_nobpt (pc, (gdb_byte *) &op, 2) != 0) + return pc; +/* Some Microsoft's system dll functions start with a + `mov %edi,%edi' instruction, which is effectively a two byte `nop'. + This instruction is used for hot patching support, together with 5 + bytes of slack before the function. Later, when hot-patching, the 2 + byte op can be replaced with a relative jump to 5 bytes back. The 5 + bytes slack is large enough to hold a jump into anywhere in + the 32-bit address space. + A two byte nop is used to be sure that no thread is executing + the instruction at byte 1 of the function, so the patching can be + performed atomically. */ + +/* 0x8b,0xff matches `mov %edi,%edi' */ + if (op[0] == 0x8b && op[1] == 0xff) + { + return pc + 2; + } +/* Here other patterns can be added if found. */ +/* Quoted from Mark Kettenis: + "I've heard of a couple of code generation tools that do something similar + as Microsoft and insert nop instructions at the start of a function to be + patched up later. So other targets could benefit from the same code. + And calling this function unconditionally keeps the code simple." */ + + 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 +852,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);