Extending RSP with vCont;n and vCont;f

ILG.Robert R.ILG@bachmann.info
Wed Oct 2 15:08:00 GMT 2013


Hallo,

we would like to improve the RSP command "vCont" for remote debugging. It seems that the range option has been introduced recently to get rid of time consuming, successive single-steps. Our intention is to get rid of further, unnecessary RSP packages being sent as our target is capable to do a step-over (called next by GDB) and a step-return (called finish by GDB). Therefore we propose to extend the vCont command with "vCont;n" and "vCont;f" as well.

You will find the necessary patch below. It has been tested on MinGW with a x86-Target. It's based on the todays trunk.

Thanks in advance. 
Robert Ilg

diff --git a/gdb/remote.c b/gdb/remote.c
index a9ef297..df31c3a 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -256,11 +256,19 @@

   /* vCont;r */
   int r;
+
+  /* vCont;f */
+  int f;
+
+  /* vCont;n */
+  int n;
};

 /* Controls whether GDB is willing to use range stepping.  */

 static int use_range_stepping = 1;
+static int use_finish_stepping = 1;
+static int use_next_stepping = 1;

 #define OPAQUETHREADBYTES 8

@@ -4704,6 +4712,8 @@
       support_C = 0;
       rs->supports_vCont.t = 0;
       rs->supports_vCont.r = 0;
+      rs->supports_vCont.n = 0;
+      rs->supports_vCont.f = 0;
       while (p && *p == ';')
    {
      p++;
@@ -4719,6 +4729,10 @@
        rs->supports_vCont.t = 1;
      else if (*p == 'r' && (*(p + 1) == ';' || *(p + 1) == 0))
        rs->supports_vCont.r = 1;
+      else if (*p == 'f' && (*(p + 1) == ';' || *(p + 1) == 0))
+        rs->supports_vCont.f = 1;
+      else if (*p == 'n' && (*(p + 1) == ';' || *(p + 1) == 0))
+        rs->supports_vCont.n = 1;

       p = strchr (p, ';');
    }
@@ -4747,9 +4761,29 @@
            ptid_t ptid, int step, enum gdb_signal siggnal)
{
   struct remote_state *rs = get_remote_state ();
+  struct thread_info *tp;
+
+  if (ptid_equal (ptid, minus_one_ptid))
+  {
+    /* If we don't know about the target thread's tid, then
+     * we're resuming magic_null_ptid (see caller).  */
+    tp = find_thread_ptid (magic_null_ptid);
+   }
+   else
+     tp = find_thread_ptid (ptid);

+   gdb_assert (tp != NULL);
+
   if (step && siggnal != GDB_SIGNAL_0)
     p += xsnprintf (p, endp - p, ";S%02x", siggnal);
+  else if (
+       /* GDB is willing to step next and target supports it */
+       use_next_stepping && rs->supports_vCont.n &&
+       /* step next is suitable for this resumption */
+       step && (tp->control.step_over_calls == STEP_OVER_ALL))
+  {
+    p += xsnprintf (p, endp - p, ";n");
+  }
   else if (step
       /* GDB is willing to range step.  */
       && use_range_stepping
@@ -4761,18 +4795,6 @@
          it).  */
       && !(remote_multi_process_p (rs) && ptid_is_pid (ptid)))
     {
-      struct thread_info *tp;
-
-      if (ptid_equal (ptid, minus_one_ptid))
-    {
-      /* If we don't know about the target thread's tid, then
-         we're resuming magic_null_ptid (see caller).  */
-      tp = find_thread_ptid (magic_null_ptid);
-    }
-      else
-    tp = find_thread_ptid (ptid);
-      gdb_assert (tp != NULL);
-
       if (tp->control.may_range_step)
    {
      int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8;
@@ -4790,6 +4812,14 @@
     p += xsnprintf (p, endp - p, ";s");
   else if (siggnal != GDB_SIGNAL_0)
     p += xsnprintf (p, endp - p, ";C%02x", siggnal);
+  else if (
+       /* GDB is willing to step next and target supports it */
+       use_finish_stepping && rs->supports_vCont.f &&
+       /* step finish is suitable for this resumption */
+       (tp->control.proceed_to_finish == 1))
+  {
+    p += xsnprintf (p, endp - p, ";f");
+  }
   else
     p += xsnprintf (p, endp - p, ";c");

@@ -11760,6 +11790,82 @@
     }
}

+/* The "set/show next-stepping" show hook.  */
+
+static void
+show_next_stepping (struct ui_file *file, int from_tty,
+             struct cmd_list_element *c,
+             const char *value)
+{
+  fprintf_filtered (file,
+            _("Debugger's willingness to use next stepping "
+              "is %s.\n"), value);
+}
+
+/* The "set/show next-stepping" set hook.  */
+
+static void
+set_next_stepping (char *ignore_args, int from_tty,
+            struct cmd_list_element *c)
+{
+  /* When enabling, check whether next stepping is actually
+     supported by the target, and warn if not.  */
+  if (use_next_stepping)
+    {
+      if (remote_desc != NULL)
+    {
+      struct remote_state *rs = get_remote_state ();
+
+      if (remote_protocol_packets[PACKET_vCont].support == PACKET_SUPPORT_UNKNOWN)
+        remote_vcont_probe (rs);
+
+      if (remote_protocol_packets[PACKET_vCont].support == PACKET_ENABLE
+          && rs->supports_vCont.n)
+        return;
+    }
+
+      warning (_("Next stepping is not supported by the current target"));
+    }
+}
+
+/* The "set/show finish-stepping" show hook.  */
+
+static void
+show_finish_stepping (struct ui_file *file, int from_tty,
+             struct cmd_list_element *c,
+             const char *value)
+{
+  fprintf_filtered (file,
+            _("Debugger's willingness to use finish stepping "
+              "is %s.\n"), value);
+}
+
+/* The "set/show finish-stepping" set hook.  */
+
+static void
+set_finish_stepping (char *ignore_args, int from_tty,
+            struct cmd_list_element *c)
+{
+  /* When enabling, check whether finish stepping is actually
+     supported by the target, and warn if not.  */
+  if (use_finish_stepping)
+    {
+      if (remote_desc != NULL)
+    {
+      struct remote_state *rs = get_remote_state ();
+
+      if (remote_protocol_packets[PACKET_vCont].support == PACKET_SUPPORT_UNKNOWN)
+        remote_vcont_probe (rs);
+
+      if (remote_protocol_packets[PACKET_vCont].support == PACKET_ENABLE
+          && rs->supports_vCont.f)
+        return;
+    }
+
+      warning (_("Finish stepping is not supported by the current target"));
+    }
+}
+
void
_initialize_remote (void)
{
@@ -12168,6 +12274,34 @@
                  &setlist,
                  &showlist);

+  add_setshow_boolean_cmd ("next-stepping", class_run,
+                 &use_next_stepping, _("\
+  Enable or disable next stepping."), _("\
+  Show whether target-assisted next stepping is enabled."), _("\
+  If on, and the target supports it, when skipping over a source line, GDB\n\
+  tells the target to skip the next instruction itself instead of\n\
+  of issuing multiple single-steps.  This speeds up source level\n\
+  stepping.  If off, GDB always issues slower stepping mechanisms\n\
+  instead, even if next stepping is supported by the target.  The default is on."),
+                 set_next_stepping,
+                 show_next_stepping,
+                 &setlist,
+                 &showlist);
+
+  add_setshow_boolean_cmd ("finish-stepping", class_run,
+                 &use_finish_stepping, _("\
+  Enable or disable finish stepping."), _("\
+  Show whether target-assisted finish stepping is enabled."), _("\
+  If on, and the target supports it, when stepping out of a function, GDB\n\
+  tells the target to step out of the corresponding stack frame itself.\n\
+  This speeds up source level stepping. If off, GDB issues slower\n\
+  stepping mechanisms instead, even if finish\n\
+  stepping is supported by the target.  The default is on."),
+                 set_finish_stepping,
+                 show_finish_stepping,
+                 &setlist,
+                 &showlist);
+
   /* Eventually initialize fileio.  See fileio.c */
  initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);





More information about the Gdb-patches mailing list