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]

Re: [RFC] "single step" atomic instruction sequences as a whole on PPC


Ulrich,

Thanks for the comments. 

I've modified the patch according to your suggestions. Any additional
comments on it?

Any suggestions for the duplicate breakpoint detection? Maybe it could
be handled in a better way.

Best Regards.
Luis
2007-04-13  Luis Machado  <luisgpm@br.ibm.com>

	* rs6000-tdep.c: Defines masks for POWER instructions that set
	and use the reservation flag (LWARX,LDARX,STWCX,STDCX).
	* rs6000-tdep.c (deal_with_atomic_sequence): Handles single
	stepping through an atomic sequence of instructions.
	* rs6000-tdep.c (rs6000_software_single_step): Added a function
	call to check if we are stepping through an atomic sequence of 
	instructions.
	* rs6000-tdep.c (rs6000_gdbarch_init): Initializes a function to
	check for atomic instruction sequences while single stepping.

Index: gdb/rs6000-tdep.c
===================================================================
--- gdb.orig/rs6000-tdep.c	2007-05-03 06:06:21.000000000 -0700
+++ gdb/rs6000-tdep.c	2007-05-03 07:45:09.000000000 -0700
@@ -719,8 +719,93 @@
     return little_breakpoint;
 }
 
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7c000028
+#define LDARX_INSTRUCTION 0x7c0000A8
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define STDCX_INSTRUCTION 0x7c0001ad
+#define BC_MASK 0xfc000000
+#define BC_INSTRUCTION 0x40000000
+
+static int 
+deal_with_atomic_sequence(struct regcache *regcache)
+{
+  CORE_ADDR pc = read_pc ();
+  CORE_ADDR breaks[16] = {-1, -1, -1, -1, -1, -1, -1, -1,
+                          -1, -1, -1, -1, -1, -1, -1, -1};
+  CORE_ADDR branch_bp; /* Breakpoint at destination of a banch instruction */
+  CORE_ADDR loc = pc;
+  int insn = read_memory_integer (loc, PPC_INSN_SIZE);
+  int insn_count;
+  int index; /* Index used for the "breaks" arrays */
+  int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed) */  
+  const int atomic_sequence_length = 16;
+  const int opcode = BC_INSTRUCTION; /* Branch instruction's OPcode */
+
+  /* Assume all atomic sequences start with an lwarx or ldarx instruction.  */
+  if ((insn & LWARX_MASK) != LWARX_INSTRUCTION
+   && (insn & LWARX_MASK) != LDARX_INSTRUCTION)
+      return 0;
+
+  /* Assume that no atomic sequence is longer than "atomic_sequence_length 
+    instructions.  */
+  for (insn_count = 0; insn_count < atomic_sequence_length ; ++insn_count)
+    {
+      loc += PPC_INSN_SIZE;
+      insn = read_memory_integer (loc, PPC_INSN_SIZE);
+
+      /* Check for conditiconal branches in the middle of the sequence
+        and put breakpoints in their destinations */
+      if ((insn & BC_MASK) == BC_INSTRUCTION)
+        {
+          branch_bp = branch_dest(opcode, insn, pc, breaks[0]);
+
+          /* Make sure we don't have two breakpoints at the same address */
+          for (index = 0; index <= last_breakpoint; index++)
+            breaks[last_breakpoint] = (breaks[last_breakpoint] == branch_bp)?
+                                        -1:branch_bp;
+
+          if (breaks[last_breakpoint] != -1)
+            last_breakpoint++;
+        }
 
-/* AIX does not support PT_STEP. Simulate it. */
+      if ((insn & STWCX_MASK) == STWCX_INSTRUCTION
+       || (insn & STWCX_MASK) == STDCX_INSTRUCTION)
+        break;
+    }
+
+  /* Assume that the atomic sequence ends with a stwcx/stdcx instruction */
+  if ((insn & STWCX_MASK) != STWCX_INSTRUCTION
+   && (insn & STWCX_MASK) != STDCX_INSTRUCTION)
+    {
+      warning (_("\nTried to step over an atomic sequence of instructions at %s\n \
+                  but could not find the end of the sequence."),
+                  core_addr_to_string(pc));
+      return 0;
+    }
+
+  loc += PPC_INSN_SIZE;
+  insn = read_memory_integer (loc, PPC_INSN_SIZE);
+
+  for (index = 0; index < last_breakpoint; index++)
+    if (loc == breaks[index])
+      break;
+
+  /* Insert a breakpoint right after the end of the atomic sequence */
+  if (index == last_breakpoint)
+    breaks[last_breakpoint++] = loc;
+
+  /* Effectively inserts all the breakpoints */
+  for (index = 0; index < last_breakpoint; index++)
+    insert_single_step_breakpoint (breaks[index]);
+
+  gdb_flush (gdb_stdout);
+
+  return 1;
+}
+
+/* AIX does not support PT_STEP. Simulate it.  */
 
 int
 rs6000_software_single_step (struct regcache *regcache)
@@ -737,6 +822,9 @@
 
   insn = read_memory_integer (loc, 4);
 
+  if (deal_with_atomic_sequence(regcache))
+    return 1;
+  
   breaks[0] = loc + breakp_sz;
   opcode = insn >> 26;
   breaks[1] = branch_dest (opcode, insn, loc, breaks[0]);
@@ -3461,6 +3549,9 @@
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
 
+  /* Handles single stepping of atomic sequences */
+  set_gdbarch_software_single_step(gdbarch, deal_with_atomic_sequence);
+  
   /* Handle the 64-bit SVR4 minimal-symbol convention of using "FN"
      for the descriptor and ".FN" for the entry-point -- a user
      specifying "break FN" will unexpectedly end up with a breakpoint

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