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]

[PATCH] PPC - Stepping off breakpoints in non-stop mode


Hi folks,

This is the ppc-specific code to step off breakpoints in non-stop mode.
The main code is the fixup function, responsible for making sure we have
the correct PC after a displaced stepping has been concluded.

It applies on top of Pedro and Jim's more general displaced stepping
patch.

Tested without regressions on PPC 32/64.

Is this OK? Comments?

Best regards,
Luis
2008-05-02  Luis Machado  <luisgpm@br.ibm.com>

	* ppc-tdep.h: Define PPC_MAX_INSN_LEN, BRANCH_MASK, B_INSN, BC_INSN,
	LWARX_MASK, LWARX_INSTRUCTION, LDARX_INSTRUCTION, STWCX_MASK,
	STWCX_INSTRUCTION, STDCX_INSTRUCTION, BXL_INSN, BP_MASK and BP_INSN.
	* rs6000-tdep.c (ppc_displaced_step_fixup): New function.
	(deal_with_atomic_sequence): Update BC masks.
	(rs6000_gdbarch_init): Init displaced stepping infra-structure.
	Remove LWARX_MASK, LWARX_INSTRUCTION, LDARX_INSTRUCTION, STWCX_MASK,
	STWCX_INSTRUCTION, STDCX_INSTRUCTION, BC_MASK and BC_INSTRUCTION.

Index: HEAD/gdb/ppc-tdep.h
===================================================================
--- HEAD.orig/gdb/ppc-tdep.h	2008-05-01 14:00:40.000000000 -0700
+++ HEAD/gdb/ppc-tdep.h	2008-05-02 10:52:53.000000000 -0700
@@ -261,10 +261,28 @@
   PPC_NUM_REGS
 };
 
+/* The length of the longest ppc instruction.  */
+#define PPC_MAX_INSN_LEN (4)
 
 /* Instruction size.  */
 #define PPC_INSN_SIZE 4
 
+/* Instruction masks used during single-stepping of atomic sequences.  */
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7c000028
+#define LDARX_INSTRUCTION 0x7c0000A8
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define STDCX_INSTRUCTION 0x7c0001ad
+
+/* Instruction masks for displaced stepping.  */
+#define BRANCH_MASK 0xfc000000
+#define BP_MASK 0xFC0007FE
+#define B_INSN 0x48000000
+#define BC_INSN 0x40000000
+#define BXL_INSN 0x4c000000
+#define BP_INSN 0x7C000008
+
 /* Estimate for the maximum number of instrctions in a function epilogue.  */
 #define PPC_MAX_EPILOGUE_INSTRUCTIONS  52
 
Index: HEAD/gdb/rs6000-tdep.c
===================================================================
--- HEAD.orig/gdb/rs6000-tdep.c	2008-04-30 22:05:39.000000000 -0700
+++ HEAD/gdb/rs6000-tdep.c	2008-05-02 11:22:04.000000000 -0700
@@ -985,16 +985,66 @@
     return little_breakpoint;
 }
 
-
-/* Instruction masks used during single-stepping of atomic sequences.  */
-#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
+/* Fix up the state of registers and memory after having single-stepped
+   a displaced instruction.  */
+void
+ppc_displaced_step_fixup (struct gdbarch *gdbarch,
+			   struct displaced_step_closure *closure,
+			   CORE_ADDR from, CORE_ADDR to,
+			   struct regcache *regs)
+{
+  /* Since we use simple_displaced_step_copy_insn, our closure is a
+     copy of the instruction.  */
+  unsigned int *insn  = (unsigned int *) closure;
+  unsigned int opcode = (*insn & BRANCH_MASK);
+  int offset = 4; /* Default offset for non PC-relative instructions.  */
+
+  if (debug_displaced)
+    fprintf_unfiltered (gdb_stdlog,
+			"displaced: (ppc) fixup (0x%s, 0x%s)\n",
+			paddr_nz (from), paddr_nz (to));
+
+
+  /* Handle PC-relative branch instructions.  */
+  if ((opcode == B_INSN) || (opcode == BC_INSN) || (opcode == BXL_INSN))
+    {
+      /* LK bit Indicates whether we should set the link register to point
+	 to the next instruction or not.  */
+      char link_register_bit = (char) (*insn & 0x1);
+      unsigned long current_pc;
+
+      /* Read the current PC value after the instruction has been executed
+	 in a displaced location.  Calculate the offset to be applied to the
+	 original PC value before the displaced stepping.  */
+      regcache_cooked_read_unsigned (regs, gdbarch_pc_regnum (gdbarch), &current_pc);
+      offset = current_pc - to;
+
+      if (debug_displaced)
+	fprintf_unfiltered (gdb_stdlog,
+			    "displaced: (ppc) branch instruction: 0x%x\n"
+			    "displaced: (ppc) adjusted PC from %s to %s\n",
+			    *insn, paddr_nz (current_pc), paddr_nz (from + offset));
+
+      if (opcode != BXL_INSN)
+	{
+	  /* AA bit indicating whether this is an absolute addressing or
+	     PC-relative. */
+	  char absolute_addr_bit = (char) (*insn & 0x2);
+
+	  if (!absolute_addr_bit)
+	    regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch), from + offset);
+	}
+
+      if (link_register_bit)
+	regcache_cooked_write_unsigned (regs, 67, from + 4);
+    }
+  /* Check for breakpoints in the inferior.  If we've found one, place the PC
+     right at the breakpoint instruction.  */
+  else if ((*insn & BP_MASK) == BP_INSN)
+    regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch), from);
+  else
+    regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch), from + offset);
+}
 
 /* Checks for an atomic sequence of instructions beginning with a LWARX/LDARX
    instruction and ending with a STWCX/STDCX instruction.  If such a sequence
@@ -1032,7 +1082,7 @@
       /* Assume that there is at most one conditional branch in the atomic
          sequence.  If a conditional branch is found, put a breakpoint in 
          its destination address.  */
-      if ((insn & BC_MASK) == BC_INSTRUCTION)
+      if ((insn & BRANCH_MASK) == BC_INSN)
         {
           if (bc_insn_count >= 1)
             return 0; /* More than one conditional branch found, fallback 
@@ -3821,6 +3871,17 @@
     /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
     tdep->ppc_dl0_regnum += 32;
 
+  /* Setup displaced stepping.  */
+  set_gdbarch_displaced_step_copy_insn (gdbarch,
+					simple_displaced_step_copy_insn);
+  set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
+  set_gdbarch_displaced_step_free_closure (gdbarch,
+					   simple_displaced_step_free_closure);
+  set_gdbarch_displaced_step_location (gdbarch,
+				       displaced_step_at_entry_point);
+
+  set_gdbarch_max_insn_length (gdbarch, PPC_MAX_INSN_LEN);
+
   return gdbarch;
 }
 

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