This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

mips-tdep.c: Fix sw watchpoint-out-of-scope events


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  <macro@mips.com>

	* 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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]