Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [rfa] Fix software-watchpoint failures by adding epilogue detection
@ 2010-09-22 19:20 Ulrich Weigand
  2010-09-22 20:01 ` Daniel Jacobowitz
  0 siblings, 1 reply; 12+ messages in thread
From: Ulrich Weigand @ 2010-09-22 19:20 UTC (permalink / raw)
  To: gdb-patches, rearnsha

Hello,

I've been seeing failures in software watchpoint tests on ARM (Thumb-2),
due to missing modeling of precise unwind states during function
epilogues.  This problem is well known from other architectures,
and is usually fixed by skipping epilogue during sofware watchpoint
single-stepping via the gdbarch_in_function_epilogue_p callback.

However, ARM currently does not define this routine.  The following
patch adds an implementation that detects common Thumb epilogue
sequences (ARM is missing, but could be added in an analogous way).

This fixes the following test case failures:
FAIL: gdb.base/recurse.exp: continue to second instance watchpoint, second time
FAIL: gdb.base/recurse.exp: second instance watchpoint deleted when leaving scope (the program exited)
FAIL: gdb.base/recurse.exp: continue to first instance watchpoint, second time (the program is no longer running)
FAIL: gdb.base/recurse.exp: first instance watchpoint deleted when leaving scope (the program is no longer running)
FAIL: gdb.base/watch-cond.exp: watchpoint with local expression, local condition evaluates in correct frame

and adds:
XPASS: gdb.mi/mi-watch.exp: sw: watchpoint trigger
XPASS: gdb.mi/mi2-watch.exp: sw: watchpoint trigger

Tested on armv7l-linux-gnueabi with no regressions.

OK for mainline?

Bye,
Ulrich


ChangeLog:

	* arm-tdep.c (arm_in_function_epilogue_p): New function.
	(arm_gdbarch_init): Install it.


=== modified file 'gdb/arm-tdep.c'
--- gdb/arm-tdep.c	2010-08-30 15:33:03 +0000
+++ gdb/arm-tdep.c	2010-09-22 17:07:18 +0000
@@ -1686,6 +1686,87 @@
     }
 }
 
+/* Return true if we are in the function's epilogue, i.e. after the
+   instruction that destroyed the function's stack frame.
+
+   We consider this to be the case if, starting from the current
+   instruction, we have a sequence of:
+
+   - [optional] setting SP from the frame pointer
+   - restoring registers from SP [may include PC]
+   - a return-type instruction [if PC wasn't already restored]
+
+  If we find anything else, we assume we're not in the epilogue.  */
+
+static int
+arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+
+  if (arm_pc_is_thumb (pc))
+    {
+      for (;;)
+	{
+	  unsigned int insn;
+	  gdb_byte buf[2];
+
+	  if (target_read_memory (pc, buf, 2))
+	    return 0;
+
+	  pc += 2;
+	  insn = extract_unsigned_integer (buf, 2, byte_order_for_code);
+
+	  if (insn == 0x4770)  /* bx lr */
+	    return 1;
+	  else if (insn == 0x46f7)  /* mov pc, lr */
+	    return 1;
+	  else if (insn == 0x46bd)  /* mov sp, r7 */
+	    ;
+	  else if ((insn & 0xfe00) == 0xbc00)  /* pop <registers> */
+	    {
+	      if (insn & 0x0100)  /* <registers> include PC.  */
+		return 1;
+	    }
+	  else if ((insn & 0xe000) == 0xe000)  /* 32-bit Thumb-2 instruction */
+	    {
+	      unsigned int insn2;
+
+	      if (target_read_memory (pc, buf, 2))
+		return 0;
+
+	      pc += 2;
+	      insn2 = extract_unsigned_integer (buf, 2, byte_order_for_code);
+
+	      if ((insn & 0xffdf) == 0xe89d)  /* ldm.w sp{!}, <registers> */
+		{
+		  if (insn2 & 0x8000)  /* <registers> include PC.  */
+		    return 1;
+		}
+	      else if (insn == 0xf85d  /* ldr.w <Rt>, [sp], #4 */
+		       && (insn2 & 0x0fff) == 0x0d04)
+		{
+		  if ((insn2 & 0xf000) == 0xf000) /* <Rt> is PC.  */
+		    return 1;
+		}
+	      else if ((insn & 0xffbf) == 0xecbd  /* vldm sp!, <list> */
+		       && (insn2 & 0x0e00) == 0x0a00)
+		;
+	      else
+		return 0;
+	    }
+	  else
+	    return 0;
+	}
+    }
+  else
+    {
+      /* FIXME: We don't handle ARM for now.  */
+    }
+
+  return 0;
+}
+
+
 /* When arguments must be pushed onto the stack, they go on in reverse
    order.  The code below implements a FILO (stack) to do this.  */
 
@@ -6818,6 +6899,9 @@
   /* Advance PC across function entry code.  */
   set_gdbarch_skip_prologue (gdbarch, arm_skip_prologue);
 
+  /* Detect whether PC is in function epilogue.  */
+  set_gdbarch_in_function_epilogue_p (gdbarch, arm_in_function_epilogue_p);
+
   /* Skip trampolines.  */
   set_gdbarch_skip_trampoline_code (gdbarch, arm_skip_stub);
 

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


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

end of thread, other threads:[~2010-10-08 13:27 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-22 19:20 [rfa] Fix software-watchpoint failures by adding epilogue detection Ulrich Weigand
2010-09-22 20:01 ` Daniel Jacobowitz
2010-09-23 16:13   ` Ulrich Weigand
2010-09-24 16:11     ` Ulrich Weigand
2010-09-28 20:23       ` Daniel Jacobowitz
2010-09-28 21:47         ` Ulrich Weigand
2010-09-28 21:49           ` Daniel Jacobowitz
2010-09-29 15:24             ` Richard Earnshaw
2010-10-07 16:12             ` [rfa, v3] Fix software-watchpoint failures on ARM " Ulrich Weigand
2010-10-08 13:01               ` Richard Earnshaw
2010-10-08 13:27                 ` Ulrich Weigand
2010-09-29 14:43           ` [rfa] Fix software-watchpoint failures " Yao Qi

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