2011-07-22 Kwok Cheung Yeung <kcy@codesourcery.com>
[deliverable/binutils-gdb.git] / gdb / gdbserver / server.c
index 9e1973929029d5bb955225cb1b547a128e8eae3f..a87aef558a1eeb0b0ad96e5f2cc70a06ef5f909a 100644 (file)
@@ -40,6 +40,9 @@ static int extended_protocol;
 static int response_needed;
 static int exit_requested;
 
+/* --once: Exit after the first connection has closed.  */
+int run_once;
+
 int multi_process;
 int non_stop;
 
@@ -121,7 +124,7 @@ queue_stop_reply (ptid_t ptid, struct target_waitstatus *status)
 {
   struct vstop_notif *new_notif;
 
-  new_notif = malloc (sizeof (*new_notif));
+  new_notif = xmalloc (sizeof (*new_notif));
   new_notif->next = NULL;
   new_notif->ptid = ptid;
   new_notif->status = *status;
@@ -1118,6 +1121,56 @@ handle_qxfer_threads (const char *annex,
   return len;
 }
 
+/* Handle qXfer:traceframe-info:read.  */
+
+static int
+handle_qxfer_traceframe_info (const char *annex,
+                             gdb_byte *readbuf, const gdb_byte *writebuf,
+                             ULONGEST offset, LONGEST len)
+{
+  static char *result = 0;
+  static unsigned int result_length = 0;
+
+  if (writebuf != NULL)
+    return -2;
+
+  if (!target_running () || annex[0] != '\0' || current_traceframe == -1)
+    return -1;
+
+  if (offset == 0)
+    {
+      struct buffer buffer;
+
+      /* When asked for data at offset 0, generate everything and
+        store into 'result'.  Successive reads will be served off
+        'result'.  */
+      free (result);
+
+      buffer_init (&buffer);
+
+      traceframe_read_info (current_traceframe, &buffer);
+
+      result = buffer_finish (&buffer);
+      result_length = strlen (result);
+      buffer_free (&buffer);
+    }
+
+  if (offset >= result_length)
+    {
+      /* We're out of data.  */
+      free (result);
+      result = NULL;
+      result_length = 0;
+      return 0;
+    }
+
+  if (len > result_length - offset)
+    len = result_length - offset;
+
+  memcpy (readbuf, result + offset, len);
+  return len;
+}
+
 static const struct qxfer qxfer_packets[] =
   {
     { "auxv", handle_qxfer_auxv },
@@ -1128,6 +1181,7 @@ static const struct qxfer qxfer_packets[] =
     { "spu", handle_qxfer_spu },
     { "statictrace", handle_qxfer_statictrace },
     { "threads", handle_qxfer_threads },
+    { "traceframe-info", handle_qxfer_traceframe_info },
   };
 
 static int
@@ -1306,7 +1360,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 
       sprintf (own_buf, "QC");
       own_buf += 2;
-      own_buf = write_ptid (own_buf, gdb_id);
+      write_ptid (own_buf, gdb_id);
       return;
     }
 
@@ -1485,6 +1539,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
            strcat (own_buf, ";FastTracepoints+");
          strcat (own_buf, ";StaticTracepoints+");
          strcat (own_buf, ";qXfer:statictrace:read+");
+         strcat (own_buf, ";qXfer:traceframe-info:read+");
+         strcat (own_buf, ";EnableDisableTracepoints+");
        }
 
       return;
@@ -1897,16 +1953,16 @@ handle_v_run (char *own_buf)
 
       if (program_argv == NULL)
        {
-         /* FIXME: new_argv memory leak */
          write_enn (own_buf);
+         freeargv (new_argv);
          return 0;
        }
 
       new_argv[0] = strdup (program_argv[0]);
       if (new_argv[0] == NULL)
        {
-         /* FIXME: new_argv memory leak */
          write_enn (own_buf);
+         freeargv (new_argv);
          return 0;
        }
     }
@@ -2260,7 +2316,9 @@ gdbserver_usage (FILE *stream)
           "  --debug               Enable general debugging output.\n"
           "  --remote-debug        Enable remote protocol debugging output.\n"
           "  --version             Display version information and exit.\n"
-          "  --wrapper WRAPPER --  Run WRAPPER to start new programs.\n");
+          "  --wrapper WRAPPER --  Run WRAPPER to start new programs.\n"
+          "  --once                Exit after the first connection has "
+                                                                 "closed.\n");
   if (REPORT_BUGS_TO[0] && stream == stdout)
     fprintf (stream, "Report bugs to \"%s\".\n", REPORT_BUGS_TO);
 }
@@ -2385,17 +2443,6 @@ detach_or_kill_for_exit (void)
   for_each_inferior (&all_processes, detach_or_kill_inferior_callback);
 }
 
-static void
-join_inferiors_callback (struct inferior_list_entry *entry)
-{
-  struct process_info *process = (struct process_info *) entry;
-
-  /* If we are attached, then we can exit.  Otherwise, we need to hang
-     around doing nothing, until the child is gone.  */
-  if (!process->attached)
-    join_inferior (ptid_get_pid (process->head.id));
-}
-
 int
 main (int argc, char *argv[])
 {
@@ -2484,6 +2531,8 @@ main (int argc, char *argv[])
                }
            }
        }
+      else if (strcmp (*next_arg, "--once") == 0)
+       run_once = 1;
       else
        {
          fprintf (stderr, "Unknown argument: %s\n", *next_arg);
@@ -2533,7 +2582,6 @@ main (int argc, char *argv[])
       exit (1);
     }
 
-  initialize_inferiors ();
   initialize_async_io ();
   initialize_low ();
   if (target_supports_tracepoints ())
@@ -2596,6 +2644,8 @@ main (int argc, char *argv[])
       exit (1);
     }
 
+  remote_prepare (port);
+
   while (1)
     {
       noack_mode = 0;
@@ -2624,7 +2674,7 @@ main (int argc, char *argv[])
         getpkt to fail; close the connection and reopen it at the
         top of the loop.  */
 
-      if (exit_requested)
+      if (exit_requested || run_once)
        {
          detach_or_kill_for_exit ();
          exit (0);
@@ -2790,8 +2840,7 @@ process_serial_event (void)
              /* If we are attached, then we can exit.  Otherwise, we
                 need to hang around doing nothing, until the child is
                 gone.  */
-             for_each_inferior (&all_processes,
-                                join_inferiors_callback);
+             join_inferior (pid);
              exit (0);
            }
        }
This page took 0.027766 seconds and 4 git commands to generate.