Cleanup bfd_close() cleanups.
[deliverable/binutils-gdb.git] / gdb / remote.c
index 402c95c5124a11901e925040e4ba360ac3b2fe2f..1087d9f014a2fc6029458795373daa157e08e241 100644 (file)
@@ -1,6 +1,5 @@
 /* Remote target communications for serial-line targets in custom GDB protocol
-   Copyright 1988, 91, 92, 93, 94, 95, 96, 97, 98, 1999 
-   Free Software Foundation, Inc.
+   Copyright 1988, 1991-2000 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -30,7 +29,7 @@
 #include "bfd.h"
 #include "symfile.h"
 #include "target.h"
-#include "wait.h"
+#include "gdb_wait.h"
 /*#include "terminal.h" */
 #include "gdbcmd.h"
 #include "objfiles.h"
@@ -56,6 +55,7 @@
 /* Prototypes for local functions */
 static void cleanup_sigint_signal_handler (void *dummy);
 static void initialize_sigint_signal_handler (void);
+static int getpkt_sane (char *buf, long sizeof_buf, int forever);
 
 static void handle_remote_sigint PARAMS ((int));
 static void handle_remote_sigint_twice PARAMS ((int));
@@ -245,15 +245,6 @@ static struct target_ops remote_async_ops;
 
 static struct target_ops extended_async_remote_ops;
 
-/* This was 5 seconds, which is a long time to sit and wait.
-   Unless this is going though some terminal server or multiplexer or
-   other form of hairy serial connection, I would think 2 seconds would
-   be plenty.  */
-
-/* Changed to allow option to set timeout value.
-   was static int remote_timeout = 2; */
-extern int remote_timeout;
-
 /* FIXME: cagney/1999-09-23: Even though getpkt was called with
    ``forever'' still use the normal timeout mechanism.  This is
    currently used by the ASYNC code to guarentee that target reads
@@ -708,6 +699,17 @@ show_remote_protocol_Z_packet_cmd (args, from_tty)
 
 static struct packet_config remote_protocol_binary_download;
 
+/* Should we try the 'ThreadInfo' query packet?
+
+   This variable (NOT available to the user: auto-detect only!)
+   determines whether GDB will use the new, simpler "ThreadInfo"
+   query or the older, more complex syntax for thread queries.
+   This is an auto-detect variable (set to true at each connect, 
+   and set to false when the target fails to recognize it).  */
+
+static int use_threadinfo_query;
+static int use_threadextra_query;
+
 static void
 set_remote_protocol_binary_download_cmd (char *args,
                                         int from_tty,
@@ -758,7 +760,13 @@ record_currthread (currthread)
   if (!in_thread_list (currthread))
     {
       add_thread (currthread);
+#ifdef UI_OUT
+      ui_out_text (uiout, "[New ");
+      ui_out_text (uiout, target_pid_to_str (currthread));
+      ui_out_text (uiout, "]\n");
+#else
       printf_filtered ("[New %s]\n", target_pid_to_str (currthread));
+#endif
     }
 }
 
@@ -831,7 +839,7 @@ typedef unsigned char threadref[OPAQUETHREADBYTES];
 
 typedef int gdb_threadref;     /* internal GDB thread reference */
 
-/*  gdb_ext_thread_info is an internal GDB data structure which is
+/* gdb_ext_thread_info is an internal GDB data structure which is
    equivalint to the reply of the remote threadinfo packet */
 
 struct gdb_ext_thread_info
@@ -1561,7 +1569,9 @@ remote_current_thread (oldpid)
     return oldpid;
 }
 
-/* Find new threads for info threads command.  */
+/* Find new threads for info threads command.  
+ * Original version, using John Metzler's thread protocol.  
+ */
 
 static void
 remote_find_new_threads ()
@@ -1572,6 +1582,13 @@ remote_find_new_threads ()
     inferior_pid = remote_current_thread (inferior_pid);
 }
 
+/*
+ * Find all threads for info threads command.
+ * Uses new thread protocol contributed by Cisco.
+ * Falls back and attempts to use the older method (above)
+ * if the target doesn't respond to the new method.
+ */
+
 static void
 remote_threads_info (void)
 {
@@ -1582,29 +1599,108 @@ remote_threads_info (void)
   if (remote_desc == 0)                /* paranoia */
     error ("Command can only be used when connected to the remote target.");
 
-  putpkt ("qfThreadInfo");
-  bufp = buf;
-  getpkt (bufp, PBUFSIZ, 0);
-  if (bufp[0] == '\0')         /* q packet not recognized! */
-    {                          /* try old jmetzler method  */
-      remote_find_new_threads ();
-      return;
+  if (use_threadinfo_query)
+    {
+      putpkt ("qfThreadInfo");
+      bufp = buf;
+      getpkt (bufp, PBUFSIZ, 0);
+      if (bufp[0] != '\0')             /* q packet recognized */
+       {       
+         while (*bufp++ == 'm')        /* reply contains one or more TID */
+           {
+             do
+               {
+                 tid = strtol (bufp, &bufp, 16);
+                 if (tid != 0 && !in_thread_list (tid))
+                   add_thread (tid);
+               }
+             while (*bufp++ == ',');   /* comma-separated list */
+             putpkt ("qsThreadInfo");
+             bufp = buf;
+             getpkt (bufp, PBUFSIZ, 0);
+           }
+         return;       /* done */
+       }
     }
-  else                         /* try new 'q' method */
-    while (*bufp++ == 'm')     /* reply contains one or more TID */
+
+  /* Else fall back to old method based on jmetzler protocol. */
+  use_threadinfo_query = 0;
+  remote_find_new_threads ();
+  return;
+}
+
+/* 
+ * Collect a descriptive string about the given thread.
+ * The target may say anything it wants to about the thread
+ * (typically info about its blocked / runnable state, name, etc.).
+ * This string will appear in the info threads display.
+ * 
+ * Optional: targets are not required to implement this function.
+ */
+
+static char *
+remote_threads_extra_info (struct thread_info *tp)
+{
+  int result;
+  int set;
+  threadref id;
+  struct gdb_ext_thread_info threadinfo;
+  static char display_buf[100];        /* arbitrary... */
+  char *bufp = alloca (PBUFSIZ);
+  int n = 0;                    /* position in display_buf */
+
+  if (remote_desc == 0)                /* paranoia */
+    internal_error ("remote_threads_extra_info");
+
+  if (use_threadextra_query)
+    {
+      sprintf (bufp, "qThreadExtraInfo,%x", tp->pid);
+      putpkt (bufp);
+      getpkt (bufp, PBUFSIZ, 0);
+      if (bufp[0] != 0)
+       {
+         char *p;
+
+         for (p = display_buf; 
+              p < display_buf + sizeof(display_buf) - 1 &&
+                bufp[0] != 0 &&
+                bufp[1] != 0;
+              p++, bufp+=2)
+           {
+             *p = fromhex (bufp[0]) * 16 + fromhex (bufp[1]);
+           }
+         *p = 0;
+         return display_buf;
+       }
+    }
+
+  /* If the above query fails, fall back to the old method.  */
+  use_threadextra_query = 0;
+  set = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME
+    | TAG_MOREDISPLAY | TAG_DISPLAY;
+  int_to_threadref (&id, tp->pid);
+  if (remote_get_threadinfo (&id, set, &threadinfo))
+    if (threadinfo.active)
       {
-       do
+       if (*threadinfo.shortname)
+         n += sprintf(&display_buf[0], " Name: %s,", threadinfo.shortname);
+       if (*threadinfo.display)
+         n += sprintf(&display_buf[n], " State: %s,", threadinfo.display);
+       if (*threadinfo.more_display)
+         n += sprintf(&display_buf[n], " Priority: %s",
+                      threadinfo.more_display);
+
+       if (n > 0)
          {
-           tid = strtol (bufp, &bufp, 16);
-           if (tid != 0 && !in_thread_list (tid))
-             add_thread (tid);
+           /* for purely cosmetic reasons, clear up trailing commas */
+           if (',' == display_buf[n-1])
+             display_buf[n-1] = ' ';
+           return display_buf;
          }
-       while (*bufp++ == ','); /* comma-separated list */
-       putpkt ("qsThreadInfo");
-       bufp = buf;
-       getpkt (bufp, PBUFSIZ, 0);
       }
+  return NULL;
 }
+
 \f
 
 /*  Restart the remote side; this is an extended protocol operation.  */
@@ -1707,14 +1803,14 @@ get_offsets ()
   offs = (struct section_offsets *) alloca (SIZEOF_SECTION_OFFSETS);
   memcpy (offs, symfile_objfile->section_offsets, SIZEOF_SECTION_OFFSETS);
 
-  ANOFFSET (offs, SECT_OFF_TEXT) = text_addr;
+  ANOFFSET (offs, SECT_OFF_TEXT (symfile_objfile)) = text_addr;
 
   /* This is a temporary kludge to force data and bss to use the same offsets
      because that's what nlmconv does now.  The real solution requires changes
      to the stub and remote.c that I don't have time to do right now.  */
 
-  ANOFFSET (offs, SECT_OFF_DATA) = data_addr;
-  ANOFFSET (offs, SECT_OFF_BSS) = data_addr;
+  ANOFFSET (offs, SECT_OFF_DATA (symfile_objfile)) = data_addr;
+  ANOFFSET (offs, SECT_OFF_BSS (symfile_objfile)) = data_addr;
 
   objfile_relocate (symfile_objfile, offs);
 }
@@ -1822,9 +1918,9 @@ remote_cisco_objfile_relocate (text_off, data_off, bss_off)
       offs = (struct section_offsets *) alloca (SIZEOF_SECTION_OFFSETS);
       memcpy (offs, symfile_objfile->section_offsets, SIZEOF_SECTION_OFFSETS);
 
-      ANOFFSET (offs, SECT_OFF_TEXT) = text_off;
-      ANOFFSET (offs, SECT_OFF_DATA) = data_off;
-      ANOFFSET (offs, SECT_OFF_BSS) = bss_off;
+      ANOFFSET (offs, SECT_OFF_TEXT (symfile_objfile)) = text_off;
+      ANOFFSET (offs, SECT_OFF_DATA (symfile_objfile)) = data_off;
+      ANOFFSET (offs, SECT_OFF_BSS (symfile_objfile)) = bss_off;
 
       /* First call the standard objfile_relocate.  */
       objfile_relocate (symfile_objfile, offs);
@@ -1921,7 +2017,8 @@ remote_open_1 (name, from_tty, target, extended_p)
 {
   if (name == 0)
     error ("To open a remote debug connection, you need to specify what\n\
-serial device is attached to the remote system (e.g. /dev/ttya).");
+serial device is attached to the remote system\n\
+(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.).");
 
   /* See FIXME above */
   wait_forever_enabled_p = 1;
@@ -1969,6 +2066,10 @@ serial device is attached to the remote system (e.g. /dev/ttya).");
      binary downloading. */
   init_packet_config (&remote_protocol_binary_download);
 
+  /* Probe for ability to use "ThreadInfo" query, as required.  */
+  use_threadinfo_query = 1;
+  use_threadextra_query = 1;
+
   /* Without this, some commands which require an active target (such
      as kill) won't work.  This variable serves (at least) double duty
      as both the pid of the target process (if it has such), and as a
@@ -2007,7 +2108,8 @@ remote_async_open_1 (name, from_tty, target, extended_p)
 {
   if (name == 0)
     error ("To open a remote debug connection, you need to specify what\n\
-serial device is attached to the remote system (e.g. /dev/ttya).");
+serial device is attached to the remote system\n\
+(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.).");
 
   target_preopen (from_tty);
 
@@ -2053,6 +2155,10 @@ serial device is attached to the remote system (e.g. /dev/ttya).");
      binary downloading. */
   init_packet_config (&remote_protocol_binary_download);
 
+  /* Probe for ability to use "ThreadInfo" query, as required.  */
+  use_threadinfo_query = 1;
+  use_threadextra_query = 1;
+
   /* Without this, some commands which require an active target (such
      as kill) won't work.  This variable serves (at least) double duty
      as both the pid of the target process (if it has such), and as a
@@ -2115,7 +2221,7 @@ remote_detach (args, from_tty)
   strcpy (buf, "D");
   remote_send (buf, PBUFSIZ);
 
-  pop_target ();
+  target_mourn_inferior ();
   if (from_tty)
     puts_filtered ("Ending remote debugging.\n");
 
@@ -2137,10 +2243,10 @@ remote_async_detach (args, from_tty)
   remote_send (buf, PBUFSIZ);
 
   /* Unregister the file descriptor from the event loop. */
-  if (SERIAL_IS_ASYNC_P (remote_desc))
+  if (target_is_async_p ())
     SERIAL_ASYNC (remote_desc, NULL, 0);
 
-  pop_target ();
+  target_mourn_inferior ();
   if (from_tty)
     puts_filtered ("Ending remote debugging.\n");
 }
@@ -2254,14 +2360,14 @@ remote_async_resume (pid, step, siggnal)
   /* FIXME: ezannoni 1999-09-28: We may need to move this out of here
      into infcmd.c in order to allow inferior function calls to work
      NOT asynchronously. */
-  if (event_loop_p && SERIAL_CAN_ASYNC_P (remote_desc))
+  if (event_loop_p && target_can_async_p ())
     target_async (inferior_event_handler, 0);
   /* Tell the world that the target is now executing. */
   /* FIXME: cagney/1999-09-23: Is it the targets responsibility to set
      this?  Instead, should the client of target just assume (for
      async targets) that the target is going to start executing?  Is
      this information already found in the continuation block?  */
-  if (SERIAL_IS_ASYNC_P (remote_desc))
+  if (target_is_async_p ())
     target_executing = 1;
   putpkt (buf);
 }
@@ -2710,14 +2816,14 @@ remote_async_wait (pid, status)
     {
       unsigned char *p;
 
-      if (!SERIAL_IS_ASYNC_P (remote_desc))
+      if (!target_is_async_p ())
        ofunc = signal (SIGINT, remote_interrupt);
       /* FIXME: cagney/1999-09-27: If we're in async mode we should
          _never_ wait for ever -> test on target_is_async_p().
          However, before we do that we need to ensure that the caller
          knows how to take the target into/out of async mode. */
       getpkt (buf, PBUFSIZ, wait_forever_enabled_p);
-      if (!SERIAL_IS_ASYNC_P (remote_desc))
+      if (!target_is_async_p ())
        signal (SIGINT, ofunc);
 
       /* This is a hook for when we need to do something (perhaps the
@@ -3490,11 +3596,6 @@ remote_read_bytes (memaddr, myaddr, len)
    SHOULD_WRITE is nonzero.  Returns length of data written or read; 0
    for error.  */
 
-#ifndef REMOTE_TRANSLATE_XFER_ADDRESS
-#define REMOTE_TRANSLATE_XFER_ADDRESS(MEM_ADDR, MEM_LEN, TARG_ADDR, TARG_LEN) \
-   (*(TARG_ADDR) = (MEM_ADDR), *(TARG_LEN) = (MEM_LEN))
-#endif
-
 /* ARGSUSED */
 static int
 remote_xfer_memory (mem_addr, buffer, mem_len, should_write, target)
@@ -3722,6 +3823,7 @@ putpkt_binary (buf, cnt)
              switch (ch)
                {
                case '+':
+               case '-':
                case SERIAL_TIMEOUT:
                case '$':
                  if (started_error_output)
@@ -3738,6 +3840,9 @@ putpkt_binary (buf, cnt)
              if (remote_debug)
                fprintf_unfiltered (gdb_stdlog, "Ack\n");
              return 1;
+           case '-':
+             if (remote_debug)
+               fprintf_unfiltered (gdb_stdlog, "Nak\n");
            case SERIAL_TIMEOUT:
              tcount++;
              if (tcount > 3)
@@ -3904,11 +4009,31 @@ read_frame (char *buf,
    store it in BUF.  If FOREVER, wait forever rather than timing out;
    this is used (in synchronous mode) to wait for a target that is is
    executing user code to stop.  */
-
+/* FIXME: ezannoni 2000-02-01 this wrapper is necessary so that we
+   don't have to change all the calls to getpkt to deal with the
+   return value, because at the moment I don't know what the right
+   thing to do it for those. */
 void
 getpkt (char *buf,
        long sizeof_buf,
        int forever)
+{
+  int timed_out;
+
+  timed_out = getpkt_sane (buf, sizeof_buf, forever);
+}
+
+
+/* Read a packet from the remote machine, with error checking, and
+   store it in BUF.  If FOREVER, wait forever rather than timing out;
+   this is used (in synchronous mode) to wait for a target that is is
+   executing user code to stop. If FOREVER == 0, this function is
+   allowed to time out gracefully and return an indication of this to
+   the caller. */
+int
+getpkt_sane (char *buf,
+       long sizeof_buf,
+       int forever)
 {
   int c;
   int tries;
@@ -3969,7 +4094,7 @@ getpkt (char *buf,
              fprintf_unfiltered (gdb_stdlog, "\n");
            }
          SERIAL_WRITE (remote_desc, "+", 1);
-         return;
+         return 0;
        }
 
       /* Try the whole thing again.  */
@@ -3981,6 +4106,7 @@ getpkt (char *buf,
 
   printf_unfiltered ("Ignoring packet error, continuing...\n");
   SERIAL_WRITE (remote_desc, "+", 1);
+  return 1;
 }
 \f
 static void
@@ -4009,7 +4135,7 @@ static void
 remote_async_kill ()
 {
   /* Unregister the file descriptor from the event loop. */
-  if (SERIAL_IS_ASYNC_P (remote_desc))
+  if (target_is_async_p ())
     SERIAL_ASYNC (remote_desc, NULL, 0);
 
   /* For some mysterious reason, wait_for_inferior calls kill instead of
@@ -4603,7 +4729,7 @@ remote_query (query_type, buf, outbuf, bufsiz)
 
 static void
 remote_rcmd (char *command,
-            struct gdb_file *outbuf)
+            struct ui_file *outbuf)
 {
   int i;
   char *buf = alloca (PBUFSIZ);
@@ -4855,7 +4981,8 @@ init_remote_ops ()
   remote_ops.to_longname = "Remote serial target in gdb-specific protocol";
   remote_ops.to_doc =
     "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
-Specify the serial device it is connected to (e.g. /dev/ttya).";
+Specify the serial device it is connected to\n\
+(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.).";
   remote_ops.to_open = remote_open;
   remote_ops.to_close = remote_close;
   remote_ops.to_detach = remote_detach;
@@ -4873,6 +5000,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
   remote_ops.to_mourn_inferior = remote_mourn;
   remote_ops.to_thread_alive = remote_thread_alive;
   remote_ops.to_find_new_threads = remote_threads_info;
+  remote_ops.to_extra_thread_info = remote_threads_extra_info;
   remote_ops.to_stop = remote_stop;
   remote_ops.to_query = remote_query;
   remote_ops.to_rcmd = remote_rcmd;
@@ -5009,6 +5137,10 @@ device is attached to the remote system (e.g. host:port).");
      binary downloading. */
   init_packet_config (&remote_protocol_binary_download);
 
+  /* Probe for ability to use "ThreadInfo" query, as required.  */
+  use_threadinfo_query = 1;
+  use_threadextra_query = 1;
+  
   /* Without this, some commands which require an active target (such
      as kill) won't work.  This variable serves (at least) double duty
      as both the pid of the target process (if it has such), and as a
@@ -5284,6 +5416,7 @@ Specify the serial device it is connected to (e.g. host:2020).";
   remote_cisco_ops.to_mourn_inferior = remote_cisco_mourn;
   remote_cisco_ops.to_thread_alive = remote_thread_alive;
   remote_cisco_ops.to_find_new_threads = remote_threads_info;
+  remote_ops.to_extra_thread_info = remote_threads_extra_info;
   remote_cisco_ops.to_stratum = process_stratum;
   remote_cisco_ops.to_has_all_memory = 1;
   remote_cisco_ops.to_has_memory = 1;
@@ -5297,14 +5430,14 @@ static int
 remote_can_async_p (void)
 {
   /* We're async whenever the serial device is. */
-  return SERIAL_CAN_ASYNC_P (remote_desc);
+  return (current_target.to_async_mask_value) && SERIAL_CAN_ASYNC_P (remote_desc);
 }
 
 static int
 remote_is_async_p (void)
 {
   /* We're async whenever the serial device is. */
-  return SERIAL_IS_ASYNC_P (remote_desc);
+  return (current_target.to_async_mask_value) && SERIAL_IS_ASYNC_P (remote_desc);
 }
 
 /* Pass the SERIAL event on and up to the client.  One day this code
@@ -5326,6 +5459,9 @@ remote_async_serial_handler (serial_t scb, void *context)
 static void
 remote_async (void (*callback) (enum inferior_event_type event_type, void *context), void *context)
 {
+  if (current_target.to_async_mask_value == 0)
+    internal_error ("Calling remote_async when async is masked");
+
   if (callback != NULL)
     {
       SERIAL_ASYNC (remote_desc, remote_async_serial_handler, NULL);
@@ -5369,6 +5505,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
   remote_async_ops.to_mourn_inferior = remote_async_mourn;
   remote_async_ops.to_thread_alive = remote_thread_alive;
   remote_async_ops.to_find_new_threads = remote_threads_info;
+  remote_ops.to_extra_thread_info = remote_threads_extra_info;
   remote_async_ops.to_stop = remote_stop;
   remote_async_ops.to_query = remote_query;
   remote_async_ops.to_rcmd = remote_rcmd;
@@ -5382,6 +5519,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
   remote_async_ops.to_can_async_p = remote_can_async_p;
   remote_async_ops.to_is_async_p = remote_is_async_p;
   remote_async_ops.to_async = remote_async;
+  remote_async_ops.to_async_mask_value = 1;
   remote_async_ops.to_magic = OPS_MAGIC;
 }
 
@@ -5482,13 +5620,6 @@ response packet.  GDB supplies the initial `$' character, and the\n\
 terminating `#' character and checksum.",
           &maintenancelist);
 
-  add_show_from_set
-    (add_set_cmd ("remotetimeout", no_class,
-                 var_integer, (char *) &remote_timeout,
-                 "Set timeout value for remote read.\n",
-                 &setlist),
-     &showlist);
-
   add_show_from_set
     (add_set_cmd ("remotebreak", no_class,
                  var_boolean, (char *) &remote_break,
This page took 0.033457 seconds and 4 git commands to generate.