No build reason found for SLE-Module-Transactional-Server:aarch64

File atomic-single-step.diff of Package gdb

20006-06-22  Paul Gilliam  <pgilliam@us.ibm.com>

	* gdbarch.sh: Change the return type of software_single_step from
	void to int and reformatted some comments to <= 80 columns.
	* gdbarch.c, gdbarch.h: Regenerated.
	* alpha-tdep.c (alpha_software_single_step): Change the return type
	from void to int and always return 1.
	* alpha-tdep.h: Change the return type of alpha_software_single_step
	from void to int.
	* arm-tdep.c (arm_software_single_step): Change the return type from
	void to int and always return 1.
	* cris-tdep.c (cris_software_single_step): Change the return type
	from void to int and always return 1.
	* mips-tdep.c (mips_software_single_step): Change the return type
	from void to int and always return 1.
	* mips-tdep.h: Change the return type of mips_software_single_step
	from void to int.
	* rs6000-tdep.c (rs6000_software_single_step): Change the return type
	from void to int and always return 1.
	*rs6000-tdep.h: Change the return type of rs6000_software_single_step
	from void to int.
	* sparc-tdep.c (sparc_software_single_step): Change the return type
	from void to int and always return 1.
	* sparc-tdep.h: Change the return type of sparc_software_single_step
	from void to int.
	* wince.c (wince_software_single_step {three times}): Change the
	return type from void to int and always return 1.
	infrun.c (resume): Check the return value from SOFTWARE_SINGLE_STEP
	and act accordingly.  True means that the software_single_step
	breakpoints where inserted; false means they where not.

Index: alpha-tdep.c
================================================================================
--- alpha-tdep.c
+++ alpha-tdep.c
@@ -1510,7 +1510,7 @@
   return (pc + 4);
 }
 
-void
+int
 alpha_software_single_step (enum target_signal sig, int insert_breakpoints_p)
 {
   static CORE_ADDR next_pc;
@@ -1528,6 +1528,7 @@
       remove_single_step_breakpoints ();
       write_pc (next_pc);
     }
+  return 1;
 }
 
 
--- alpha-tdep.h
+++ alpha-tdep.h
@@ -107,7 +107,7 @@
 };
 
 extern unsigned int alpha_read_insn (CORE_ADDR pc);
-extern void alpha_software_single_step (enum target_signal, int);
+extern int alpha_software_single_step (enum target_signal, int);
 extern CORE_ADDR alpha_after_prologue (CORE_ADDR pc);
 
 extern void alpha_mdebug_init_abi (struct gdbarch_info, struct gdbarch *);
--- arm-tdep.c
+++ arm-tdep.c
@@ -1840,7 +1840,7 @@
    single_step() is also called just after the inferior stops.  If we
    had set up a simulated single-step, we undo our damage.  */
 
-static void
+static int
 arm_software_single_step (enum target_signal sig, int insert_bpt)
 {
   /* NOTE: This may insert the wrong breakpoint instruction when
@@ -1855,6 +1855,8 @@
     }
   else
     remove_single_step_breakpoints ();
+
+  return 1
 }
 
 #include "bfd-in2.h"
--- cris-tdep.c
+++ cris-tdep.c
@@ -2117,7 +2117,7 @@
    digs through the opcodes in order to find all possible targets. 
    Either one ordinary target or two targets for branches may be found.  */
 
-static void
+static int
 cris_software_single_step (enum target_signal ignore, int insert_breakpoints)
 {
   inst_env_type inst_env;
@@ -2150,6 +2150,8 @@
     }
   else
     remove_single_step_breakpoints ();
+
+  return 1;
 }
 
 /* Calculates the prefix value for quick offset addressing mode.  */
--- gdbarch.c
+++ gdbarch.c
@@ -3273,14 +3273,14 @@
   return gdbarch->software_single_step != NULL;
 }
 
-void
+int
 gdbarch_software_single_step (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p)
 {
   gdb_assert (gdbarch != NULL);
   gdb_assert (gdbarch->software_single_step != NULL);
   if (gdbarch_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "gdbarch_software_single_step called\n");
-  gdbarch->software_single_step (sig, insert_breakpoints_p);
+  return gdbarch->software_single_step (sig, insert_breakpoints_p);
 }
 
 void
--- gdbarch.h
+++ gdbarch.h
@@ -1140,14 +1140,16 @@
 #define SMASH_TEXT_ADDRESS(addr) (gdbarch_smash_text_address (current_gdbarch, addr))
 #endif
 
-/* FIXME/cagney/2001-01-18: This should be split in two.  A target method that indicates if
-   the target needs software single step.  An ISA method to implement it.
+/* FIXME/cagney/2001-01-18: This should be split in two.  A target method that
+   indicates if the target needs software single step.  An ISA method to
+   implement it.
   
-   FIXME/cagney/2001-01-18: This should be replaced with something that inserts breakpoints
-   using the breakpoint system instead of blatting memory directly (as with rs6000).
+   FIXME/cagney/2001-01-18: This should be replaced with something that inserts
+   breakpoints using the breakpoint system instead of blatting memory directly
+   (as with rs6000).
   
-   FIXME/cagney/2001-01-18: The logic is backwards.  It should be asking if the target can
-   single step.  If not, then implement single step using breakpoints. */
+   FIXME/cagney/2001-01-18: The logic is backwards.  It should be asking if the
+   target can single step.  If not, then implement single step using breakpoints. */
 
 #if defined (SOFTWARE_SINGLE_STEP)
 /* Legacy for systems yet to multi-arch SOFTWARE_SINGLE_STEP */
@@ -1164,8 +1166,8 @@
 #define SOFTWARE_SINGLE_STEP_P() (gdbarch_software_single_step_p (current_gdbarch))
 #endif
 
-typedef void (gdbarch_software_single_step_ftype) (enum target_signal sig, int insert_breakpoints_p);
-extern void gdbarch_software_single_step (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p);
+typedef int (gdbarch_software_single_step_ftype) (enum target_signal sig, int insert_breakpoints_p);
+extern int gdbarch_software_single_step (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p);
 extern void set_gdbarch_software_single_step (struct gdbarch *gdbarch, gdbarch_software_single_step_ftype *software_single_step);
 #if !defined (GDB_TM_FILE) && defined (SOFTWARE_SINGLE_STEP)
 #error "Non multi-arch definition of SOFTWARE_SINGLE_STEP"
--- gdbarch.sh
+++ gdbarch.sh
@@ -601,15 +601,19 @@
 # It is not at all clear why SMASH_TEXT_ADDRESS is not folded into
 # ADDR_BITS_REMOVE.
 f:=:CORE_ADDR:smash_text_address:CORE_ADDR addr:addr::core_addr_identity::0
-# FIXME/cagney/2001-01-18: This should be split in two.  A target method that indicates if
-# the target needs software single step.  An ISA method to implement it.
+
+# FIXME/cagney/2001-01-18: This should be split in two.  A target method that
+# indicates if the target needs software single step.  An ISA method to
+# implement it.
 #
-# FIXME/cagney/2001-01-18: This should be replaced with something that inserts breakpoints
-# using the breakpoint system instead of blatting memory directly (as with rs6000).
+# FIXME/cagney/2001-01-18: This should be replaced with something that inserts
+# breakpoints using the breakpoint system instead of blatting memory directly
+# (as with rs6000).
 #
-# FIXME/cagney/2001-01-18: The logic is backwards.  It should be asking if the target can
-# single step.  If not, then implement single step using breakpoints.
-F:=:void:software_single_step:enum target_signal sig, int insert_breakpoints_p:sig, insert_breakpoints_p
+# FIXME/cagney/2001-01-18: The logic is backwards.  It should be asking if the
+# target can single step.  If not, then implement single step using breakpoints.
+F:=:int:software_single_step:enum target_signal sig, int insert_breakpoints_p:sig, insert_breakpoints_p
+
 # Return non-zero if the processor is executing a delay slot and a
 # further single-step is needed before the instruction finishes.
 M::int:single_step_through_delay:struct frame_info *frame:frame
--- infrun.c
+++ infrun.c
@@ -557,13 +557,15 @@
   if (SOFTWARE_SINGLE_STEP_P () && step)
     {
       /* Do it the hard way, w/temp breakpoints */
-      SOFTWARE_SINGLE_STEP (sig, 1 /*insert-breakpoints */ );
-      /* ...and don't ask hardware to do it.  */
-      step = 0;
-      /* and do not pull these breakpoints until after a `wait' in
-         `wait_for_inferior' */
-      singlestep_breakpoints_inserted_p = 1;
-      singlestep_ptid = inferior_ptid;
+      if (SOFTWARE_SINGLE_STEP (sig, 1 /*insert-breakpoints */ ))
+	{
+	  /* ...and don't ask hardware to do it.  */
+	  step = 0;
+	  /* and do not pull these breakpoints until after a `wait' in
+	  `wait_for_inferior' */
+	  singlestep_breakpoints_inserted_p = 1;
+	  singlestep_ptid = inferior_ptid;
+	}
     }
 
   /* If there were any forks/vforks/execs that were caught and are
@@ -1382,7 +1384,7 @@
 					   (LONGEST) ecs->ws.value.integer));
       gdb_flush (gdb_stdout);
       target_mourn_inferior ();
-      singlestep_breakpoints_inserted_p = 0;	/*SOFTWARE_SINGLE_STEP_P() */
+      singlestep_breakpoints_inserted_p = 0;	/* SOFTWARE_SINGLE_STEP_P() */
       stop_print_frame = 0;
       stop_stepping (ecs);
       return;
@@ -1402,7 +1404,7 @@
       target_mourn_inferior ();
 
       print_stop_reason (SIGNAL_EXITED, stop_signal);
-      singlestep_breakpoints_inserted_p = 0;	/*SOFTWARE_SINGLE_STEP_P() */
+      singlestep_breakpoints_inserted_p = 0;	/* SOFTWARE_SINGLE_STEP_P() */
       stop_stepping (ecs);
       return;
 
@@ -1576,7 +1578,7 @@
 	  if (debug_infrun)
 	    fprintf_unfiltered (gdb_stdlog, "infrun: stepping_past_singlestep_breakpoint\n");
 	  /* Pull the single step breakpoints out of the target.  */
-	  SOFTWARE_SINGLE_STEP (0, 0);
+	  (void) SOFTWARE_SINGLE_STEP (0, 0);
 	  singlestep_breakpoints_inserted_p = 0;
 
 	  ecs->random_signal = 0;
@@ -1640,7 +1642,7 @@
 	  if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
 	    {
 	      /* Pull the single step breakpoints out of the target. */
-	      SOFTWARE_SINGLE_STEP (0, 0);
+	      (void) SOFTWARE_SINGLE_STEP (0, 0);
 	      singlestep_breakpoints_inserted_p = 0;
 	    }
 
@@ -1713,7 +1715,7 @@
   if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
     {
       /* Pull the single step breakpoints out of the target. */
-      SOFTWARE_SINGLE_STEP (0, 0);
+      (void) SOFTWARE_SINGLE_STEP (0, 0);
       singlestep_breakpoints_inserted_p = 0;
     }
 
--- mips-tdep.c
+++ mips-tdep.c
@@ -2185,7 +2185,7 @@
    single_step is also called just after the inferior stops.  If we had
    set up a simulated single-step, we undo our damage.  */
 
-void
+int
 mips_software_single_step (enum target_signal sig, int insert_breakpoints_p)
 {
   CORE_ADDR pc, next_pc;
@@ -2199,6 +2199,8 @@
     }
   else
     remove_single_step_breakpoints ();
+
+  return 1;
 }
 
 /* Test whether the PC points to the return instruction at the
--- mips-tdep.h
+++ mips-tdep.h
@@ -103,7 +103,7 @@
 };
 
 /* Single step based on where the current instruction will take us.  */
-extern void mips_software_single_step (enum target_signal, int);
+extern int mips_software_single_step (enum target_signal, int);
 
 /* Tell if the program counter value in MEMADDR is in a MIPS16
    function.  */
--- ppc-linux-tdep.c
+++ ppc-linux-tdep.c
@@ -931,6 +931,90 @@
   trad_frame_set_id (this_cache, frame_id_build (base, func));
 }
 
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7C000028
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define BC_MASK 0xfc000000
+#define BC_INSTRUCTION 0x40000000
+#define IMMEDIATE_PART(insn)  (((insn & ~3) << 16) >> 16)
+#define ABSOLUTE_P(insn) ((int) ((insn >> 1) & 1))
+
+static int 
+ppc_atomic_single_step (enum target_signal sig, int insert_breakpoints_p)
+{
+  if (insert_breakpoints_p)
+    {
+      CORE_ADDR pc = read_pc ();
+      CORE_ADDR breaks[2] = {-1, -1};
+      CORE_ADDR loc = pc;
+      int insn = read_insn (loc);
+      int last_break = 0;
+      int i;
+
+
+      /* Assume all atomic sequences start with an lwarx instruction. */
+      if ((insn & LWARX_MASK) != LWARX_INSTRUCTION)
+         return 0;
+
+      /* Assume that no atomic sequence is longer than 6 instructions. */
+      for (i = 1; i < 5; ++i)
+	{
+	  loc += PPC_INSN_SIZE;
+	  insn = read_insn (loc);
+
+	  /* Assume at most one conditional branch instruction between
+	     the lwarx and stwcx instructions.*/
+	  if ((insn & BC_MASK) == BC_INSTRUCTION)
+	    {
+	      last_break = 1;
+	      breaks[1] = IMMEDIATE_PART (insn);
+	      if (! ABSOLUTE_P (insn))
+		breaks[1] += loc;
+	      continue;
+	    }
+
+	  if ((insn & STWCX_MASK) == STWCX_INSTRUCTION)
+	    break;
+	}
+
+      /* Assume that the atomic sequence ends with a stwcx instruction
+         followed by a conditional branch instruction. */
+      if ((insn & STWCX_MASK) != STWCX_INSTRUCTION)
+	{
+	  warning (_("Tried to step over an atomic sequence of instructions but could not find the end of the sequence."));
+	  return 0;
+	}
+
+      loc += PPC_INSN_SIZE;
+      insn = read_insn (loc);
+
+      if ((insn & BC_MASK) != BC_INSTRUCTION)
+	{
+	  warning (_("Tried to step over an atomic sequence of instructions but it did not end as expected."));
+	  return 0;
+	}
+
+      breaks[0] = loc;
+
+      /* This should never happen, but make sure we don't but
+	 two breakpoints on the same address. */
+      if (last_break && breaks[1] == breaks[0])
+	last_break = 0;
+
+      for (i= 0; i <= last_break; ++i)
+	insert_single_step_breakpoint (breaks[i]);
+
+      printf_unfiltered (_("Stepping over an atomic sequence of instructions beginning at %s\n"),
+			 core_addr_to_string (pc));
+      gdb_flush (gdb_stdout);
+    }
+  else
+    remove_single_step_breakpoints ();
+
+  return 1;
+}
+
 static void
 ppc32_linux_sigaction_cache_init (const struct tramp_frame *self,
 				  struct frame_info *next_frame,
@@ -1086,6 +1170,10 @@
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
+
+  /* Enable software_single_step in case someone tries to sngle step a
+     sequence of instructions that should be atomic. */
+  set_gdbarch_software_single_step (gdbarch, ppc_atomic_single_step);
 }
 
 void
--- rs6000-tdep.c
+++ rs6000-tdep.c
@@ -702,10 +702,89 @@
     return little_breakpoint;
 }
 
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7C000028
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define BC_MASK 0xfc000000
+#define BC_INSTRUCTION 0x40000000
+#define IMMEDIATE_PART(insn)  (((insn & ~3) << 16) >> 16)
+#define ABSOLUTE_P(insn) ((int) ((insn >> 1) & 1))
+
+static int 
+deal_with_atomic_sequence (enum target_signal sig)
+{
+  CORE_ADDR pc = read_pc ();
+  CORE_ADDR breaks[2] = {-1, -1};
+  CORE_ADDR loc = pc;
+  int insn = read_memory_integer (loc, 4);
+  int last_break = 0;
+  int i;
 
-/* AIX does not support PT_STEP. Simulate it. */
 
-void
+  /* Assume all atomic sequences start with an lwarx instruction. */
+  if ((insn & LWARX_MASK) != LWARX_INSTRUCTION)
+     return 0;
+
+  /* Assume that no atomic sequence is longer than 6 instructions. */
+  for (i = 1; i < 5; ++i)
+    {
+      loc += PPC_INSN_SIZE;
+      insn = read_memory_integer (loc, 4);
+
+      /* Assume at most one conditional branch instruction between
+ 	 the lwarx and stwcx instructions.*/
+      if ((insn & BC_MASK) == BC_INSTRUCTION)
+	{
+	  last_break = 1;
+	  breaks[1] = IMMEDIATE_PART (insn);
+	  if (! ABSOLUTE_P (insn))
+	    breaks[1] += loc;
+	    continue;
+	}
+
+      if ((insn & STWCX_MASK) == STWCX_INSTRUCTION)
+	break;
+    }
+
+  /* Assume that the atomic sequence ends with a stwcx instruction
+       followed by a conditional branch instruction. */
+  if ((insn & STWCX_MASK) != STWCX_INSTRUCTION)
+    {
+      warning (_("Tried to step over an atomic sequence of instructions but could not find the end of the sequence."));
+      return 0;
+    }
+
+  loc += PPC_INSN_SIZE;
+  insn = read_memory_integer (loc, 4);
+
+  if ((insn & BC_MASK) != BC_INSTRUCTION)
+    {
+      warning (_("Tried to step over an atomic sequence of instructions but it did not end as expected."));
+      return 0;
+    }
+
+  breaks[0] = loc;
+
+  /* This should never happen, but make sure we don't but
+     two breakpoints on the same address. */
+  if (last_break && breaks[1] == breaks[0])
+    last_break = 0;
+
+  for (i= 0; i <= last_break; ++i)
+    insert_single_step_breakpoint (breaks[i]);
+
+  printf_unfiltered (_("Stepping over an atomic sequence of instructions beginning at %s\n"),
+		     core_addr_to_string (pc));
+  gdb_flush (gdb_stdout);
+
+  return 1;
+}
+
+/* AIX does not support PT_STEP. Simulate it, dealing with any sequence of
+   instructions that must be atomic. */
+
+int
 rs6000_software_single_step (enum target_signal signal,
 			     int insert_breakpoints_p)
 {
@@ -723,6 +802,9 @@
 
       insn = read_memory_integer (loc, 4);
 
+      if (deal_with_atomic_sequence (signal))
+	return 1;
+
       breaks[0] = loc + breakp_sz;
       opcode = insn >> 26;
       breaks[1] = branch_dest (opcode, insn, loc, breaks[0]);
@@ -744,6 +826,8 @@
 
   errno = 0;			/* FIXME, don't ignore errors! */
   /* What errors?  {read,write}_memory call error().  */
+
+  return 1;
 }
 
 
--- rs6000-tdep.h
+++ rs6000-tdep.h
@@ -21,6 +21,6 @@
 
 #include "defs.h"
 
-extern void rs6000_software_single_step (enum target_signal signal,
-					 int insert_breakpoints_p);
+extern int rs6000_software_single_step (enum target_signal signal,
+                                        int insert_breakpoints_p);
 
--- sparc-tdep.c
+++ sparc-tdep.c
@@ -1131,7 +1131,7 @@
   return 0;
 }
 
-void
+int
 sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
 {
   struct gdbarch *arch = current_gdbarch;
@@ -1161,6 +1161,8 @@
     }
   else
     remove_single_step_breakpoints ();
+
+  return 1;
 }
 
 static void
--- sparc-tdep.h
+++ sparc-tdep.h
@@ -167,8 +167,8 @@
 
 
 
-extern void sparc_software_single_step (enum target_signal sig,
-					int insert_breakpoints_p);
+extern int sparc_software_single_step (enum target_signal sig,
+                                       int insert_breakpoints_p);
 
 extern void sparc_supply_rwindow (struct regcache *regcache,
 				  CORE_ADDR sp, int regnum);
--- wince.c
+++ wince.c
@@ -838,7 +838,7 @@
     }
 }
 
-void
+int
 wince_software_single_step (enum target_signal ignore,
 			    int insert_breakpoints_p)
 {
@@ -850,14 +850,15 @@
   if (!insert_breakpoints_p)
     {
       undoSStep (th);
-      return;
+      return 1;
     }
 
   th->stepped = 1;
   pc = read_register (PC_REGNUM);
   th->step_pc = mips_next_pc (pc);
   insert_single_step_breakpoint (th->step_pc);
-  return;
+
+  return 1;
 }
 #elif SHx
 /* Renesas SH architecture instruction encoding masks */
@@ -979,7 +980,7 @@
    instruction and setting a breakpoint on the "next" instruction
    which would be executed.  This code hails from sh-stub.c.
  */
-void
+int
 wince_software_single_step (enum target_signal ignore,
 			    int insert_breakpoints_p)
 {
@@ -989,13 +990,14 @@
   if (!insert_breakpoints_p)
     {
       undoSStep (th);
-      return;
+      return 1;
     }
 
   th->stepped = 1;
   th->step_pc = sh_get_next_pc (&th->context);
   insert_single_step_breakpoint (th->step_pc);
-  return;
+
+  return 1;
 }
 #elif defined (ARM)
 #undef check_for_step
@@ -1026,7 +1028,7 @@
     }
 }
 
-void
+int
 wince_software_single_step (enum target_signal ignore,
 			    int insert_breakpoints_p)
 {
@@ -1038,14 +1040,15 @@
   if (!insert_breakpoints_p)
     {
       undoSStep (th);
-      return;
+      return 1;
     }
 
   th->stepped = 1;
   pc = read_register (PC_REGNUM);
   th->step_pc = arm_get_next_pc (pc);
   insert_single_step_breakpoint (th->step_pc);
-  return;
+
+  return 1;
 }
 #endif
 
openSUSE Build Service is sponsored by