diff options
author | Pedro Alves <palves@redhat.com> | 2013-05-23 17:15:35 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2013-05-23 17:15:35 +0000 |
commit | c1e36e3e919994da4fa0da232b173939f3e44bb8 (patch) | |
tree | 0e355e32e09ba6192768b6ebdd20994848acbdfe /gdb/remote.c | |
parent | d458bd84a8d3576fa7c2b4e3132ebe96e104e918 (diff) | |
download | gdb-c1e36e3e919994da4fa0da232b173939f3e44bb8.zip gdb-c1e36e3e919994da4fa0da232b173939f3e44bb8.tar.gz gdb-c1e36e3e919994da4fa0da232b173939f3e44bb8.tar.bz2 |
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.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/gdb/remote.c b/gdb/remote.c index eb58b94..658fae2 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); |