Index: gdb/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.10906
diff -u -r1.10906 ChangeLog
--- gdb/ChangeLog	25 Sep 2009 21:39:52 -0000	1.10906
+++ gdb/ChangeLog	26 Sep 2009 03:38:17 -0000
@@ -1,3 +1,24 @@
+2009-09-25  Kazuyoshi Caz Yokoyama  <caz@caztech.com>
+
+	* remote.c: Add a new remote variable, interrupt_sequence and
+	interrupt-on-start. interrupt_sequence provides arbitrary number of
+	characters include Ctrl-C to the remote target to stop the execution
+	of the program on the target. Not only characters but it also send
+	BREAK signal to the target. For example,
+	^C: ASCII ETX character (Ctrl-c, 0x03)
+	BREAK: BREAK signal
+	BREAK-g: BREAK signal and 'g' which is Magic SysRq which interrupt
+	         the execution of Linux kernel 
+	abcdef: ASCII character, abcdef
+	abc-xyz: ASCII character, abcxyz
+	remotebreak is deprecated even though it is still available. It switches
+	^C and BREAK.
+	interrupt-on-start is a boolean variable and controls whether
+	interrupt_sequence is sent when gdb starts. When you debug Linux kernel,
+	you probably do
+	set remote interrupt-sequence BREAK-g
+	set remote interrupt-on-start on
+	
 2009-09-25  Tom Tromey  <tromey@redhat.com>
 
 	PR python/10664:
Index: gdb/remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.372
diff -u -r1.372 remote.c
--- gdb/remote.c	10 Sep 2009 22:47:56 -0000	1.372
+++ gdb/remote.c	26 Sep 2009 03:38:20 -0000
@@ -546,13 +546,66 @@
    this can go away.  */
 static int wait_forever_enabled_p = 1;
 
+/* Interrupt sequence to the remote target to interrupt the program
+   or OS.  */
+
+#define CTRL_C "^C"  /* default of interrupt_sequence */
+#define BREAK "BREAK"
+static char *interrupt_sequence = NULL;
+
+/* This boolean variable specifies whether interrupt_sequence is sent
+   to remote target when gdb starts. This is mostly needed when you debug
+   Linux kernel. Linux kernel expects BREAK g which is Magic SysRq for
+   connecting gdb.
+  */
+static int interrupt_on_start = 0;
 
 /* 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.  */
 
-static int remote_break;
+static int remote_break = 0;
+
+static void
+set_remote_break (char *args, int from_tty, struct cmd_list_element *c)
+{
+  if (strcmp(interrupt_sequence, CTRL_C) == 0)
+    {
+      interrupt_sequence = xmalloc(sizeof(BREAK) + 1);
+      strcpy(interrupt_sequence, BREAK);
+      remote_break = 1;
+    }
+  else if (strcmp(interrupt_sequence, BREAK) == 0)
+    {
+      interrupt_sequence = xmalloc(sizeof(CTRL_C) + 1);
+      strcpy(interrupt_sequence, CTRL_C);
+      remote_break = 0;
+    }
+#if 0
+  fprintf_filtered (file, _("\
+Deprecated. Use interrupt_sequence instead."));
+#endif
+}
+
+static void
+show_remote_break (struct ui_file *file, int from_tty,
+		   struct cmd_list_element *c,
+		   const char *value)
+{
+  if (strcmp(interrupt_sequence, CTRL_C) == 0)
+    fprintf_filtered (file, _("\
+Whether to send break if interrupted is off.\n\
+Deprecated. Use set remote interrupt_sequence instead.\n"));
+  else if (strcmp(interrupt_sequence, "BREAK") == 0)
+    fprintf_filtered (file, _("\
+Whether to send break if interrupted is on.\n\
+Deprecated. Use set remote interrupt_sequence instead.\n"));
+  else
+    fprintf_filtered (file, _("\
+Sending %s as interrupt_sequence.\n\
+Deprecated. Use interrupt_sequence instead.\n"), interrupt_sequence);
+}
 
 /* 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
@@ -2585,6 +2638,38 @@
   int extended_p;
 };
 
+/*
+  Send interrupt_sequence to remote target.
+*/
+static void
+send_interrupt_sequence ()
+{
+  char *b, *p, ch;
+
+  b = xmalloc (strlen(interrupt_sequence) + 1);
+  if (b == NULL)
+    internal_error (__FILE__, __LINE__,
+		    _("can't allocate b in send_interrupt_sequence()"));
+  strcpy (b, interrupt_sequence);
+  for (p = strtok (b, "-");
+       p; p = strtok(NULL, "-"))
+    {
+      if (strcmp(p, CTRL_C) == 0)
+	serial_write (remote_desc, "\x03", 1);
+      else if (strcmp(p, "BREAK") == 0)
+	serial_send_break (remote_desc);
+      else if (*p == '\\')
+	{
+	  sscanf (p, "%c", &ch);
+	  serial_write (remote_desc, &ch, 1);
+	}
+      else
+	serial_write (remote_desc, p, strlen(p));
+    }
+
+  xfree (b);
+}
+
 static void
 remote_start_remote (struct ui_out *uiout, void *opaque)
 {
@@ -2598,6 +2683,12 @@
   /* Ack any packet which the remote side has already sent.  */
   serial_write (remote_desc, "+", 1);
 
+  /* Interrupt_sequence is sent to remote target when gdb starts.
+     This is mostly needed when you debug Linux kernel.
+     Linux kernel expects BREAK g which is Magic SysRq for connecting gdb.  */
+  if (interrupt_on_start)
+    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.  */
@@ -4021,12 +4112,8 @@
   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
@@ -9056,13 +9143,33 @@
 terminating `#' character and checksum."),
 	   &maintenancelist);
 
-  add_setshow_boolean_cmd ("remotebreak", no_class, &remote_break, _("\
+  add_setshow_boolean_cmd ("remotebreak", class_obscure, &remote_break, _("\
 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_remote_break, show_remote_break,
 			   &setlist, &showlist);
 
+  /* When set command is called for the item which is defined by
+     add_setshow_string_cmd, a string is freed when the string is not NULL
+     even it is set by initialization.  */
+  interrupt_sequence = xmalloc(sizeof(CTRL_C) + 1);
+  strcpy(interrupt_sequence, CTRL_C);
+  add_setshow_string_noescape_cmd ("interrupt-sequence", class_support,
+				   &interrupt_sequence, _("\
+Set interrupt sequence to remote target."), _("\
+Show interrupt sequence to remote target."), _("\
+\\xNN, ^C and BREAK are interpreted as appropriately."),
+				   NULL, NULL,
+				   &remote_set_cmdlist, &remote_show_cmdlist);
+
+  add_setshow_boolean_cmd ("interrupt-on-start", no_class, &interrupt_on_start, _("\
+Set whether to send interrupt sequence when gdb starts."), _("		\
+Show whether to send interrupt sequence when gdb starts."), _("		\
+If set, interrupt sequence is sent to the remote target."),
+			   NULL, NULL,
+			   &remote_set_cmdlist, &remote_show_cmdlist);
+
   /* Install commands for configuring memory read/write packets.  */
 
   add_cmd ("remotewritesize", no_class, set_memory_write_packet_size, _("\
