From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16902 invoked by alias); 11 Sep 2007 16:24:17 -0000 Received: (qmail 16884 invoked by uid 22791); 11 Sep 2007 16:24:16 -0000 X-Spam-Check-By: sourceware.org Received: from dmz.mips-uk.com (HELO dmz.mips-uk.com) (194.74.144.194) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 11 Sep 2007 16:24:12 +0000 Received: from internal-mx1 ([192.168.192.240] helo=ukservices1.mips.com) by dmz.mips-uk.com with esmtp (Exim 3.35 #1 (Debian)) id 1IV8X3-0004j2-00; Tue, 11 Sep 2007 17:24:09 +0100 Received: from perivale.mips.com ([192.168.192.200]) by ukservices1.mips.com with esmtp (Exim 3.36 #1 (Debian)) id 1IV8Wu-0000YH-00; Tue, 11 Sep 2007 17:24:00 +0100 Received: from macro (helo=localhost) by perivale.mips.com with local-esmtp (Exim 4.63) (envelope-from ) id 1IV8Wo-0004bA-V4; Tue, 11 Sep 2007 17:23:54 +0100 Date: Tue, 11 Sep 2007 16:24:00 -0000 From: "Maciej W. Rozycki" To: gdb-patches@sourceware.org, Daniel Jacobowitz cc: "Maciej W. Rozycki" Subject: mips-tdep.c: Fix sw watchpoint-out-of-scope events Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-MIPS-Technologies-UK-MailScanner: Found to be clean X-MIPS-Technologies-UK-MailScanner-From: macro@mips.com 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: 2007-09/txt/msg00153.txt.bz2 Hello, This is a fix for software watchpoint-out-of-scope events for MIPS platforms. It implements a in_function_epilogue_p() hook which is used to single-step a function's epilogue once a local watchpoint has been destroyed (because of the restoration of the frame pointer). As a result the event is only reported once the caller has been reached back. This change has been tested natively for mips-linux-gnu and remotely for mipsisa32-sde-elf, with mips-sim-sde32/-EB, mips-sim-sde32/-EB/-mips16, mips-sim-sde32/-EL and mips-sim-sde32/-EL/-mips16. It fixes sw watchpoint regressions in gdb.mi/mi*-watch.exp: FAIL: gdb.mi/mi-watch.exp: wp out of scope (2) for the remote targets. It does not fix them for Linux, because the o32 calling convention makes the restoration of the GOT pointer in the caller ("lw gp,..." after "jalr") a part of the function call. Therefore execution stops in the right function, but one instruction too early, still within the source line of the call. It is still a step forward though and less of nuisance for the user. 2007-09-11 Maciej W. Rozycki * mips-tdep.c (mips32_in_function_epilogue_p): New function. (mips16_in_function_epilogue_p): Likewise. (mips_in_function_epilogue_p): Likewise. (mips_gdbarch_init): Register mips_in_function_epilogue_p(). OK to apply? Maciej 14677.diff Index: binutils-quilt/src/gdb/mips-tdep.c =================================================================== --- binutils-quilt.orig/src/gdb/mips-tdep.c 2007-09-11 14:16:22.000000000 +0100 +++ binutils-quilt/src/gdb/mips-tdep.c 2007-09-11 14:17:42.000000000 +0100 @@ -4883,6 +4883,95 @@ return mips32_scan_prologue (pc, limit_pc, NULL, NULL); } +/* Check whether the PC is in a function epilogue (32-bit version). + This is a helper function for mips_in_function_epilogue_p. */ +static int +mips32_in_function_epilogue_p (CORE_ADDR pc) +{ + CORE_ADDR func_addr = 0, func_end = 0; + + if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) + { + /* The MIPS epilogue is max. 12 bytes long. */ + CORE_ADDR addr = func_end - 12; + + if (addr < func_addr + 4) + addr = func_addr + 4; + if (pc < addr) + return 0; + + for (; pc < func_end; pc += MIPS_INSN32_SIZE) + { + unsigned long high_word; + unsigned long inst; + + inst = mips_fetch_instruction (pc); + high_word = (inst >> 16) & 0xffff; + + if (high_word != 0x27bd /* addiu $sp,$sp,offset */ + && high_word != 0x67bd /* daddiu $sp,$sp,offset */ + && inst != 0x03e00008 /* jr $ra */ + && inst != 0x00000000) /* nop */ + return 0; + } + + return 1; + } + + return 0; +} + +/* Check whether the PC is in a function epilogue (16-bit version). + This is a helper function for mips_in_function_epilogue_p. */ +static int +mips16_in_function_epilogue_p (CORE_ADDR pc) +{ + CORE_ADDR func_addr = 0, func_end = 0; + + if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) + { + /* The MIPS epilogue is max. 12 bytes long. */ + CORE_ADDR addr = func_end - 12; + + if (addr < func_addr + 4) + addr = func_addr + 4; + if (pc < addr) + return 0; + + for (; pc < func_end; pc += MIPS_INSN16_SIZE) + { + unsigned short inst; + + inst = mips_fetch_instruction (pc); + + if ((inst & 0xf800) == 0xf000) /* extend */ + continue; + + if (inst != 0x6300 /* addiu $sp,offset */ + && inst != 0xfb00 /* daddiu $sp,$sp,offset */ + && inst != 0xe820 /* jr $ra */ + && inst != 0xe8a0 /* jrc $ra */ + && inst != 0x6500) /* nop */ + return 0; + } + + return 1; + } + + return 0; +} + +/* The epilogue is defined here as the area at the end of a function, + after an instruction which destroys the function's stack frame. */ +static int +mips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + if (mips_pc_is_mips16 (pc)) + return mips16_in_function_epilogue_p (pc); + else + return mips32_in_function_epilogue_p (pc); +} + /* Root of all "set mips "/"show mips " commands. This will eventually be used for all MIPS-specific commands. */ @@ -5995,6 +6084,8 @@ set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue); + set_gdbarch_in_function_epilogue_p (gdbarch, mips_in_function_epilogue_p); + set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address); set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer); set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);