summaryrefslogtreecommitdiff
path: root/gdb/remote.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2013-05-23 17:15:34 +0000
committerPedro Alves <palves@redhat.com>2013-05-23 17:15:34 +0000
commitee9c380976c428455ba465c586e1c945fb1c0e97 (patch)
tree8e9810e84ce7052355f96cb1d2db5c0a3a222cd7 /gdb/remote.c
parent7ac839d2ea970056e05eb9aabfa2925c6c9d6a13 (diff)
downloadgdb-ee9c380976c428455ba465c586e1c945fb1c0e97.tar.gz
range stepping: gdb
This patch teaches GDB to take advantage of target-assisted range stepping. It adds a new 'r ADDR1,ADDR2' action to vCont (vCont;r), meaning, "step once, and keep stepping as long as the thread is in the [ADDR1,ADDR2) range". Rationale: When user issues the "step" command on the following line of source, a = b + c + d * e - a; GDB single-steps every single instruction until the program reaches a new different line. E.g., on x86_64, that line compiles to: 0x08048434 <+65>: mov 0x1c(%esp),%eax 0x08048438 <+69>: mov 0x30(%esp),%edx 0x0804843c <+73>: add %eax,%edx 0x0804843e <+75>: mov 0x18(%esp),%eax 0x08048442 <+79>: imul 0x2c(%esp),%eax 0x08048447 <+84>: add %edx,%eax 0x08048449 <+86>: sub 0x34(%esp),%eax 0x0804844d <+90>: mov %eax,0x34(%esp) 0x08048451 <+94>: mov 0x1c(%esp),%eax and the following is the RSP traffic between GDB and GDBserver: --> vCont;s:p2e13.2e13;c <-- T0505:68efffbf;04:30efffbf;08:3c840408;thread:p2e13.2e13;core:1; --> vCont;s:p2e13.2e13;c <-- T0505:68efffbf;04:30efffbf;08:3e840408;thread:p2e13.2e13;core:2; --> vCont;s:p2e13.2e13;c <-- T0505:68efffbf;04:30efffbf;08:42840408;thread:p2e13.2e13;core:2; --> vCont;s:p2e13.2e13;c <-- T0505:68efffbf;04:30efffbf;08:47840408;thread:p2e13.2e13;core:0; --> vCont;s:p2e13.2e13;c <-- T0505:68efffbf;04:30efffbf;08:49840408;thread:p2e13.2e13;core:0; --> vCont;s:p2e13.2e13;c <-- T0505:68efffbf;04:30efffbf;08:4d840408;thread:p2e13.2e13;core:0; --> vCont;s:p2e13.2e13;c <-- T0505:68efffbf;04:30efffbf;08:51840408;thread:p2e13.2e13;core:0; IOW, a lot of roundtrips between GDB and GDBserver. If we add a new command to the RSP, meaning "keep stepping and don't report a stop until the program goes out of the [0x08048434, 0x08048451) address range", then the RSP traffic can be reduced down to: --> vCont;r8048434,8048451:p2db0.2db0;c <-- T0505:68efffbf;04:30efffbf;08:51840408;thread:p2db0.2db0;core:1; As number of packets is reduced dramatically, the performance of stepping source lines is much improved. In case something is wrong with range stepping on the stub side, the debug info or even gdb, this adds a "set/show range-stepping" command to be able to turn range stepping off. gdb/ 2013-05-23 Yao Qi <yao@codesourcery.com> Pedro Alves <palves@redhat.com> * gdbthread.h (struct thread_control_state) <may_range_step>: New field. * infcmd.c (step_once, until_next_command): Enable range stepping. * infrun.c (displaced_step_prepare): Disable range stepping. (resume): Disable range stepping if stepping over a breakpoint or we have software watchpoints. If range stepping is enabled, assert the thread is in the stepping range. (clear_proceed_status_thread): Clear may_range_step. (handle_inferior_event): Disable range stepping as soon as we know the thread that hit the event. Re-enable it whenever we're going to step with a step range. * remote.c (struct vCont_action_support) <r>: New field. (use_range_stepping): New global. (remote_vcont_probe): Handle 'r' action. (append_resumption): Append an 'r' action if the thread may range step. (show_range_stepping): New function. (set_range_stepping): New function. (_initialize_remote): Call add_setshow_boolean_cmd to register the 'set range-stepping' and 'show range-stepping' commands. * NEWS: Mention range stepping, the new vCont;r action, and the new "set/show range-stepping" commands. gdb/doc/ 2013-05-23 Yao Qi <yao@codesourcery.com> Pedro Alves <palves@redhat.com> * gdb.texinfo (Packets): Document 'vCont;r'. (Continuing and Stepping): Document target-assisted range stepping, and the 'set range-stepping' and 'show range-stepping' commands.
Diffstat (limited to 'gdb/remote.c')
-rw-r--r--gdb/remote.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/gdb/remote.c b/gdb/remote.c
index eb58b9454e2..658fae22074 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -260,8 +260,15 @@ struct vCont_action_support
{
/* vCont;t */
int t;
+
+ /* vCont;r */
+ int r;
};
+/* Controls whether GDB is willing to use range stepping. */
+
+static int use_range_stepping = 1;
+
/* Description of the remote protocol state for the currently
connected target. This is per-target state, and independent of the
selected architecture. */
@@ -4653,6 +4660,7 @@ remote_vcont_probe (struct remote_state *rs)
support_c = 0;
support_C = 0;
rs->supports_vCont.t = 0;
+ rs->supports_vCont.r = 0;
while (p && *p == ';')
{
p++;
@@ -4666,6 +4674,8 @@ remote_vcont_probe (struct remote_state *rs)
support_C = 1;
else if (*p == 't' && (*(p + 1) == ';' || *(p + 1) == 0))
rs->supports_vCont.t = 1;
+ else if (*p == 'r' && (*(p + 1) == ';' || *(p + 1) == 0))
+ rs->supports_vCont.r = 1;
p = strchr (p, ';');
}
@@ -4697,6 +4707,42 @@ append_resumption (char *p, char *endp,
if (step && siggnal != GDB_SIGNAL_0)
p += xsnprintf (p, endp - p, ";S%02x", siggnal);
+ else if (step
+ /* GDB is willing to range step. */
+ && use_range_stepping
+ /* Target supports range stepping. */
+ && rs->supports_vCont.r
+ /* We don't currently support range stepping multiple
+ threads with a wildcard (though the protocol allows it,
+ so stubs shouldn't make an active effort to forbid
+ 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;
+
+ p += xsnprintf (p, endp - p, ";r%s,%s",
+ phex_nz (tp->control.step_range_start,
+ addr_size),
+ phex_nz (tp->control.step_range_end,
+ addr_size));
+ }
+ else
+ p += xsnprintf (p, endp - p, ";s");
+ }
else if (step)
p += xsnprintf (p, endp - p, ";s");
else if (siggnal != GDB_SIGNAL_0)
@@ -11659,6 +11705,44 @@ remote_upload_trace_state_variables (struct uploaded_tsv **utsvp)
return 0;
}
+/* The "set/show range-stepping" show hook. */
+
+static void
+show_range_stepping (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file,
+ _("Debugger's willingness to use range stepping "
+ "is %s.\n"), value);
+}
+
+/* The "set/show range-stepping" set hook. */
+
+static void
+set_range_stepping (char *ignore_args, int from_tty,
+ struct cmd_list_element *c)
+{
+ /* Whene enabling, check whether range stepping is actually
+ supported by the target, and warn if not. */
+ if (use_range_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.r)
+ return;
+ }
+
+ warning (_("Range stepping is not supported by the current target"));
+ }
+}
+
void
_initialize_remote (void)
{
@@ -12056,6 +12140,20 @@ Set the remote pathname for \"run\""), _("\
Show the remote pathname for \"run\""), NULL, NULL, NULL,
&remote_set_cmdlist, &remote_show_cmdlist);
+ add_setshow_boolean_cmd ("range-stepping", class_run,
+ &use_range_stepping, _("\
+Enable or disable range stepping."), _("\
+Show whether target-assisted range stepping is enabled."), _("\
+If on, and the target supports it, when stepping a source line, GDB\n\
+tells the target to step the corresponding range of addresses itself instead\n\
+of issuing multiple single-steps. This speeds up source level\n\
+stepping. If off, GDB always issues single-steps, even if range\n\
+stepping is supported by the target. The default is on."),
+ set_range_stepping,
+ show_range_stepping,
+ &setlist,
+ &showlist);
+
/* Eventually initialize fileio. See fileio.c */
initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);