From de979965d3f5de7e4bf2354871fe85b3f77c720e Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 30 Nov 2015 16:05:17 +0000 Subject: [PATCH] New vCtrlC packet, non-stop mode equivalent of \003 There's currently no non-stop equivalent of the all-stop ^C (\003) "packet" that GDB sends when a ctrl-c is pressed while a foreground command is active. There's vCont;t, but that's defined to cause a "signal 0" stop. This fixes many tests that type ^C, when testing with extended-remote with "maint set target-non-stop on". E.g.: Continuing. talk to me baby PASS: gdb.base/interrupt.exp: process is alive a a PASS: gdb.base/interrupt.exp: child process ate our char ^C [Thread 22730.22730] #1 stopped. 0x0000003615ee6650 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81 81 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) (gdb) FAIL: gdb.base/interrupt.exp: send_gdb control C p func1 () gdb/ 2015-11-30 Pedro Alves * NEWS (New remote packets): Mention vCtrlC. * remote.c (PACKET_vCtrlC): New enum value. (async_remote_interrupt): Call target_interrupt instead of target_stop. (remote_interrupt_as): Remove 'ptid' parameter. (remote_interrupt_ns): New function. (remote_stop): Adjust. (remote_interrupt): If the target is in non-stop mode, try interrupting with vCtrlC. (initialize_remote): Install set remote ctrl-c packet. gdb/doc/ 2015-11-30 Pedro Alves * gdb.texinfo (Bootstrapping): Add "interrupting remote targets" anchor. (Packets): Document vCtrlC. gdb/gdbserver/ 2015-11-30 Pedro Alves * server.c (handle_v_requests): Handle vCtrlC. --- gdb/ChangeLog | 13 ++++++++++ gdb/NEWS | 4 +++ gdb/doc/ChangeLog | 6 +++++ gdb/doc/gdb.texinfo | 34 +++++++++++++++++++++++--- gdb/gdbserver/ChangeLog | 4 +++ gdb/gdbserver/server.c | 7 ++++++ gdb/remote.c | 65 +++++++++++++++++++++++++++++++++++++++++++------ 7 files changed, 122 insertions(+), 11 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a0eff91..0d4ea33 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,18 @@ 2015-11-30 Pedro Alves + * NEWS (New remote packets): Mention vCtrlC. + * remote.c (PACKET_vCtrlC): New enum value. + (async_remote_interrupt): Call target_interrupt instead of + target_stop. + (remote_interrupt_as): Remove 'ptid' parameter. + (remote_interrupt_ns): New function. + (remote_stop): Adjust. + (remote_interrupt): If the target is in non-stop mode, try + interrupting with vCtrlC. + (initialize_remote): Install set remote ctrl-c packet. + +2015-11-30 Pedro Alves + * remote.c (struct remote_state) : Delete fields. (struct private_thread_info) : diff --git a/gdb/NEWS b/gdb/NEWS index 5f704fe..a7c12e7 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -84,6 +84,10 @@ exec-events feature in qSupported response can contain the corresponding 'stubfeature'. Set and show commands can be used to display whether these features are enabled. +vCtrlC + Equivalent to interrupting with the ^C character, but works in + non-stop mode. + * Extended-remote exec events ** GDB now has support for exec events on extended-remote Linux targets. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 7e747dc..3e0d626 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2015-11-30 Pedro Alves + + * gdb.texinfo (Bootstrapping): Add "interrupting remote targets" + anchor. + (Packets): Document vCtrlC. + 2015-11-26 Simon Marchi * gdb.texinfo (Thread List Format): Mention thread names. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c4d8a18..972ace0 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -35090,6 +35090,24 @@ command in the @samp{vCont} packet. The @samp{vCont} packet is not supported. @end table +@anchor{vCtrlC packet} +@item vCtrlC +@cindex @samp{vCtrlC} packet +Interrupt remote target as if a control-C was pressed on the remote +terminal. This is the equivalent to reacting to the @code{^C} +(@samp{\003}, the control-C character) character in all-stop mode +while the target is running, except this works in non-stop mode. +@xref{interrupting remote targets}, for more info on the all-stop +variant. + +Reply: +@table @samp +@item E @var{nn} +for an error +@item OK +for success +@end table + @item vFile:@var{operation}:@var{parameter}@dots{} @cindex @samp{vFile} packet Perform a file operation on the target system. For details, @@ -37857,11 +37875,12 @@ operation. @node Interrupts @section Interrupts @cindex interrupts (remote protocol) +@anchor{interrupting remote targets} -When a program on the remote target is running, @value{GDBN} may -attempt to interrupt it by sending a @samp{Ctrl-C}, @code{BREAK} or -a @code{BREAK} followed by @code{g}, -control of which is specified via @value{GDBN}'s @samp{interrupt-sequence}. +In all-stop mode, when a program on the remote target is running, +@value{GDBN} may attempt to interrupt it by sending a @samp{Ctrl-C}, +@code{BREAK} or a @code{BREAK} followed by @code{g}, control of which +is specified via @value{GDBN}'s @samp{interrupt-sequence}. The precise meaning of @code{BREAK} is defined by the transport mechanism and may, in fact, be undefined. @value{GDBN} does not @@ -37882,6 +37901,13 @@ and does @emph{not} represent an interrupt. E.g., an @samp{X} packet When Linux kernel receives this sequence from serial port, it stops execution and connects to gdb. +In non-stop mode, because packet resumptions are asynchronous +(@pxref{vCont packet}), @value{GDBN} is always free to send a remote +command to the remote stub, even when the target is running. For that +reason, @value{GDBN} instead sends a regular packet (@pxref{vCtrlC +packet}) with the usual packet framing instead of the single byte +@code{0x03}. + Stubs are not required to recognize these interrupt mechanisms and the precise meaning associated with receipt of the interrupt is implementation defined. If the target supports debugging of multiple diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 28ff0e1..22d729f 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,5 +1,9 @@ 2015-11-30 Pedro Alves + * server.c (handle_v_requests): Handle vCtrlC. + +2015-11-30 Pedro Alves + * gdbthread.h (find_any_thread_of_pid): Declare. * inferiors.c (thread_of_pid, find_any_thread_of_pid): New functions. diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 9d65f65..f6245d7 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -2861,6 +2861,13 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len) { if (!disable_packet_vCont) { + if (strcmp (own_buf, "vCtrlC") == 0) + { + (*the_target->request_interrupt) (); + write_ok (own_buf); + return; + } + if (startswith (own_buf, "vCont;")) { require_running (own_buf); diff --git a/gdb/remote.c b/gdb/remote.c index 5270bd2..7256c23 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1480,6 +1480,9 @@ enum { /* Support for query supported vCont actions. */ PACKET_vContSupported, + /* Support remote CTRL-C. */ + PACKET_vCtrlC, + PACKET_MAX }; @@ -5581,7 +5584,7 @@ async_remote_interrupt (gdb_client_data arg) if (remote_debug) fprintf_unfiltered (gdb_stdlog, "async_remote_interrupt called\n"); - target_stop (inferior_ptid); + target_interrupt (inferior_ptid); } /* Perform interrupt, if the first attempt did not succeed. Just give @@ -5688,7 +5691,7 @@ remote_stop_ns (ptid_t ptid) process reports the interrupt. */ static void -remote_interrupt_as (ptid_t ptid) +remote_interrupt_as (void) { struct remote_state *rs = get_remote_state (); @@ -5704,6 +5707,38 @@ remote_interrupt_as (ptid_t ptid) send_interrupt_sequence (); } +/* Non-stop version of target_interrupt. Uses `vCtrlC' to interrupt + the remote target. It is undefined which thread of which process + reports the interrupt. Returns true if the packet is supported by + the server, false otherwise. */ + +static int +remote_interrupt_ns (void) +{ + struct remote_state *rs = get_remote_state (); + char *p = rs->buf; + char *endp = rs->buf + get_remote_packet_size (); + + xsnprintf (p, endp - p, "vCtrlC"); + + /* In non-stop, we get an immediate OK reply. The stop reply will + come in asynchronously by notification. */ + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); + + switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_vCtrlC])) + { + case PACKET_OK: + break; + case PACKET_UNKNOWN: + return 0; + case PACKET_ERROR: + error (_("Interrupting target failed: %s"), rs->buf); + } + + return 1; +} + /* Implement the to_stop function for the remote targets. */ static void @@ -5718,7 +5753,7 @@ remote_stop (struct target_ops *self, ptid_t ptid) { /* We don't currently have a way to transparently pause the remote target in all-stop mode. Interrupt it instead. */ - remote_interrupt_as (ptid); + remote_interrupt_as (); } } @@ -5730,14 +5765,27 @@ remote_interrupt (struct target_ops *self, ptid_t ptid) if (remote_debug) fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n"); - if (target_is_non_stop_p ()) + if (non_stop) { - /* We don't currently have a way to ^C the remote target in - non-stop mode. Stop it (with no signal) instead. */ + /* In non-stop mode, we always stop with no signal instead. */ remote_stop_ns (ptid); } else - remote_interrupt_as (ptid); + { + /* In all-stop, we emulate ^C-ing the remote target's + terminal. */ + if (target_is_non_stop_p ()) + { + if (!remote_interrupt_ns ()) + { + /* No support for ^C-ing the remote target. Stop it + (with no signal) instead. */ + remote_stop_ns (ptid); + } + } + else + remote_interrupt_as (); + } } /* Ask the user what to do when an interrupt is received. */ @@ -13643,6 +13691,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_exec_event_feature], "exec-event-feature", "exec-event-feature", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_vCtrlC], + "vCtrlC", "ctrl-c", 0); + /* Assert that we've registered "set remote foo-packet" commands for all packet configs. */ { -- 2.7.4