Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* mips-tdep.c: Fix sw watchpoint-out-of-scope events
@ 2007-09-11 16:24 Maciej W. Rozycki
  2007-09-18 15:54 ` Daniel Jacobowitz
  0 siblings, 1 reply; 6+ messages in thread
From: Maciej W. Rozycki @ 2007-09-11 16:24 UTC (permalink / raw)
  To: gdb-patches, Daniel Jacobowitz; +Cc: Maciej W. Rozycki

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


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-09-19 13:16 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-09-11 16:24 mips-tdep.c: Fix sw watchpoint-out-of-scope events Maciej W. Rozycki
2007-09-18 15:54 ` Daniel Jacobowitz
2007-09-19 12:31   ` Maciej W. Rozycki
2007-09-19 12:38     ` Daniel Jacobowitz
2007-09-19 13:05       ` Maciej W. Rozycki
2007-09-19 13:16         ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox