2010-01-21 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / remote.c
index 9c50f7ef928b983f45c47d3b4b7ef518bfd95dec..2cee1b0c3a0158d7a2d916d4e3cca29b1cf96d51 100644 (file)
@@ -60,6 +60,7 @@
 #include "remote-fileio.h"
 #include "gdb/fileio.h"
 #include "gdb_stat.h"
+#include "xml-support.h"
 
 #include "memory-map.h"
 
@@ -188,9 +189,9 @@ static void record_currthread (ptid_t currthread);
 
 static int fromhex (int a);
 
-static int hex2bin (const char *hex, gdb_byte *bin, int count);
+extern int hex2bin (const char *hex, gdb_byte *bin, int count);
 
-static int bin2hex (const gdb_byte *bin, char *hex, int count);
+extern int bin2hex (const gdb_byte *bin, char *hex, int count);
 
 static int putpkt_binary (char *buf, int cnt);
 
@@ -214,8 +215,12 @@ static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
 static ptid_t read_ptid (char *buf, char **obuf);
 
 struct remote_state;
-static void remote_get_tracing_state (struct remote_state *);
+static int remote_get_trace_status (struct trace_status *ts);
 
+static int remote_upload_tracepoints (struct uploaded_tp **utpp);
+
+static int remote_upload_trace_state_variables (struct uploaded_tsv **utsvp);
+  
 static void remote_query_supported (void);
 
 static void remote_check_symbols (struct objfile *objfile);
@@ -324,6 +329,20 @@ struct remote_state
   int ctrlc_pending_p;
 };
 
+/* Private data that we'll store in (struct thread_info)->private.  */
+struct private_thread_info
+{
+  char *extra;
+  int core;
+};
+
+static void
+free_private_thread_info (struct private_thread_info *info)
+{
+  xfree (info->extra);
+  xfree (info);
+}
+
 /* Returns true if the multi-process extensions are in effect.  */
 static int
 remote_multi_process_p (struct remote_state *rs)
@@ -1121,6 +1140,7 @@ enum {
   PACKET_qXfer_spu_read,
   PACKET_qXfer_spu_write,
   PACKET_qXfer_osdata,
+  PACKET_qXfer_threads,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
   PACKET_QPassSignals,
@@ -1395,7 +1415,7 @@ remote_notice_new_inferior (ptid_t currthread, int running)
              remote_add_thread (currthread, running);
              inferior_ptid = currthread;
            }
-         return;
+         return;
        }
 
       if (ptid_equal (magic_null_ptid, inferior_ptid))
@@ -1405,7 +1425,7 @@ remote_notice_new_inferior (ptid_t currthread, int running)
             doesn't support qC.  This is the first stop reported
             after an attach, so this is the main thread.  Update the
             ptid in the thread list.  */
-         thread_change_ptid (inferior_ptid, currthread);
+         thread_change_ptid (inferior_ptid, currthread);
          return;
        }
 
@@ -1427,6 +1447,26 @@ remote_notice_new_inferior (ptid_t currthread, int running)
     }
 }
 
+/* Return the private thread data, creating it if necessary.  */
+
+struct private_thread_info *
+demand_private_info (ptid_t ptid)
+{
+  struct thread_info *info = find_thread_ptid (ptid);
+
+  gdb_assert (info);
+
+  if (!info->private)
+    {
+      info->private = xmalloc (sizeof (*(info->private)));
+      info->private_dtor = free_private_thread_info;
+      info->private->core = -1;
+      info->private->extra = 0;
+    }
+
+  return info->private;
+}
+
 /* Call this function as a result of
    1) A halt indication (T packet) containing a thread id
    2) A direct query of currthread
@@ -1437,12 +1477,6 @@ static void
 record_currthread (ptid_t currthread)
 {
   general_thread = currthread;
-
-  if (ptid_equal (currthread, minus_one_ptid))
-    /* We're just invalidating the local thread mirror.  */
-    return;
-
-  remote_notice_new_inferior (currthread, 0);
 }
 
 static char *last_pass_packet;
@@ -2371,6 +2405,80 @@ remote_find_new_threads (void)
                              CRAZY_MAX_THREADS);
 }
 
+#if defined(HAVE_LIBEXPAT)
+
+typedef struct thread_item
+{
+  ptid_t ptid;
+  char *extra;
+  int core;
+} thread_item_t;
+DEF_VEC_O(thread_item_t);
+
+struct threads_parsing_context
+{
+  VEC (thread_item_t) *items;
+};
+
+static void
+start_thread (struct gdb_xml_parser *parser,
+             const struct gdb_xml_element *element,
+             void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+  struct threads_parsing_context *data = user_data;
+
+  struct thread_item item;
+  char *id;
+
+  id = VEC_index (gdb_xml_value_s, attributes, 0)->value;
+  item.ptid = read_ptid (id, NULL);
+
+  if (VEC_length (gdb_xml_value_s, attributes) > 1)
+    item.core = *(ULONGEST *) VEC_index (gdb_xml_value_s, attributes, 1)->value;
+  else
+    item.core = -1;
+
+  item.extra = 0;
+
+  VEC_safe_push (thread_item_t, data->items, &item);
+}
+
+static void
+end_thread (struct gdb_xml_parser *parser,
+           const struct gdb_xml_element *element,
+           void *user_data, const char *body_text)
+{
+  struct threads_parsing_context *data = user_data;
+
+  if (body_text && *body_text)
+    VEC_last (thread_item_t, data->items)->extra = strdup (body_text);
+}
+
+const struct gdb_xml_attribute thread_attributes[] = {
+  { "id", GDB_XML_AF_NONE, NULL, NULL },
+  { "core", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element thread_children[] = {
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element threads_children[] = {
+  { "thread", thread_attributes, thread_children,
+    GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+    start_thread, end_thread },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element threads_elements[] = {
+  { "threads", NULL, threads_children,
+    GDB_XML_EF_NONE, NULL, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+#endif
+
 /*
  * Find all threads for info threads command.
  * Uses new thread protocol contributed by Cisco.
@@ -2388,6 +2496,61 @@ remote_threads_info (struct target_ops *ops)
   if (remote_desc == 0)                /* paranoia */
     error (_("Command can only be used when connected to the remote target."));
 
+#if defined(HAVE_LIBEXPAT)
+  if (remote_protocol_packets[PACKET_qXfer_threads].support == PACKET_ENABLE)
+    {
+      char *xml = target_read_stralloc (&current_target,
+                                        TARGET_OBJECT_THREADS, NULL);
+
+      struct cleanup *back_to = make_cleanup (xfree, xml);
+      if (xml && *xml)
+       {
+         struct gdb_xml_parser *parser;
+         struct threads_parsing_context context;
+         struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+
+         context.items = 0;
+         parser = gdb_xml_create_parser_and_cleanup (_("threads"),
+                                                     threads_elements,
+                                                     &context);
+
+         gdb_xml_use_dtd (parser, "threads.dtd");
+
+         if (gdb_xml_parse (parser, xml) == 0)
+           {
+             int i;
+             struct thread_item *item;
+
+             for (i = 0; VEC_iterate (thread_item_t, context.items, i, item); ++i)
+               {
+                 if (!ptid_equal (item->ptid, null_ptid))
+                   {
+                     struct private_thread_info *info;
+                     /* In non-stop mode, we assume new found threads
+                        are running until proven otherwise with a
+                        stop reply.  In all-stop, we can only get
+                        here if all threads are stopped.  */
+                     int running = non_stop ? 1 : 0;
+
+                     remote_notice_new_inferior (item->ptid, running);
+
+                     info = demand_private_info (item->ptid);
+                     info->core = item->core;
+                     info->extra = item->extra;
+                     item->extra = 0;
+                   }
+                 xfree (item->extra);
+               }
+           }
+
+         VEC_free (thread_item_t, context.items);
+       }
+
+      do_cleanups (back_to);
+      return;
+    }
+#endif
+
   if (use_threadinfo_query)
     {
       putpkt ("qfThreadInfo");
@@ -2460,6 +2623,15 @@ remote_threads_extra_info (struct thread_info *tp)
        server doesn't know about it.  */
     return NULL;
 
+  if (remote_protocol_packets[PACKET_qXfer_threads].support == PACKET_ENABLE)
+    {
+      struct thread_info *info = find_thread_ptid (tp->ptid);
+      if (info && info->private)
+       return info->private->extra;
+      else
+       return NULL;
+    }
+
   if (use_threadextra_query)
     {
       char *b = rs->buf;
@@ -2990,7 +3162,23 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
      previously; find out where things are at.  */
   if (rs->disconnected_tracing)
     {
-      remote_get_tracing_state (rs);
+      struct uploaded_tp *uploaded_tps = NULL;
+      struct uploaded_tsv *uploaded_tsvs = NULL;
+
+      remote_get_trace_status (current_trace_status ());
+      if (current_trace_status ()->running)
+       printf_filtered (_("Trace is already running on the target.\n"));
+
+      /* Get trace state variables first, they may be checked when
+        parsing uploaded commands.  */
+
+      remote_upload_trace_state_variables (&uploaded_tsvs);
+
+      merge_uploaded_trace_state_variables (&uploaded_tsvs);
+
+      remote_upload_tracepoints (&uploaded_tps);
+
+      merge_uploaded_tracepoints (&uploaded_tps);
     }
 
   /* If breakpoints are global, insert them now.  */
@@ -3245,6 +3433,8 @@ static struct protocol_feature remote_protocol_features[] = {
     PACKET_qXfer_spu_write },
   { "qXfer:osdata:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_osdata },
+  { "qXfer:threads:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_threads },
   { "QPassSignals", PACKET_DISABLE, remote_supported_packet,
     PACKET_QPassSignals },
   { "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet,
@@ -3778,7 +3968,7 @@ fromhex (int a)
     error (_("Reply contains invalid hex digit %d"), a);
 }
 
-static int
+int
 hex2bin (const char *hex, gdb_byte *bin, int count)
 {
   int i;
@@ -3808,7 +3998,7 @@ tohex (int nib)
     return 'a' + nib - 10;
 }
 
-static int
+int
 bin2hex (const gdb_byte *bin, char *hex, int count)
 {
   int i;
@@ -4359,6 +4549,8 @@ struct stop_reply
 
   int solibs_changed;
   int replay_event;
+
+  int core;
 };
 
 /* The list of already fetched and acknowledged stop events.  */
@@ -4522,6 +4714,7 @@ remote_parse_stop_reply (char *buf, struct stop_reply *event)
   event->replay_event = 0;
   event->stopped_by_watchpoint_p = 0;
   event->regcache = NULL;
+  event->core = -1;
 
   switch (buf[0])
     {
@@ -4548,7 +4741,8 @@ remote_parse_stop_reply (char *buf, struct stop_reply *event)
          /* If this packet is an awatch packet, don't parse the 'a'
             as a register number.  */
 
-         if (strncmp (p, "awatch", strlen("awatch")) != 0)
+         if (strncmp (p, "awatch", strlen("awatch")) != 0
+             && strncmp (p, "core", strlen ("core") != 0))
            {
              /* Read the ``P'' register number.  */
              pnum = strtol (p, &p_temp, 16);
@@ -4594,6 +4788,12 @@ Packet: '%s'\n"),
                  if (p_temp)
                    p = p_temp;
                }
+             else if (strncmp (p, "core", p1 - p) == 0)
+               {
+                 ULONGEST c;
+                 p = unpack_varlen_hex (++p1, &c);
+                 event->core = c;
+               }
              else
                {
                  /* Silently skip unknown optional info.  */
@@ -4803,6 +5003,7 @@ process_stop_reply (struct stop_reply *stop_reply,
                    struct target_waitstatus *status)
 {
   ptid_t ptid;
+  struct thread_info *info;
 
   *status = stop_reply->ws;
   ptid = stop_reply->ptid;
@@ -4834,6 +5035,7 @@ process_stop_reply (struct stop_reply *stop_reply,
       remote_watch_data_address = stop_reply->watch_data_address;
 
       remote_notice_new_inferior (ptid, 0);
+      demand_private_info (ptid)->core = stop_reply->core;
     }
 
   stop_reply_xfree (stop_reply);
@@ -7676,6 +7878,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
        (ops, "osdata", annex, readbuf, offset, len,
         &remote_protocol_packets[PACKET_qXfer_osdata]);
 
+    case TARGET_OBJECT_THREADS:
+      gdb_assert (annex == NULL);
+      return remote_read_qxfer (ops, "threads", annex, readbuf, offset, len,
+                               &remote_protocol_packets[PACKET_qXfer_threads]);
+
     default:
       return -1;
     }
@@ -7847,7 +8054,7 @@ remote_rcmd (char *command,
     {
       char *buf;
 
-      /* XXX - see also tracepoint.c:remote_get_noisy_reply().  */
+      /* XXX - see also remote_get_noisy_reply().  */
       rs->buf[0] = '\0';
       getpkt (&rs->buf, &rs->buf_size, 0);
       buf = rs->buf;
@@ -9155,9 +9362,15 @@ static void
 remote_download_trace_state_variable (struct trace_state_variable *tsv)
 {
   struct remote_state *rs = get_remote_state ();
+  char *p;
 
-  sprintf (rs->buf, "QTDV:%x:%s",
-          tsv->number, phex ((ULONGEST) tsv->initial_value, 8));
+  sprintf (rs->buf, "QTDV:%x:%s:%x:",
+          tsv->number, phex ((ULONGEST) tsv->initial_value, 8), tsv->builtin);
+  p = rs->buf + strlen (rs->buf);
+  if ((p - rs->buf) + strlen (tsv->name) * 2 >= get_remote_packet_size ())
+    error (_("Trace state variable name too long for tsv definition packet"));
+  p += 2 * bin2hex ((gdb_byte *) (tsv->name), p, 0);
+  *p++ = '\0';
   putpkt (rs->buf);
   remote_get_noisy_reply (&target_buf, &target_buf_size);
 }
@@ -9208,16 +9421,39 @@ remote_trace_start ()
 }
 
 static int
-remote_get_trace_status (int *stop_reason)
+remote_get_trace_status (struct trace_status *ts)
 {
+  char *p, *p1, *p_temp;
+  ULONGEST val;
+  /* FIXME we need to get register block size some other way */
+  extern int trace_regblock_size;
+  trace_regblock_size = get_remote_arch_state ()->sizeof_g_packet;
+
   putpkt ("qTStatus");
-  remote_get_noisy_reply (&target_buf, &target_buf_size);
+  getpkt (&target_buf, &target_buf_size, 0);
+  /* FIXME should handle more variety of replies */
+
+  p = target_buf;
+
+  /* If the remote target doesn't do tracing, flag it.  */
+  if (*p == '\0')
+    return -1;
 
-  if (target_buf[0] != 'T' ||
-      (target_buf[1] != '0' && target_buf[1] != '1'))
+  /* We're working with a live target.  */
+  ts->from_file = 0;
+
+  /* Set some defaults.  */
+  ts->running_known = 0;
+  ts->stop_reason = trace_stop_reason_unknown;
+  ts->traceframe_count = -1;
+  ts->buffer_free = 0;
+
+  if (*p++ != 'T')
     error (_("Bogus trace status reply from target: %s"), target_buf);
 
-  return (target_buf[1] == '1');
+  parse_trace_status (p, ts);
+
+  return ts->running;
 }
 
 static void
@@ -9247,16 +9483,16 @@ remote_trace_find (enum trace_find_type type, int num,
       sprintf (p, "%x", num);
       break;
     case tfind_pc:
-      sprintf (p, "pc:%s", paddress (target_gdbarch, addr1));
+      sprintf (p, "pc:%s", phex_nz (addr1, 0));
       break;
     case tfind_tp:
       sprintf (p, "tdp:%x", num);
       break;
     case tfind_range:
-      sprintf (p, "range:%s:%s", paddress (target_gdbarch, addr1), paddress (target_gdbarch, addr2));
+      sprintf (p, "range:%s:%s", phex_nz (addr1, 0), phex_nz (addr2, 0));
       break;
     case tfind_outside:
-      sprintf (p, "outside:%s:%s", paddress (target_gdbarch, addr1), paddress (target_gdbarch, addr2));
+      sprintf (p, "outside:%s:%s", phex_nz (addr1, 0), phex_nz (addr2, 0));
       break;
     default:
       error ("Unknown trace find type %d", type);
@@ -9312,6 +9548,67 @@ remote_get_trace_state_variable_value (int tsvnum, LONGEST *val)
   return 0;
 }
 
+static int
+remote_save_trace_data (char *filename)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *p, *reply;
+
+  p = rs->buf;
+  strcpy (p, "QTSave:");
+  p += strlen (p);
+  if ((p - rs->buf) + strlen (filename) * 2 >= get_remote_packet_size ())
+    error (_("Remote file name too long for trace save packet"));
+  p += 2 * bin2hex ((gdb_byte *) filename, p, 0);
+  *p++ = '\0';
+  putpkt (rs->buf);
+  remote_get_noisy_reply (&target_buf, &target_buf_size);
+  return 0;
+}
+
+/* This is basically a memory transfer, but needs to be its own packet
+   because we don't know how the target actually organizes its trace
+   memory, plus we want to be able to ask for as much as possible, but
+   not be unhappy if we don't get as much as we ask for.  */
+
+static LONGEST
+remote_get_raw_trace_data (gdb_byte *buf, ULONGEST offset, LONGEST len)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *reply;
+  char *p;
+  int rslt;
+
+  p = rs->buf;
+  strcpy (p, "qTBuffer:");
+  p += strlen (p);
+  p += hexnumstr (p, offset);
+  *p++ = ',';
+  p += hexnumstr (p, len);
+  *p++ = '\0';
+
+  putpkt (rs->buf);
+  reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
+  if (reply && *reply)
+    {
+      /* 'l' by itself means we're at the end of the buffer and
+        there is nothing more to get.  */
+      if (*reply == 'l')
+       return 0;
+
+      /* Convert the reply into binary.  Limit the number of bytes to
+        convert according to our passed-in buffer size, rather than
+        what was returned in the packet; if the target is
+        unexpectedly generous and gives us a bigger reply than we
+        asked for, we don't want to crash.  */
+      rslt = hex2bin (target_buf, buf, len);
+      return rslt;
+    }
+
+  /* Something went wrong, flag as an error.  */
+  return -1;
+}
+
 static void
 remote_set_disconnected_tracing (int val)
 {
@@ -9324,6 +9621,15 @@ remote_set_disconnected_tracing (int val)
     error (_("Target does not support this command."));
 }
 
+static int
+remote_core_of_thread (struct target_ops *ops, ptid_t ptid)
+{
+  struct thread_info *info = find_thread_ptid (ptid);
+  if (info && info->private)
+    return info->private->core;
+  return -1;
+}
+
 static void
 init_remote_ops (void)
 {
@@ -9396,7 +9702,12 @@ Specify the serial device it is connected to\n\
   remote_ops.to_trace_stop = remote_trace_stop;
   remote_ops.to_trace_find = remote_trace_find;
   remote_ops.to_get_trace_state_variable_value = remote_get_trace_state_variable_value;
+  remote_ops.to_save_trace_data = remote_save_trace_data;
+  remote_ops.to_upload_tracepoints = remote_upload_tracepoints;
+  remote_ops.to_upload_trace_state_variables = remote_upload_trace_state_variables;
+  remote_ops.to_get_raw_trace_data = remote_get_raw_trace_data;
   remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing;
+  remote_ops.to_core_of_thread = remote_core_of_thread;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
@@ -9547,181 +9858,51 @@ remote_new_objfile (struct objfile *objfile)
     remote_check_symbols (objfile);
 }
 
-/* Struct to collect random info about tracepoints on the target.  */
-
-struct uploaded_tp {
-  int number;
-  enum bptype type;
-  ULONGEST addr;
-  int enabled;
-  int step;
-  int pass;
-  int orig_size;
-  char *cond;
-  int cond_len;
-  struct uploaded_tp *next;
-};
-
-struct uploaded_tp *uploaded_tps;
-
-struct uploaded_tp *
-get_uploaded_tp (int num)
-{
-  struct uploaded_tp *utp;
-
-  for (utp = uploaded_tps; utp; utp = utp->next)
-    if (utp->number == num)
-      return utp;
-  utp = (struct uploaded_tp *) xmalloc (sizeof (struct uploaded_tp));
-  utp->number = num;
-  utp->next = uploaded_tps;
-  uploaded_tps = utp;
-  return utp;
-}
-
-/* Look for an existing tracepoint that seems similar enough to the
-   uploaded one.  Enablement isn't checked, because the user can
-   toggle that freely, and may have done so in anticipation of the
-   next trace run.  */
-
-struct breakpoint *
-find_matching_tracepoint (struct uploaded_tp *utp)
+/* Pull all the tracepoints defined on the target and create local
+   data structures representing them.  We don't want to create real
+   tracepoints yet, we don't want to mess up the user's existing
+   collection.  */
+  
+static int
+remote_upload_tracepoints (struct uploaded_tp **utpp)
 {
-  VEC(breakpoint_p) *tp_vec = all_tracepoints ();
-  int ix;
-  struct breakpoint *t;
+  struct remote_state *rs = get_remote_state ();
+  char *p;
 
-  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
+  /* Ask for a first packet of tracepoint definition.  */
+  putpkt ("qTfP");
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  p = rs->buf;
+  while (*p && *p != 'l')
     {
-      if (t->type == utp->type
-         && (t->loc && t->loc->address == utp->addr)
-         && t->step_count == utp->step
-         && t->pass_count == utp->pass
-         /* FIXME also test conditionals and actions */
-         )
-       return t;
+      parse_tracepoint_definition (p, utpp);
+      /* Ask for another packet of tracepoint definition.  */
+      putpkt ("qTsP");
+      getpkt (&rs->buf, &rs->buf_size, 0);
+      p = rs->buf;
     }
-  return NULL;
+  return 0;
 }
 
-/* Find out everything we can about the trace run that was already
-   happening on the target.  This includes both running/stopped, and
-   the tracepoints that were in use.  */
-
-static void
-remote_get_tracing_state (struct remote_state *rs)
+static int
+remote_upload_trace_state_variables (struct uploaded_tsv **utsvp)
 {
+  struct remote_state *rs = get_remote_state ();
   char *p;
-  ULONGEST num, addr, step, pass, orig_size, xlen;
-  int enabled, i;
-  enum bptype type;
-  char *cond;
-  struct uploaded_tp *utp;
-  struct breakpoint *t;
-  extern void get_trace_status ();
-
-  get_trace_status ();
-  if (trace_running_p)
-    printf_filtered (_("Trace is running on the target.\n"));
 
-  putpkt ("qTfP");
+  /* Ask for a first packet of variable definition.  */
+  putpkt ("qTfV");
   getpkt (&rs->buf, &rs->buf_size, 0);
   p = rs->buf;
-  while (*p != '\0')
+  while (*p && *p != 'l')
     {
-      if (*p == 'T')
-       {
-         p++;
-         p = unpack_varlen_hex (p, &num);
-         p++;
-         p = unpack_varlen_hex (p, &addr);
-         p++;
-         enabled = (*p++ == 'E');
-         p++;
-         p = unpack_varlen_hex (p, &step);
-         p++;
-         p = unpack_varlen_hex (p, &pass);
-         p++;
-         type = bp_tracepoint;
-         cond = NULL;
-         while (*p)
-           {
-             if (*p == 'F')
-               {
-                 type = bp_fast_tracepoint;
-                 p++;
-                 p = unpack_varlen_hex (p, &orig_size);
-               }
-             else if (*p == 'X')
-               {
-                 p++;
-                 p = unpack_varlen_hex (p, &xlen);
-                 p++;  /* skip the comma */
-                 cond = (char *) xmalloc (xlen);
-                 hex2bin (p, cond, xlen);
-                 p += 2 * xlen;
-               }
-             else
-               /* Silently skip over anything else.  */
-               p++;
-           }
-         utp = get_uploaded_tp (num);
-         utp->type = type;
-         utp->addr = addr;
-         utp->enabled = enabled;
-         utp->step = step;
-         utp->pass = pass;
-         utp->cond = cond;
-         utp->cond_len = xlen;
-       }
-      else if (*p == 'A')
-       {
-         p++;
-         p = unpack_varlen_hex (p, &num);
-         p++;
-         p = unpack_varlen_hex (p, &addr);
-         p++;
-         utp = get_uploaded_tp (num);
-         /* FIXME save the action */
-       }
-      else if (*p == 'S')
-       {
-         p++;
-         p = unpack_varlen_hex (p, &num);
-         p++;
-         p = unpack_varlen_hex (p, &addr);
-         p++;
-         utp = get_uploaded_tp (num);
-         /* FIXME save the action */
-       }
-      else if (*p == 'l')
-       {
-         /* No more tracepoint info, get out of the loop.  */
-         break;
-       }
-      putpkt ("qTsP");
+      parse_tsv_definition (p, utsvp);
+      /* Ask for another packet of variable definition.  */
+      putpkt ("qTsV");
       getpkt (&rs->buf, &rs->buf_size, 0);
       p = rs->buf;
     }
-  /* Got all the tracepoint info, now look for matches among what we
-     already have in GDB.  */
-  for (utp = uploaded_tps; utp; utp = utp->next)
-    {
-      t = find_matching_tracepoint (utp);
-      if (t)
-       {
-         printf_filtered (_("Assuming tracepoint %d is same as target's tracepoint %d.\n"),
-                          t->number, utp->number);
-         t->number_on_target = utp->number;
-       }
-      else
-       {
-         extern void create_tracepoint_from_upload (int num, ULONGEST addr);
-         create_tracepoint_from_upload (utp->number, utp->addr);
-       }
-    }
-  /* FIXME free all the space */
-  uploaded_tps = NULL;
+  return 0;
 }
 
 void
@@ -9933,6 +10114,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_osdata],
                         "qXfer:osdata:read", "osdata", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_threads],
+                        "qXfer:threads:read", "threads", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_siginfo_read],
                          "qXfer:siginfo:read", "read-siginfo-object", 0);
 
This page took 0.033266 seconds and 4 git commands to generate.