Refactor queries for hardware and software single stepping support in GDBServer.
authorAntoine Tremblay <antoine.tremblay@ericsson.com>
Thu, 19 Nov 2015 16:29:10 +0000 (11:29 -0500)
committerAntoine Tremblay <antoine.tremblay@ericsson.com>
Mon, 30 Nov 2015 20:17:36 +0000 (15:17 -0500)
Before this patch there was only one call: can_hardware_single_step. Its
implementation was a check on breakpoint_reinsert_addr if NULL it assumed
that the target could hardware single step.

This patch prepares for the case where this is not true anymore.

In order to improve software single stepping in GDBServer the
breakpoint_reinsert_addr operation of targets that had a very simple
software implementation used only for stepping over thread creation events
will be removed.

This will create a case where a target does not support hardware single
step and has the operation breakpoint_reinsert_addr set to NULL, thus
can_hardware_single_step needs to be implemented another way.

A new target operation supports_hardware_single_step is introduced and is
to return true if the target does support such a feature, support for the
feature is manually hardcoded.

Note that the hardware single step support was enabled as per the current
behavior, I did not check if tile for example really has ptrace singlestep
support but since the current implementation assumed it had, I kept it
that way.

No regressions on Ubuntu 14.04 on ARMv7 and x86.
With gdbserver-{native,extended} / { -marm -mthumb }

Compilation tested on: aarch64,arm,bfind,crisv32,m32r,ppc,s390,tic6x,tile,
xtensa.
Not tested : sh.

gdb/gdbserver/ChangeLog:

* linux-aarch64-low.c (aarch64_supports_hardware_single_step):
New function.
(struct linux_target_ops) <supports_hardware_single_step>: Initialize.
* linux-arm-low.c (arm_supports_hardware_single_step): New function.
(struct linux_target_ops) <supports_hardware_single_step>: Initialize.
* linux-bfin-low.c (bfin_supports_hardware_single_step): New function.
(struct linux_target_ops) <bfin_supports_hardware_single_step>:
Initialize.
* linux-crisv32-low.c (cris_supports_hardware_single_step):
New function.
(struct linux_target_ops) <supports_hardware_single_step>: Initialize.
* linux-low.c (can_hardware_single_step): Use
supports_hardware_single_step.
(can_software_single_step): New function.
(start_step_over): Call can_software_single_step.
(linux_supports_hardware_single_step): New function.
(struct target_ops) <supports_software_single_step>: Initialize.
* linux-low.h (struct linux_target_ops)
<supports_hardware_single_step>: Initialize.
* linux-m32r-low.c (m32r_supports_hardware_single_step): New function.
(struct linux_target_ops) <supports_hardware_single_step>: Initialize.
* linux-ppc-low.c (ppc_supports_hardware_single_step): New function.
(struct linux_target_ops) <supports_hardware_single_step> Initialize.
* linux-s390-low.c (s390_supports_hardware_single_step): New function.
(struct linux_target_ops) <supports_hardware_single_step>: Initialize.
* linux-sh-low.c (sh_supports_hardware_single_step): New function.
(struct linux_target_ops) <supports_hardware_single_step>: Initialize.
* linux-tic6x-low.c (tic6x_supports_hardware_single_step): New function.
(struct linux_target_ops) <tic6x_supports_hardware_single_step>:
Initialize.
* linux-tile-low.c (tile_supports_hardware_single_step): New function.
(struct linux_target_ops) <tile_supports_hardware_single_step>:
Initialize.
* linux-x86-low.c (x86_supports_hardware_single_step) New function.
(struct linux_target_ops) <supports_hardware_single_step>: Initialize.
* linux-xtensa-low.c (xtensa_supports_hardware_single_step):
New function.
(struct linux_target_ops) <supports_hardware_single_step>: Initialize.
* target.h (struct target_ops): <supports_software_single_step>:
New field.
(target_supports_software_single_step): New macro.

16 files changed:
gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-aarch64-low.c
gdb/gdbserver/linux-arm-low.c
gdb/gdbserver/linux-bfin-low.c
gdb/gdbserver/linux-crisv32-low.c
gdb/gdbserver/linux-low.c
gdb/gdbserver/linux-low.h
gdb/gdbserver/linux-m32r-low.c
gdb/gdbserver/linux-ppc-low.c
gdb/gdbserver/linux-s390-low.c
gdb/gdbserver/linux-sh-low.c
gdb/gdbserver/linux-tic6x-low.c
gdb/gdbserver/linux-tile-low.c
gdb/gdbserver/linux-x86-low.c
gdb/gdbserver/linux-xtensa-low.c
gdb/gdbserver/target.h

index f48d7f271e14b4682f750dba840f4b58b526aae0..4f25205c93d73de143f536c976f06322d1e570c5 100644 (file)
@@ -1,3 +1,47 @@
+2015-11-30  Antoine Tremblay  <antoine.tremblay@ericsson.com>
+
+       * linux-aarch64-low.c (aarch64_supports_hardware_single_step):
+       New function.
+       (struct linux_target_ops) <supports_hardware_single_step>: Initialize.
+       * linux-arm-low.c (arm_supports_hardware_single_step): New function.
+       (struct linux_target_ops) <supports_hardware_single_step>: Initialize.
+       * linux-bfin-low.c (bfin_supports_hardware_single_step): New function.
+       (struct linux_target_ops) <bfin_supports_hardware_single_step>:
+       Initialize.
+       * linux-crisv32-low.c (cris_supports_hardware_single_step):
+       New function.
+       (struct linux_target_ops) <supports_hardware_single_step>: Initialize.
+       * linux-low.c (can_hardware_single_step): Use
+       supports_hardware_single_step.
+       (can_software_single_step): New function.
+       (start_step_over): Call can_software_single_step.
+       (linux_supports_hardware_single_step): New function.
+       (struct target_ops) <supports_software_single_step>: Initialize.
+       * linux-low.h (struct linux_target_ops)
+       <supports_hardware_single_step>: Initialize.
+       * linux-m32r-low.c (m32r_supports_hardware_single_step): New function.
+       (struct linux_target_ops) <supports_hardware_single_step>: Initialize.
+       * linux-ppc-low.c (ppc_supports_hardware_single_step): New function.
+       (struct linux_target_ops) <supports_hardware_single_step> Initialize.
+       * linux-s390-low.c (s390_supports_hardware_single_step): New function.
+       (struct linux_target_ops) <supports_hardware_single_step>: Initialize.
+       * linux-sh-low.c (sh_supports_hardware_single_step): New function.
+       (struct linux_target_ops) <supports_hardware_single_step>: Initialize.
+       * linux-tic6x-low.c (tic6x_supports_hardware_single_step): New function.
+       (struct linux_target_ops) <tic6x_supports_hardware_single_step>:
+       Initialize.
+       * linux-tile-low.c (tile_supports_hardware_single_step): New function.
+       (struct linux_target_ops) <tile_supports_hardware_single_step>:
+       Initialize.
+       * linux-x86-low.c (x86_supports_hardware_single_step) New function.
+       (struct linux_target_ops) <supports_hardware_single_step>: Initialize.
+       * linux-xtensa-low.c (xtensa_supports_hardware_single_step):
+       New function.
+       (struct linux_target_ops) <supports_hardware_single_step>: Initialize.
+       * target.h (struct target_ops): <supports_software_single_step>:
+       New field.
+       (target_supports_software_single_step): New macro.
+
 2015-11-30  Antoine Tremblay  <antoine.tremblay@ericsson.com>
 
        * linux-low.c (linux_wait_1): Fix pc advance condition.
index cb7866646272f375a9378f88c12fee3448d4cd5c..17798ff24a34a51caac1f3ef15a1329c531293c1 100644 (file)
@@ -2944,6 +2944,14 @@ aarch64_sw_breakpoint_from_kind (int kind, int *size)
   return aarch64_breakpoint;
 }
 
+/* Support for hardware single step.  */
+
+static int
+aarch64_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 struct linux_target_ops the_low_target =
 {
   aarch64_arch_setup,
@@ -2977,6 +2985,8 @@ struct linux_target_ops the_low_target =
   aarch64_emit_ops,
   aarch64_get_min_fast_tracepoint_insn_len,
   aarch64_supports_range_stepping,
+  NULL, /* breakpoint_kind_from_current_state */
+  aarch64_supports_hardware_single_step,
 };
 
 void
index 6f37f581096a02c6014df6da2655698cb0573f55..0c788886159f464f411c2944889ab917fe930907 100644 (file)
@@ -902,6 +902,14 @@ arm_arch_setup (void)
     have_ptrace_getregset = 0;
 }
 
+/* Support for hardware single step.  */
+
+static int
+arm_supports_hardware_single_step (void)
+{
+  return 0;
+}
+
 /* Register sets without using PTRACE_GETREGSET.  */
 
 static struct regset_info arm_regsets[] = {
@@ -1058,7 +1066,8 @@ struct linux_target_ops the_low_target = {
   NULL, /* emit_ops */
   NULL, /* get_min_fast_tracepoint_insn_len */
   NULL, /* supports_range_stepping */
-  arm_breakpoint_kind_from_current_state
+  arm_breakpoint_kind_from_current_state,
+  arm_supports_hardware_single_step
 };
 
 void
index d3b83fc827e971996c5201dc4945a30dd5204784..912d253342c466dd05defb95df49c53d785e66d7 100644 (file)
@@ -105,6 +105,14 @@ bfin_arch_setup (void)
   current_process ()->tdesc = tdesc_bfin;
 }
 
+/* Support for hardware single step.  */
+
+static int
+bfin_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 static struct usrregs_info bfin_usrregs_info =
   {
     bfin_num_regs,
@@ -136,6 +144,27 @@ struct linux_target_ops the_low_target = {
   NULL, /* breakpoint_reinsert_addr */
   2,
   bfin_breakpoint_at,
+  NULL, /* supports_z_point_type */
+  NULL, /* insert_point */
+  NULL, /* remove_point */
+  NULL, /* stopped_by_watchpoint */
+  NULL, /* stopped_data_address */
+  NULL, /* collect_ptrace_register */
+  NULL, /* supply_ptrace_register */
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* new_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  bfin_supports_hardware_single_step,
 };
 
 
index 8d9ef04c5762ce1a90dff1e144a8930e1f2685a6..4f9afa6d9f0edcf89070b55c155e8d21ffc4eb4b 100644 (file)
@@ -388,6 +388,14 @@ cris_arch_setup (void)
   current_process ()->tdesc = tdesc_crisv32;
 }
 
+/* Support for hardware single step.  */
+
+static int
+cris_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 static struct regset_info cris_regsets[] = {
   { PTRACE_GETREGS, PTRACE_SETREGS, 0, cris_num_regs * 4,
     GENERAL_REGS, cris_fill_gregset, cris_store_gregset },
@@ -439,6 +447,22 @@ struct linux_target_ops the_low_target = {
   cris_remove_point,
   cris_stopped_by_watchpoint,
   cris_stopped_data_address,
+  NULL, /* collect_ptrace_register */
+  NULL, /* supply_ptrace_register */
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* new_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  cris_supports_hardware_single_step,
 };
 
 void
index b29f54e523d4b40be7ede9f2b9e96c3b50d58936..cfc5987e092ace8af54b243ef93b4f0e391e118e 100644 (file)
@@ -269,13 +269,24 @@ static void complete_ongoing_step_over (void);
    being stepped.  */
 ptid_t step_over_bkpt;
 
-/* True if the low target can hardware single-step.  Such targets
-   don't need a BREAKPOINT_REINSERT_ADDR callback.  */
+/* True if the low target can hardware single-step.  */
 
 static int
 can_hardware_single_step (void)
 {
-  return (the_low_target.breakpoint_reinsert_addr == NULL);
+  if (the_low_target.supports_hardware_single_step != NULL)
+    return the_low_target.supports_hardware_single_step ();
+  else
+    return 0;
+}
+
+/* True if the low target can software single-step.  Such targets
+   implement the BREAKPOINT_REINSERT_ADDR callback.  */
+
+static int
+can_software_single_step (void)
+{
+  return (the_low_target.breakpoint_reinsert_addr != NULL);
 }
 
 /* True if the low target supports memory breakpoints.  If so, we'll
@@ -4509,12 +4520,17 @@ start_step_over (struct lwp_info *lwp)
     {
       step = 1;
     }
-  else
+  else if (can_software_single_step ())
     {
       CORE_ADDR raddr = (*the_low_target.breakpoint_reinsert_addr) ();
       set_reinsert_breakpoint (raddr);
       step = 0;
     }
+  else
+    {
+      internal_error (__FILE__, __LINE__,
+                     "stepping is not implemented on this target");
+    }
 
   current_thread = saved_thread;
 
@@ -5713,6 +5729,12 @@ linux_supports_hardware_single_step (void)
   return can_hardware_single_step ();
 }
 
+static int
+linux_supports_software_single_step (void)
+{
+  return can_software_single_step ();
+}
+
 static int
 linux_stopped_by_watchpoint (void)
 {
@@ -7153,7 +7175,8 @@ static struct target_ops linux_target_ops = {
   linux_breakpoint_kind_from_pc,
   linux_sw_breakpoint_from_kind,
   linux_proc_tid_get_name,
-  linux_breakpoint_kind_from_current_state
+  linux_breakpoint_kind_from_current_state,
+  linux_supports_software_single_step
 };
 
 static void
index e2bfeb70c18504d9c1691b67183e0fdff64ffbf7..24ea2d35fbfe11c1f68b782de37753e3668dd51a 100644 (file)
@@ -236,6 +236,9 @@ struct linux_target_ops
 
   /* See target.h.  */
   int (*breakpoint_kind_from_current_state) (CORE_ADDR *pcptr);
+
+  /* See target.h.  */
+  int (*supports_hardware_single_step) (void);
 };
 
 extern struct linux_target_ops the_low_target;
index bb1002f9db4a2b4e601fc8cf4196f88f30decd90..c6d79b64febc67b6004dc615170805420993cab7 100644 (file)
@@ -103,6 +103,14 @@ m32r_arch_setup (void)
   current_process ()->tdesc = tdesc_m32r;
 }
 
+/* Support for hardware single step.  */
+
+static int
+m32r_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 static struct usrregs_info m32r_usrregs_info =
   {
     m32r_num_regs,
@@ -134,6 +142,27 @@ struct linux_target_ops the_low_target = {
   NULL,
   0,
   m32r_breakpoint_at,
+  NULL, /* supports_z_point_type */
+  NULL, /* insert_point */
+  NULL, /* remove_point */
+  NULL, /* stopped_by_watchpoint */
+  NULL, /* stopped_data_address */
+  NULL, /* collect_ptrace_register */
+  NULL, /* supply_ptrace_register */
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* new_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  m32r_supports_hardware_single_step,
 };
 
 void
index 995a725c536b7ce03aa4911d7b149617ee139da7..decee86b1e62e3640e58777f70854421e387b895 100644 (file)
@@ -547,6 +547,14 @@ ppc_store_evrregset (struct regcache *regcache, const void *buf)
   supply_register_by_name (regcache, "spefscr", &regset->spefscr);
 }
 
+/* Support for hardware single step.  */
+
+static int
+ppc_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 static struct regset_info ppc_regsets[] = {
   /* List the extra register sets before GENERAL_REGS.  That way we will
      fetch them every time, but still fall back to PTRACE_PEEKUSER for the
@@ -705,6 +713,20 @@ struct linux_target_ops the_low_target = {
   NULL,
   ppc_collect_ptrace_register,
   ppc_supply_ptrace_register,
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* new_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  ppc_supports_hardware_single_step,
 };
 
 void
index efede2de74b056e25235d1c2f946ccf09f1883c1..7127373a147e96b19fba7c1344ab4a182f4067d8 100644 (file)
@@ -609,6 +609,14 @@ s390_breakpoint_at (CORE_ADDR pc)
   return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
 }
 
+/* Support for hardware single step.  */
+
+static int
+s390_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 static struct usrregs_info s390_usrregs_info =
   {
     s390_num_regs,
@@ -686,6 +694,20 @@ struct linux_target_ops the_low_target = {
   NULL,
   s390_collect_ptrace_register,
   s390_supply_ptrace_register,
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* new_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  s390_supports_hardware_single_step,
 };
 
 void
index 207e87e02818f50cecc12d6945cd480c15cd2dc8..1b3189b244834ccc9b5973c4b98753fb5a09c5c4 100644 (file)
@@ -100,6 +100,14 @@ sh_breakpoint_at (CORE_ADDR where)
   return 0;
 }
 
+/* Support for hardware single step.  */
+
+static int
+sh_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 /* Provide only a fill function for the general register set.  ps_lgetregs
    will use this for NPTL support.  */
 
@@ -162,6 +170,27 @@ struct linux_target_ops the_low_target = {
   NULL,
   0,
   sh_breakpoint_at,
+  NULL, /* supports_z_point_type */
+  NULL, /* insert_point */
+  NULL, /* remove_point */
+  NULL, /* stopped_by_watchpoint */
+  NULL, /* stopped_data_address */
+  NULL, /* collect_ptrace_register */
+  NULL, /* supply_ptrace_register */
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* new_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  sh_supports_hardware_single_step,
 };
 
 void
index cf8b5fb4615468cde7c93508d234036f7590d612..e4aba15f3932b36e36e234538a57f0954e7924de 100644 (file)
@@ -341,6 +341,14 @@ tic6x_arch_setup (void)
   current_process ()->tdesc = tic6x_read_description ();
 }
 
+/* Support for hardware single step.  */
+
+static int
+tic6x_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 static struct regsets_info tic6x_regsets_info =
   {
     tic6x_regsets, /* regsets */
@@ -380,6 +388,27 @@ struct linux_target_ops the_low_target = {
   NULL,
   0,
   tic6x_breakpoint_at,
+  NULL, /* supports_z_point_type */
+  NULL, /* insert_point */
+  NULL, /* remove_point */
+  NULL, /* stopped_by_watchpoint */
+  NULL, /* stopped_data_address */
+  NULL, /* collect_ptrace_register */
+  NULL, /* supply_ptrace_register */
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* new_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  tic6x_supports_hardware_single_step,
 };
 
 void
index 47ca245215ec42dc838a45181064cd34c1e3d9ca..6f1635512e4c57a6635e798b52b51d1c2d3a7aca 100644 (file)
@@ -181,6 +181,14 @@ tile_arch_setup (void)
     current_process ()->tdesc = tdesc_tilegx;
 }
 
+/* Support for hardware single step.  */
+
+static int
+tile_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 
 struct linux_target_ops the_low_target =
 {
@@ -196,6 +204,27 @@ struct linux_target_ops the_low_target =
   NULL,
   0,
   tile_breakpoint_at,
+  NULL, /* supports_z_point_type */
+  NULL, /* insert_point */
+  NULL, /* remove_point */
+  NULL, /* stopped_by_watchpoint */
+  NULL, /* stopped_data_address */
+  NULL, /* collect_ptrace_register */
+  NULL, /* supply_ptrace_register */
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* new_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  tile_supports_hardware_single_step,
 };
 
 void
index 7f0719401a5299f50360c23ab767b23db53a8af1..18adf5ee7d17e34dc2a3b7d74faa3e63790e27ef 100644 (file)
@@ -3264,6 +3264,15 @@ x86_supports_range_stepping (void)
   return 1;
 }
 
+/* Implementation of linux_target_ops method "supports_hardware_single_step".
+ */
+
+static int
+x86_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 /* This is initialized assuming an amd64 target.
    x86_arch_setup will correct it for i386 or amd64 targets.  */
 
@@ -3304,6 +3313,8 @@ struct linux_target_ops the_low_target =
   x86_emit_ops,
   x86_get_min_fast_tracepoint_insn_len,
   x86_supports_range_stepping,
+  NULL, /* breakpoint_kind_from_current_state */
+  x86_supports_hardware_single_step,
 };
 
 void
index 7c71631ad9d41e8822421f0e1673ec5d189cf0c6..b48e8dd83bb0a9ae3e29217ed32409011ed2d91f 100644 (file)
@@ -229,6 +229,14 @@ xtensa_arch_setup (void)
   current_process ()->tdesc = tdesc_xtensa;
 }
 
+/* Support for hardware single step.  */
+
+static int
+xtensa_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 static const struct regs_info *
 xtensa_regs_info (void)
 {
@@ -248,6 +256,27 @@ struct linux_target_ops the_low_target = {
   NULL,
   0,
   xtensa_breakpoint_at,
+  NULL, /* supports_z_point_type */
+  NULL, /* insert_point */
+  NULL, /* remove_point */
+  NULL, /* stopped_by_watchpoint */
+  NULL, /* stopped_data_address */
+  NULL, /* collect_ptrace_register */
+  NULL, /* supply_ptrace_register */
+  NULL, /* siginfo_fixup */
+  NULL, /* new_process */
+  NULL, /* new_thread */
+  NULL, /* new_fork */
+  NULL, /* prepare_to_resume */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* get_thread_area */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* supports_range_stepping */
+  NULL, /* breakpoint_kind_from_current_state */
+  xtensa_supports_hardware_single_step,
 };
 
 
index d3fcb36033330a89af55d18f5474b6b5ee7e3c9f..9cd07bc2d945d13410e4431c6b357458a1e7d386 100644 (file)
@@ -463,6 +463,9 @@ struct target_ops
      PC.  The PCPTR is adjusted to the real memory location in case a flag
      (e.g., the Thumb bit on ARM) is present in the PC.  */
   int (*breakpoint_kind_from_current_state) (CORE_ADDR *pcptr);
+
+  /* Returns true if the target can software single step.  */
+  int (*supports_software_single_step) (void);
 };
 
 extern struct target_ops *the_target;
@@ -655,6 +658,10 @@ int kill_inferior (int);
    ? (*the_target->breakpoint_kind_from_current_state) (pcptr) \
    : target_breakpoint_kind_from_pc (pcptr))
 
+#define target_supports_software_single_step() \
+  (the_target->supports_software_single_step ? \
+   (*the_target->supports_software_single_step) () : 0)
+
 /* Start non-stop mode, returns 0 on success, -1 on failure.   */
 
 int start_non_stop (int nonstop);