From 9a7071a8ce92ca34996d97b77e72ac8cc3946cd6 Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Wed, 28 Oct 2009 15:01:27 +0000 Subject: [PATCH] gdb/: * remote.c (interrupt_sequence_control_c) (interrupt_sequence_break, interrupt_sequence_break_g) (interrupt_sequence_modes): New constants. (interrupt_sequence_mode, interrupt_on_connect): New variable. (show_interrupt_sequence): New function. (set_remotebreak, show_remotebreak): New function. (send_interrupt_sequence): New function. (remote_start_remote): Call send_interrupt_sequence if interrupt_on_connect is true. (remote_stop_as): Call send_interrupt_sequence. (_initialize_remote): Add interrupt-sequence and interrupt-on-connect, modify remotebreak to call set_remotebreak and show_remotebreak. * NEWS: Add entry for "set/show remote interrupt-sequence" and "set/show remote interrupt-on-connect". Also mention that "set/show remotebreak" is now deprecated. gdb/doc/: * gdb.texinfo (Remote Configuration): Add "set/show remote interrupt-sequence" and "set/show remote interrupt-on-connect" command. --- gdb/NEWS | 18 ++++++++ gdb/doc/gdb.texinfo | 38 ++++++++++++++-- gdb/remote.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 169 insertions(+), 14 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index b95edba..d20d8e6 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -37,6 +37,24 @@ remove-inferior ID maint info program-spaces List the program spaces loaded into GDB. +set remote interrupt-sequence [Ctrl-C | BREAK | BREAK-g] +show remote interrupt-sequence + Allow the user to select one of ^C, a BREAK signal or BREAK-g + as the sequence to the remote target in order to interrupt the execution. + Ctrl-C is a default. Some system prefers BREAK which is high level of + serial line for some certain time. Linux kernel prefers BREAK-g, a.k.a + Magic SysRq g. It is BREAK signal and character 'g'. + +set remote interrupt-on-connect [on | off] +show remote interrupt-on-connect + When interrupt-on-connect is ON, gdb sends interrupt-sequence to + remote target when gdb connects to it. This is needed when you debug + Linux kernel. + +set remotebreak [on | off] +show remotebreak +Deprecated. Use "set/show remote interrupt-sequence" instead. + * New options set follow-exec-mode new|same diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6a74aeb..aa28bc3 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -15234,6 +15234,34 @@ extended-remote}. This should be set to a filename valid on the target system. If it is not set, the target will use a default filename (e.g.@: the last program run). +@item set remote interrupt-sequence +@cindex interrupt remote programs +@cindex select Ctrl-C, BREAK or BREAK-g +Allow the user to select one of @samp{Ctrl-C}, a @code{BREAK} or +@samp{BREAK-g} as the +sequence to the remote target in order to interrupt the execution. +@samp{Ctrl-C} is a default. Some system prefers @code{BREAK} which +is high level of serial line for some certain time. +Linux kernel prefers @samp{BREAK-g}, a.k.a Magic SysRq g. +It is @code{BREAK} signal followed by character @code{g}. + +@item show interrupt-sequence +Show which of @samp{Ctrl-C}, @code{BREAK} or @code{BREAK-g} +is sent by @value{GDBN} to interrupt the remote program. +@code{BREAK-g} is BREAK signal followed by @code{g} and +also known as Magic SysRq g. + +@item set remote interrupt-on-connect +@cindex send interrupt-sequence on start +Specify whether interrupt-sequence is sent to remote target when +@value{GDBN} connects to it. This is mostly needed when you debug +Linux kernel. Linux kernel expects @code{BREAK} followed by @code{g} +which is known as Magic SysRq g in order to connect @value{GDBN}. + +@item show interrupt-on-connect +Show whether interrupt-sequence is sent +to remote target when @value{GDBN} connects to it. + @kindex set tcp @kindex show tcp @item set tcp auto-retry on @@ -30084,9 +30112,9 @@ or -1 if an error occurs. @var{pathname} is a string. @cindex interrupts (remote protocol) When a program on the remote target is running, @value{GDBN} may -attempt to interrupt it by sending a @samp{Ctrl-C} or a @code{BREAK}, -control of which is specified via @value{GDBN}'s @samp{remotebreak} -setting (@pxref{set remotebreak}). +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 @@ -30103,6 +30131,10 @@ and does @emph{not} represent an interrupt. E.g., an @samp{X} packet (@pxref{X packet}), used for binary downloads, may include an unescaped @code{0x03} as part of its packet. +@code{BREAK} followed by @code{g} is also known as Magic SysRq g. +When Linux kernel receives this sequence from serial port, +it stops execution and connects to gdb. + 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/remote.c b/gdb/remote.c index 43955e9..664a9c7 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -546,14 +546,76 @@ static int remote_async_mask_value = 1; this can go away. */ static int wait_forever_enabled_p = 1; +/* Allow the user to specify what sequence to send to the remote + when he requests a program interruption: Although ^C is usually + what remote systems expect (this is the default, here), it is + sometimes preferable to send a break. On other systems such + as the Linux kernel, a break followed by g, which is Magic SysRq g + is required in order to interrupt the execution. */ +const char interrupt_sequence_control_c[] = "Ctrl-C"; +const char interrupt_sequence_break[] = "BREAK"; +const char interrupt_sequence_break_g[] = "BREAK-g"; +static const char *interrupt_sequence_modes[] = + { + interrupt_sequence_control_c, + interrupt_sequence_break, + interrupt_sequence_break_g, + NULL + }; +static const char *interrupt_sequence_mode = interrupt_sequence_control_c; + +static void +show_interrupt_sequence (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + if (interrupt_sequence_mode == interrupt_sequence_control_c) + fprintf_filtered (file, + _("Send the ASCII ETX character (Ctrl-c) " + "to the remote target to interrupt the " + "execution of the program.\n")); + else if (interrupt_sequence_mode == interrupt_sequence_break) + fprintf_filtered (file, + _("send a break signal to the remote target " + "to interrupt the execution of the program.\n")); + else if (interrupt_sequence_mode == interrupt_sequence_break_g) + fprintf_filtered (file, + _("Send a break signal and 'g' a.k.a. Magic SysRq g to " + "the remote target to interrupt the execution " + "of Linux kernel.\n")); + else + internal_error (__FILE__, __LINE__, + _("Invalid value for interrupt_sequence_mode: %s."), + interrupt_sequence_mode); +} -/* This variable chooses whether to send a ^C or a break when the user - requests program interruption. Although ^C is usually what remote - systems expect, and that is the default here, sometimes a break is - preferable instead. */ +/* This boolean variable specifies whether interrupt_sequence is sent + to the remote target when gdb connects to it. + This is mostly needed when you debug the Linux kernel: The Linux kernel + expects BREAK g which is Magic SysRq g for connecting gdb. */ +static int interrupt_on_connect = 0; +/* This variable is used to implement the "set/show remotebreak" commands. + Since these commands are now deprecated in favor of "set/show remote + interrupt-sequence", it no longer has any effect on the code. */ static int remote_break; +static void +set_remotebreak (char *args, int from_tty, struct cmd_list_element *c) +{ + if (remote_break) + interrupt_sequence_mode = interrupt_sequence_break; + else + interrupt_sequence_mode = interrupt_sequence_control_c; +} + +static void +show_remotebreak (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ +} + /* Descriptor for I/O to remote machine. Initialize it to NULL so that remote_open knows that we don't have a file open when the program starts. */ @@ -2604,6 +2666,25 @@ struct start_remote_args int extended_p; }; +/* Send interrupt_sequence to remote target. */ +static void +send_interrupt_sequence () +{ + if (interrupt_sequence_mode == interrupt_sequence_control_c) + serial_write (remote_desc, "\x03", 1); + else if (interrupt_sequence_mode == interrupt_sequence_break) + serial_send_break (remote_desc); + else if (interrupt_sequence_mode == interrupt_sequence_break_g) + { + serial_send_break (remote_desc); + serial_write (remote_desc, "g", 1); + } + else + internal_error (__FILE__, __LINE__, + _("Invalid value for interrupt_sequence_mode: %s."), + interrupt_sequence_mode); +} + static void remote_start_remote (struct ui_out *uiout, void *opaque) { @@ -2617,6 +2698,9 @@ remote_start_remote (struct ui_out *uiout, void *opaque) /* Ack any packet which the remote side has already sent. */ serial_write (remote_desc, "+", 1); + if (interrupt_on_connect) + send_interrupt_sequence (); + /* The first packet we send to the target is the optional "supported packets" request. If the target can answer this, it will tell us which later probes to skip. */ @@ -4044,12 +4128,8 @@ remote_stop_as (ptid_t ptid) if (rs->cached_wait_status) return; - /* Send a break or a ^C, depending on user preference. */ - - if (remote_break) - serial_send_break (remote_desc); - else - serial_write (remote_desc, "\003", 1); + /* Send interrupt_sequence to remote target. */ + send_interrupt_sequence (); } /* This is the generic stop called via the target vector. When a target @@ -9019,6 +9099,8 @@ void _initialize_remote (void) { struct remote_state *rs; + struct cmd_list_element *cmd; + char *cmd_name; /* architecture specific data */ remote_gdbarch_data_handle = @@ -9086,8 +9168,31 @@ terminating `#' character and checksum."), Set whether to send break if interrupted."), _("\ Show whether to send break if interrupted."), _("\ If set, a break, instead of a cntrl-c, is sent to the remote target."), - NULL, NULL, /* FIXME: i18n: Whether to send break if interrupted is %s. */ + set_remotebreak, show_remotebreak, &setlist, &showlist); + cmd_name = "remotebreak"; + cmd = lookup_cmd (&cmd_name, setlist, "", -1, 1); + deprecate_cmd (cmd, "set remote interrupt-sequence"); + cmd_name = "remotebreak"; /* needed because lookup_cmd updates the pointer */ + cmd = lookup_cmd (&cmd_name, showlist, "", -1, 1); + deprecate_cmd (cmd, "show remote interrupt-sequence"); + + add_setshow_enum_cmd ("interrupt-sequence", class_support, + interrupt_sequence_modes, &interrupt_sequence_mode, _("\ +Set interrupt sequence to remote target."), _("\ +Show interrupt sequence to remote target."), _("\ +Valid value is \"Ctrl-C\", \"BREAK\" or \"BREAK-g\". The default is \"Ctrl-C\"."), + NULL, show_interrupt_sequence, + &remote_set_cmdlist, + &remote_show_cmdlist); + + add_setshow_boolean_cmd ("interrupt-on-connect", class_support, + &interrupt_on_connect, _("\ +Set whether interrupt-sequence is sent to remote target when gdb connects to."), _(" \ +Show whether interrupt-sequence is sent to remote target when gdb connects to."), _(" \ +If set, interrupt sequence is sent to remote target."), + NULL, NULL, + &remote_set_cmdlist, &remote_show_cmdlist); /* Install commands for configuring memory read/write packets. */ -- 2.7.4