gdb/
authorDaniel Jacobowitz <drow@false.org>
Thu, 16 Nov 2006 15:08:25 +0000 (15:08 +0000)
committerDaniel Jacobowitz <drow@false.org>
Thu, 16 Nov 2006 15:08:25 +0000 (15:08 +0000)
* remote.c (PACKET_QPassSignals): New.
(last_pass_packet, remote_pass_signals): New.
(remote_protocol_features): Add QPassSignals.
(remote_query_supported): Correct an infinite loop.
(remote_open_1): Reset last_pass_packet.
(remote_resume): Call remote_pass_signals.
(_initialize_remote): Register "set remote pass-signals".
gdb/doc/
* gdb.texinfo (Remote configuration): Mention
"pass-signals-packet".
(General Query Packets): Document QPassSignals.  Fix
a typo.
gdb/gdbserver/
* linux-low.c (linux_wait_for_event): Reformat.  Use the
pass_signals array.
* remote-utils.c (decode_address_to_semicolon): New.
* server.c (pass_signals, handle_general_set): New.
(handle_query): Mention QPassSignals for qSupported.
(main): Call handle_general_set.
* server.h (pass_signals, decode_address_to_semicolon): New.

gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c
gdb/gdbserver/remote-utils.c
gdb/gdbserver/server.c
gdb/gdbserver/server.h
gdb/remote.c

index 6ff5bad..cda1e49 100644 (file)
@@ -1,3 +1,13 @@
+2006-11-16  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * remote.c (PACKET_QPassSignals): New.
+       (last_pass_packet, remote_pass_signals): New.
+       (remote_protocol_features): Add QPassSignals.
+       (remote_query_supported): Correct an infinite loop.
+       (remote_open_1): Reset last_pass_packet.
+       (remote_resume): Call remote_pass_signals.
+       (_initialize_remote): Register "set remote pass-signals".
+
 2006-11-14  Maxim Grigoriev  <maxim@tensilica.com>
 
        * NEWS: New port to Xtensa.
 2006-11-14  Maxim Grigoriev  <maxim@tensilica.com>
 
        * NEWS: New port to Xtensa.
index 97f5018..ecf7a8c 100644 (file)
@@ -1,3 +1,10 @@
+2006-11-16  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdb.texinfo (Remote configuration): Mention
+       "pass-signals-packet".
+       (General Query Packets): Document QPassSignals.  Fix
+       a typo.
+
 2006-11-14  Maxim Grigoriev  <maxim@tensilica.com>
 
        * gdb.texinfo (Contributors): Add contributors of Xtensa port.
 2006-11-14  Maxim Grigoriev  <maxim@tensilica.com>
 
        * gdb.texinfo (Contributors): Add contributors of Xtensa port.
index 0491816..f0b5f87 100644 (file)
@@ -12841,6 +12841,10 @@ The available settings are:
 @tab @code{qSupported}
 @tab Remote communications parameters
 
 @tab @code{qSupported}
 @tab Remote communications parameters
 
+@item @code{pass-signals-packet}
+@tab @code{QPassSignals}
+@tab @code{handle @var{signal}}
+
 @end multitable
 
 @node remote stub
 @end multitable
 
 @node remote stub
@@ -23347,8 +23351,8 @@ The @samp{C}, @samp{c}, @samp{S}, @samp{s} and @samp{?} packets can
 receive any of the below as a reply.  In the case of the @samp{C},
 @samp{c}, @samp{S} and @samp{s} packets, that reply is only returned
 when the target halts.  In the below the exact meaning of @dfn{signal
 receive any of the below as a reply.  In the case of the @samp{C},
 @samp{c}, @samp{S} and @samp{s} packets, that reply is only returned
 when the target halts.  In the below the exact meaning of @dfn{signal
-number} is poorly defined.  In general one of the UNIX signal
-numbering conventions is used.
+number} is defined by the header @file{include/gdb/signals.h} in the
+@value{GDBN} source code.
 
 As in the description of request packets, we include spaces in the
 reply templates for clarity; these are not part of the reply packet's
 
 As in the description of request packets, we include spaces in the
 reply templates for clarity; these are not part of the reply packet's
@@ -23604,6 +23608,37 @@ Don't use this packet; use the @samp{qThreadExtraInfo} query instead
 
 Reply: see @code{remote.c:remote_unpack_thread_info_response()}.
 
 
 Reply: see @code{remote.c:remote_unpack_thread_info_response()}.
 
+@item QPassSignals: @var{signal} @r{[};@var{signal}@r{]}@dots{}
+@cindex pass signals to inferior, remote request
+@cindex @samp{QPassSignals} packet
+Each listed @var{signal} should be passed directly to the inferior process. 
+Signals are numbered identically to continue packets and stop replies
+(@pxref{Stop Reply Packets}).  Each @var{signal} list item should be
+strictly greater than the previous item.  These signals do not need to stop
+the inferior, or be reported to @value{GDBN}.  All other signals should be
+reported to @value{GDBN}.  Multiple @samp{QPassSignals} packets do not
+combine; any earlier @samp{QPassSignals} list is completely replaced by the
+new list.  This packet improves performance when using @samp{handle
+@var{signal} nostop noprint pass}.
+
+Reply:
+@table @samp
+@item OK
+The request succeeded.
+
+@item E @var{nn}
+An error occurred.  @var{nn} are hex digits.
+
+@item
+An empty reply indicates that @samp{QPassSignals} is not supported by
+the stub.
+@end table
+
+Use of this packet is controlled by the @code{set remote pass-signals}
+command (@pxref{Remote configuration, set remote pass-signals}).
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+
 @item qRcmd,@var{command}
 @cindex execute remote command, remote request
 @cindex @samp{qRcmd} packet
 @item qRcmd,@var{command}
 @cindex execute remote command, remote request
 @cindex @samp{qRcmd} packet
@@ -23747,6 +23782,11 @@ These are the currently defined stub features and their properties:
 @tab @samp{-}
 @tab Yes
 
 @tab @samp{-}
 @tab Yes
 
+@item @samp{QPassSignals}
+@tab No
+@tab @samp{-}
+@tab Yes
+
 @end multitable
 
 These are the currently defined stub features, in more detail:
 @end multitable
 
 These are the currently defined stub features, in more detail:
@@ -23862,7 +23902,7 @@ Access the target's @dfn{auxiliary vector}.  @xref{OS Information,
 auxiliary vector}.  Note @var{annex} must be empty.
 
 This packet is not probed by default; the remote stub must request it,
 auxiliary vector}.  Note @var{annex} must be empty.
 
 This packet is not probed by default; the remote stub must request it,
-by suppling an appropriate @samp{qSupported} response (@pxref{qSupported}).
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 @end table
 
 @table @samp
 @end table
 
 @table @samp
index 3a53f86..fa7080f 100644 (file)
@@ -1,3 +1,13 @@
+2006-11-16  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * linux-low.c (linux_wait_for_event): Reformat.  Use the
+       pass_signals array.
+       * remote-utils.c (decode_address_to_semicolon): New.
+       * server.c (pass_signals, handle_general_set): New.
+       (handle_query): Mention QPassSignals for qSupported.
+       (main): Call handle_general_set.
+       * server.h (pass_signals, decode_address_to_semicolon): New.
+
 2006-11-06  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * server.c (handle_query): Correct error handling for read_auxv.
 2006-11-06  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * server.c (handle_query): Correct error handling for read_auxv.
index 2a780ea..83a56aa 100644 (file)
@@ -498,69 +498,76 @@ linux_wait_for_event (struct thread_info *child)
       current_inferior = (struct thread_info *)
        find_inferior_id (&all_threads, event_child->tid);
 
       current_inferior = (struct thread_info *)
        find_inferior_id (&all_threads, event_child->tid);
 
-      if (using_threads)
+      /* Check for thread exit.  */
+      if (using_threads && ! WIFSTOPPED (wstat))
        {
        {
-         /* Check for thread exit.  */
-         if (! WIFSTOPPED (wstat))
-           {
-             if (debug_threads)
-               fprintf (stderr, "Thread %ld (LWP %ld) exiting\n",
-                        event_child->tid, event_child->head.id);
+         if (debug_threads)
+           fprintf (stderr, "Thread %ld (LWP %ld) exiting\n",
+                    event_child->tid, event_child->head.id);
 
 
-             /* If the last thread is exiting, just return.  */
-             if (all_threads.head == all_threads.tail)
-               return wstat;
+         /* If the last thread is exiting, just return.  */
+         if (all_threads.head == all_threads.tail)
+           return wstat;
 
 
-             dead_thread_notify (event_child->tid);
+         dead_thread_notify (event_child->tid);
 
 
-             remove_inferior (&all_processes, &event_child->head);
-             free (event_child);
-             remove_thread (current_inferior);
-             current_inferior = (struct thread_info *) all_threads.head;
+         remove_inferior (&all_processes, &event_child->head);
+         free (event_child);
+         remove_thread (current_inferior);
+         current_inferior = (struct thread_info *) all_threads.head;
 
 
-             /* If we were waiting for this particular child to do something...
-                well, it did something.  */
-             if (child != NULL)
-               return wstat;
+         /* If we were waiting for this particular child to do something...
+            well, it did something.  */
+         if (child != NULL)
+           return wstat;
 
 
-             /* Wait for a more interesting event.  */
-             continue;
-           }
+         /* Wait for a more interesting event.  */
+         continue;
+       }
 
 
-         if (WIFSTOPPED (wstat)
-             && WSTOPSIG (wstat) == SIGSTOP
-             && event_child->stop_expected)
-           {
-             if (debug_threads)
-               fprintf (stderr, "Expected stop.\n");
-             event_child->stop_expected = 0;
-             linux_resume_one_process (&event_child->head,
-                                       event_child->stepping, 0, NULL);
-             continue;
-           }
+      if (using_threads
+         && WIFSTOPPED (wstat)
+         && WSTOPSIG (wstat) == SIGSTOP
+         && event_child->stop_expected)
+       {
+         if (debug_threads)
+           fprintf (stderr, "Expected stop.\n");
+         event_child->stop_expected = 0;
+         linux_resume_one_process (&event_child->head,
+                                   event_child->stepping, 0, NULL);
+         continue;
+       }
 
 
-         /* FIXME drow/2002-06-09: Get signal numbers from the inferior's
-            thread library?  */
-         if (WIFSTOPPED (wstat)
-             && (WSTOPSIG (wstat) == __SIGRTMIN
-                 || WSTOPSIG (wstat) == __SIGRTMIN + 1))
-           {
-             siginfo_t info, *info_p;
+      /* If GDB is not interested in this signal, don't stop other
+        threads, and don't report it to GDB.  Just resume the
+        inferior right away.  We do this for threading-related
+        signals as well as any that GDB specifically requested
+        we ignore.  But never ignore SIGSTOP if we sent it
+        ourselves.  */
+      /* FIXME drow/2002-06-09: Get signal numbers from the inferior's
+        thread library?  */
+      if (WIFSTOPPED (wstat)
+         && ((using_threads && (WSTOPSIG (wstat) == __SIGRTMIN
+                                || WSTOPSIG (wstat) == __SIGRTMIN + 1))
+             || (pass_signals[target_signal_from_host (WSTOPSIG (wstat))]
+                 && (WSTOPSIG (wstat) != SIGSTOP
+                     || !event_child->sigstop_sent))))
+       {
+         siginfo_t info, *info_p;
 
 
-             if (debug_threads)
-               fprintf (stderr, "Ignored signal %d for %ld (LWP %ld).\n",
-                        WSTOPSIG (wstat), event_child->tid,
-                        event_child->head.id);
+         if (debug_threads)
+           fprintf (stderr, "Ignored signal %d for %ld (LWP %ld).\n",
+                    WSTOPSIG (wstat), event_child->tid,
+                    event_child->head.id);
 
 
-             if (ptrace (PTRACE_GETSIGINFO, event_child->lwpid, 0, &info) == 0)
-               info_p = &info;
-             else
-               info_p = NULL;
-             linux_resume_one_process (&event_child->head,
-                                       event_child->stepping,
-                                       WSTOPSIG (wstat), info_p);
-             continue;
-           }
+         if (ptrace (PTRACE_GETSIGINFO, event_child->lwpid, 0, &info) == 0)
+           info_p = &info;
+         else
+           info_p = NULL;
+         linux_resume_one_process (&event_child->head,
+                                   event_child->stepping,
+                                   WSTOPSIG (wstat), info_p);
+         continue;
        }
 
       /* If this event was not handled above, and is not a SIGTRAP, report
        }
 
       /* If this event was not handled above, and is not a SIGTRAP, report
index eb5d05d..fd5c844 100644 (file)
@@ -296,6 +296,22 @@ decode_address (CORE_ADDR *addrp, const char *start, int len)
   *addrp = addr;
 }
 
   *addrp = addr;
 }
 
+const char *
+decode_address_to_semicolon (CORE_ADDR *addrp, const char *start)
+{
+  const char *end;
+
+  end = start;
+  while (*end != '\0' && *end != ';')
+    end++;
+
+  decode_address (addrp, start, end - start);
+
+  if (*end == ';')
+    end++;
+  return end;
+}
+
 /* Convert number NIB to a hex digit.  */
 
 static int
 /* Convert number NIB to a hex digit.  */
 
 static int
index 5f78736..10a891e 100644 (file)
@@ -36,6 +36,8 @@ unsigned long old_thread_from_wait;
 int extended_protocol;
 int server_waiting;
 
 int extended_protocol;
 int server_waiting;
 
+int pass_signals[TARGET_SIGNAL_LAST];
+
 jmp_buf toplevel;
 
 /* The PID of the originally created or attached inferior.  Used to
 jmp_buf toplevel;
 
 /* The PID of the originally created or attached inferior.  Used to
@@ -157,6 +159,40 @@ write_qxfer_response (char *buf, unsigned char *data, int len, int is_more)
                               PBUFSIZ - 2) + 1;
 }
 
                               PBUFSIZ - 2) + 1;
 }
 
+/* Handle all of the extended 'Q' packets.  */
+void
+handle_general_set (char *own_buf)
+{
+  if (strncmp ("QPassSignals:", own_buf, strlen ("QPassSignals:")) == 0)
+    {
+      int numsigs = (int) TARGET_SIGNAL_LAST, i;
+      const char *p = own_buf + strlen ("QPassSignals:");
+      CORE_ADDR cursig;
+
+      p = decode_address_to_semicolon (&cursig, p);
+      for (i = 0; i < numsigs; i++)
+       {
+         if (i == cursig)
+           {
+             pass_signals[i] = 1;
+             if (*p == '\0')
+               /* Keep looping, to clear the remaining signals.  */
+               cursig = -1;
+             else
+               p = decode_address_to_semicolon (&cursig, p);
+           }
+         else
+           pass_signals[i] = 0;
+       }
+      strcpy (own_buf, "OK");
+      return;
+    }
+
+  /* Otherwise we didn't know what packet it was.  Say we didn't
+     understand it.  */
+  own_buf[0] = 0;
+}
+
 /* Handle all of the extended 'q' packets.  */
 void
 handle_query (char *own_buf, int *new_packet_len_p)
 /* Handle all of the extended 'q' packets.  */
 void
 handle_query (char *own_buf, int *new_packet_len_p)
@@ -248,7 +284,7 @@ handle_query (char *own_buf, int *new_packet_len_p)
   if (strncmp ("qSupported", own_buf, 10) == 0
       && (own_buf[10] == ':' || own_buf[10] == '\0'))
     {
   if (strncmp ("qSupported", own_buf, 10) == 0
       && (own_buf[10] == ':' || own_buf[10] == '\0'))
     {
-      sprintf (own_buf, "PacketSize=%x", PBUFSIZ - 1);
+      sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
 
       if (the_target->read_auxv != NULL)
        strcat (own_buf, ";qXfer:auxv:read+");
 
       if (the_target->read_auxv != NULL)
        strcat (own_buf, ";qXfer:auxv:read+");
@@ -601,6 +637,9 @@ main (int argc, char *argv[])
            case 'q':
              handle_query (own_buf, &new_packet_len);
              break;
            case 'q':
              handle_query (own_buf, &new_packet_len);
              break;
+           case 'Q':
+             handle_general_set (own_buf);
+             break;
            case 'd':
              remote_debug = !remote_debug;
              break;
            case 'd':
              remote_debug = !remote_debug;
              break;
index 5e7d394..e1fad45 100644 (file)
@@ -129,6 +129,7 @@ extern unsigned long step_thread;
 extern unsigned long thread_from_wait;
 extern unsigned long old_thread_from_wait;
 extern int server_waiting;
 extern unsigned long thread_from_wait;
 extern unsigned long old_thread_from_wait;
 extern int server_waiting;
+extern int pass_signals[];
 
 extern jmp_buf toplevel;
 
 
 extern jmp_buf toplevel;
 
@@ -153,6 +154,7 @@ void new_thread_notify (int id);
 void dead_thread_notify (int id);
 void prepare_resume_reply (char *buf, char status, unsigned char sig);
 
 void dead_thread_notify (int id);
 void prepare_resume_reply (char *buf, char status, unsigned char sig);
 
+const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start);
 void decode_address (CORE_ADDR *addrp, const char *start, int len);
 void decode_m_packet (char *from, CORE_ADDR * mem_addr_ptr,
                      unsigned int *len_ptr);
 void decode_address (CORE_ADDR *addrp, const char *start, int len);
 void decode_m_packet (char *from, CORE_ADDR * mem_addr_ptr,
                      unsigned int *len_ptr);
index afbec0d..513b6c7 100644 (file)
@@ -867,6 +867,7 @@ enum {
   PACKET_qXfer_memory_map,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
   PACKET_qXfer_memory_map,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
+  PACKET_QPassSignals,
   PACKET_MAX
 };
 
   PACKET_MAX
 };
 
@@ -1004,6 +1005,65 @@ record_currthread (int currthread)
     }
 }
 
     }
 }
 
+static char *last_pass_packet;
+
+/* If 'QPassSignals' is supported, tell the remote stub what signals
+   it can simply pass through to the inferior without reporting.  */
+
+static void
+remote_pass_signals (void)
+{
+  if (remote_protocol_packets[PACKET_QPassSignals].support != PACKET_DISABLE)
+    {
+      char *pass_packet, *p;
+      int numsigs = (int) TARGET_SIGNAL_LAST;
+      int count = 0, i;
+
+      gdb_assert (numsigs < 256);
+      for (i = 0; i < numsigs; i++)
+       {
+         if (signal_stop_state (i) == 0
+             && signal_print_state (i) == 0
+             && signal_pass_state (i) == 1)
+           count++;
+       }
+      pass_packet = xmalloc (count * 3 + strlen ("QPassSignals:") + 1);
+      strcpy (pass_packet, "QPassSignals:");
+      p = pass_packet + strlen (pass_packet);
+      for (i = 0; i < numsigs; i++)
+       {
+         if (signal_stop_state (i) == 0
+             && signal_print_state (i) == 0
+             && signal_pass_state (i) == 1)
+           {
+             if (i >= 16)
+               *p++ = tohex (i >> 4);
+             *p++ = tohex (i & 15);
+             if (count)
+               *p++ = ';';
+             else
+               break;
+             count--;
+           }
+       }
+      *p = 0;
+      if (!last_pass_packet || strcmp (last_pass_packet, pass_packet))
+       {
+         struct remote_state *rs = get_remote_state ();
+         char *buf = rs->buf;
+
+         putpkt (pass_packet);
+         getpkt (&rs->buf, &rs->buf_size, 0);
+         packet_ok (buf, &remote_protocol_packets[PACKET_QPassSignals]);
+         if (last_pass_packet)
+           xfree (last_pass_packet);
+         last_pass_packet = pass_packet;
+       }
+      else
+       xfree (pass_packet);
+    }
+}
+
 #define MAGIC_NULL_PID 42000
 
 static void
 #define MAGIC_NULL_PID 42000
 
 static void
@@ -2206,7 +2266,9 @@ static struct protocol_feature remote_protocol_features[] = {
   { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_auxv },
   { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
   { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_auxv },
   { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
-    PACKET_qXfer_memory_map }
+    PACKET_qXfer_memory_map },
+  { "QPassSignals", PACKET_DISABLE, remote_supported_packet,
+    PACKET_QPassSignals },
 };
 
 static void
 };
 
 static void
@@ -2260,14 +2322,14 @@ remote_query_supported (void)
        }
       else
        {
        }
       else
        {
+         *end = '\0';
+         next = end + 1;
+
          if (end == p)
            {
              warning (_("empty item in \"qSupported\" response"));
              continue;
            }
          if (end == p)
            {
              warning (_("empty item in \"qSupported\" response"));
              continue;
            }
-
-         *end = '\0';
-         next = end + 1;
        }
 
       name_end = strchr (p, '=');
        }
 
       name_end = strchr (p, '=');
@@ -2354,6 +2416,10 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target,
 
   unpush_target (target);
 
 
   unpush_target (target);
 
+  /* Make sure we send the passed signals list the next time we resume.  */
+  xfree (last_pass_packet);
+  last_pass_packet = NULL;
+
   remote_fileio_reset ();
   reopen_exec_file ();
   reread_symbols ();
   remote_fileio_reset ();
   reopen_exec_file ();
   reread_symbols ();
@@ -2728,6 +2794,9 @@ remote_resume (ptid_t ptid, int step, enum target_signal siggnal)
   if (deprecated_target_resume_hook)
     (*deprecated_target_resume_hook) ();
 
   if (deprecated_target_resume_hook)
     (*deprecated_target_resume_hook) ();
 
+  /* Update the inferior on signals to silently pass, if they've changed.  */
+  remote_pass_signals ();
+
   /* The vCont packet doesn't need to specify threads via Hc.  */
   if (remote_vcont_resume (ptid, step, siggnal))
     return;
   /* The vCont packet doesn't need to specify threads via Hc.  */
   if (remote_vcont_resume (ptid, step, siggnal))
     return;
@@ -6281,6 +6350,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_vCont],
                         "vCont", "verbose-resume", 0);
 
   add_packet_config_cmd (&remote_protocol_packets[PACKET_vCont],
                         "vCont", "verbose-resume", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_QPassSignals],
+                        "QPassSignals", "pass-signals", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qSymbol],
                         "qSymbol", "symbol-lookup", 0);
 
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qSymbol],
                         "qSymbol", "symbol-lookup", 0);