gdb/
authorPedro Alves <palves@redhat.com>
Mon, 14 Feb 2011 11:13:12 +0000 (11:13 +0000)
committerPedro Alves <palves@redhat.com>
Mon, 14 Feb 2011 11:13:12 +0000 (11:13 +0000)
* target.h (struct traceframe_info): Forward declare.
(enum target_object): Add TARGET_OBJECT_TRACEFRAME_INFO.
(struct target_ops) <to_traceframe_info>: New field.
(target_traceframe_info): New.
* target.c (update_current_target): Inherit and default
to_traceframe_info.
* remote.c (PACKET_qXfer_traceframe_info): New.
(remote_protocol_features): Register qXfer:traceframe-info:read.
(remote_xfer_partial): Handle TARGET_OBJECT_TRACEFRAME_INFO.
(remote_traceframe_info): New.
(init_remote_ops): Install it.
(_initialize_remote): Install "set/show remote traceframe-info"
commands.
* tracepoint.h (parse_traceframe_info): Declare.
* tracepoint.c (struct mem_range): New.
(mem_range_s): New typedef.
(struct traceframe_info): New.
(traceframe_info): New global.
(free_traceframe_info): New function.
(clear_traceframe_info): New function.
(start_tracing, tfind_1, set_traceframe_number): Clear traceframe
info.
(build_traceframe_info): New function.
(tfile_traceframe_info): New function.
(init_tfile_ops): Install tfile_traceframe_info.
(traceframe_info_start_memory, free_result): New functions.
(memory_attributes, traceframe_info_elements): New globals.
(parse_traceframe_info, get_traceframe_info): New functions.
* features/traceframe-info.dtd: New file.
* Makefile.in (XMLFILES): Add traceframe-info.dtd.

gdb/gdbserver/
* server.c (handle_qxfer_traceframe_info): New.
(qxfer_packets): Register "traceframe-info".
(handle_query): Report support for qXfer:traceframe-info:read+.
* tracepoint.c (match_blocktype): New.
(traceframe_find_block_type): Rename to ...
(traceframe_walk_blocks): ... this.  Add callback filter argument,
and use it.
(traceframe_find_block_type): New, reimplemented on top of
traceframe_walk_blocks.
(build_traceframe_info_xml): New.
(traceframe_read_info): New.
* server.h (traceframe_read_info): Declare.

gdb/doc/
* gdb.texinfo (Remote Configuration): Mention set/show remote
traceframe-info.
(Tools/Packages Optional for Building GDB): Mention that expat is
used for traceframe info.
(Remote Protocol) <Menu>: Add "Traceframe Info Format".
(General Query Packets) <qSupported>: Describe the
qXfer:traceframe-info:read feature.
(qXfer::read): Describe qXfer:traceframe-info:read.
(Traceframe Info Format): New section.

13 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/gdbserver/ChangeLog
gdb/gdbserver/server.c
gdb/gdbserver/server.h
gdb/gdbserver/tracepoint.c
gdb/remote.c
gdb/target.c
gdb/target.h
gdb/tracepoint.c
gdb/tracepoint.h

index aa5498873297c6df966ae7c977d93dc1c7a8fa79..d74fc1ef1f17e39409d3b1410aee86e5f1426498 100644 (file)
@@ -1,8 +1,40 @@
+2011-02-14  Pedro Alves  <pedro@codesourcery.com>
+
+       * target.h (struct traceframe_info): Forward declare.
+       (enum target_object): Add TARGET_OBJECT_TRACEFRAME_INFO.
+       (struct target_ops) <to_traceframe_info>: New field.
+       (target_traceframe_info): New.
+       * target.c (update_current_target): Inherit and default
+       to_traceframe_info.
+       * remote.c (PACKET_qXfer_traceframe_info): New.
+       (remote_protocol_features): Register qXfer:traceframe-info:read.
+       (remote_xfer_partial): Handle TARGET_OBJECT_TRACEFRAME_INFO.
+       (remote_traceframe_info): New.
+       (init_remote_ops): Install it.
+       (_initialize_remote): Install "set/show remote traceframe-info"
+       commands.
+       * tracepoint.h (parse_traceframe_info): Declare.
+       * tracepoint.c (struct mem_range): New.
+       (mem_range_s): New typedef.
+       (struct traceframe_info): New.
+       (traceframe_info): New global.
+       (free_traceframe_info): New function.
+       (clear_traceframe_info): New function.
+       (start_tracing, tfind_1, set_traceframe_number): Clear traceframe
+       info.
+       (build_traceframe_info): New function.
+       (tfile_traceframe_info): New function.
+       (init_tfile_ops): Install tfile_traceframe_info.
+       (traceframe_info_start_memory, free_result): New functions.
+       (memory_attributes, traceframe_info_elements): New globals.
+       (parse_traceframe_info, get_traceframe_info): New functions.
+       * features/traceframe-info.dtd: New file.
+       * Makefile.in (XMLFILES): Add traceframe-info.dtd.
+
 2011-02-14  Pedro Alves  <pedro@codesourcery.com>
 
        Base support for <unavailable> value contents.
 
-       gdb/
        * value.h (value_bytes_available): Declare.
        (mark_value_bytes_unavailable): Declare.
        * value.c (struct range): New struct.
index 5f91e351d87eb37a12e0804955a084359657968a..f991cb030ae8d2a83faab7b2dcc909c5c7797735 100644 (file)
@@ -499,7 +499,7 @@ RUNTESTFLAGS=
 # XML files to build in to GDB.
 XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd \
        $(srcdir)/features/library-list.dtd $(srcdir)/features/osdata.dtd \
-       $(srcdir)/features/threads.dtd
+       $(srcdir)/features/threads.dtd $(srcdir)/features/traceframe-info.dtd
 
 # This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
 # interface to the serial port.  Hopefully if get ported to OS/2, VMS,
index d10f9123f44d8c313fee50354b4c6825c7773fef..1dfda73adbe3001f9d263cf1598225acb2d363de 100644 (file)
@@ -1,3 +1,15 @@
+2011-02-14  Pedro Alves  <pedro@codesourcery.com>
+
+       * gdb.texinfo (Remote Configuration): Mention set/show remote
+       traceframe-info.
+       (Tools/Packages Optional for Building GDB): Mention that expat is
+       used for traceframe info.
+       (Remote Protocol) <Menu>: Add "Traceframe Info Format".
+       (General Query Packets) <qSupported>: Describe the
+       qXfer:traceframe-info:read feature.
+       (qXfer::read): Describe qXfer:traceframe-info:read.
+       (Traceframe Info Format): New section.
+
 2011-02-04  Pedro Alves  <pedro@codesourcery.com>
 
        * gdbint.texinfo (Formatting): Mention some formatting guidelines
index 6a3c7dee0e2af78a2e37f0b2a9fc5309220a0bb7..332fdef2c86cb32cb9d1ab17254a60b8bedcd86c 100644 (file)
@@ -16698,6 +16698,10 @@ are:
 @item @code{query-attached}
 @tab @code{qAttached}
 @tab Querying remote process attach state.
+
+@item @code{traceframe-info}
+@tab @code{qXfer:traceframe-info:read}
+@tab Traceframe info
 @end multitable
 
 @node Remote Stub
@@ -30848,6 +30852,8 @@ Target descriptions (@pxref{Target Descriptions})
 Remote shared library lists (@pxref{Library List Format})
 @item
 MS-Windows shared libraries (@pxref{Shared Libraries})
+@item
+Traceframe info (@pxref{Traceframe Info Format})
 @end itemize
 
 @item zlib
@@ -31670,6 +31676,7 @@ Show the current setting of the target wait timeout.
 * Library List Format::
 * Memory Map Format::
 * Thread List Format::
+* Traceframe Info Format::
 @end menu
 
 @node Overview
@@ -33220,6 +33227,11 @@ These are the currently defined stub features and their properties:
 @tab @samp{-}
 @tab Yes
 
+@item @samp{qXfer:traceframe-info:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
 
 @item @samp{QNonStop}
 @tab No
@@ -33322,6 +33334,10 @@ The remote stub understands the @samp{qXfer:siginfo:write} packet
 The remote stub understands the @samp{qXfer:threads:read} packet
 (@pxref{qXfer threads read}).
 
+@item qXfer:traceframe-info:read
+The remote stub understands the @samp{qXfer:traceframe-info:read}
+packet (@pxref{qXfer traceframe info read}).
+
 @item QNonStop
 The remote stub understands the @samp{QNonStop} packet
 (@pxref{QNonStop}).
@@ -33560,6 +33576,16 @@ annex part of the generic @samp{qXfer} packet must be empty
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 
+@item qXfer:traceframe-info:read::@var{offset},@var{length}
+@anchor{qXfer traceframe info read}
+
+Return a description of the current traceframe's contents.
+@xref{Traceframe Info Format}.  The annex part of the generic
+@samp{qXfer} packet must be empty (@pxref{qXfer read}).
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+
 @item qXfer:osdata:read::@var{offset},@var{length}
 @anchor{qXfer osdata read}
 Access the target's @dfn{operating system information}.  
@@ -35851,6 +35877,58 @@ identifies the thread (@pxref{thread-id syntax}).  The
 the thread was last executing on.  The content of the of @samp{thread}
 element is interpreted as human-readable auxilliary information.
 
+@node Traceframe Info Format
+@section Traceframe Info Format
+@cindex traceframe info format
+
+To be able to know which objects in the inferior can be examined when
+inspecting a tracepoint hit, @value{GDBN} needs to obtain the list of
+memory ranges, registers and trace state variables that have been
+collected in a traceframe.
+
+This list is obtained using the @samp{qXfer:traceframe-info:read}
+(@pxref{qXfer traceframe info read}) packet and is an XML document.
+
+@value{GDBN} must be linked with the Expat library to support XML
+traceframe info discovery.  @xref{Expat}.
+
+The top-level structure of the document is shown below:
+
+@smallexample
+<?xml version="1.0"?>
+<!DOCTYPE traceframe-info
+          PUBLIC "+//IDN gnu.org//DTD GDB Memory Map V1.0//EN"
+                 "http://sourceware.org/gdb/gdb-traceframe-info.dtd">
+<traceframe-info>
+   block...
+</traceframe-info>
+@end smallexample
+
+Each traceframe block can be either:
+
+@itemize
+
+@item
+A region of collected memory starting at @var{addr} and extending for
+@var{length} bytes from there:
+
+@smallexample
+<memory start="@var{addr}" length="@var{length}"/>
+@end smallexample
+
+@end itemize
+
+The formal DTD for the traceframe info format is given below:
+
+@smallexample
+<!ELEMENT traceframe-info  (memory)* >
+<!ATTLIST traceframe-info  version CDATA   #FIXED  "1.0">
+
+<!ELEMENT memory        EMPTY>
+<!ATTLIST memory        start   CDATA   #REQUIRED
+                        length  CDATA   #REQUIRED>
+@end smallexample
+
 @include agentexpr.texi
 
 @node Trace File Format
index 470b383e216b0c65b81b643235bf8e764a376cb0..682c86f4296c21ff1a50a53e72cbf72111dafe47 100644 (file)
@@ -1,3 +1,18 @@
+2011-02-14  Pedro Alves  <pedro@codesourcery.com>
+
+       * server.c (handle_qxfer_traceframe_info): New.
+       (qxfer_packets): Register "traceframe-info".
+       (handle_query): Report support for qXfer:traceframe-info:read+.
+       * tracepoint.c (match_blocktype): New.
+       (traceframe_find_block_type): Rename to ...
+       (traceframe_walk_blocks): ... this.  Add callback filter argument,
+       and use it.
+       (traceframe_find_block_type): New, reimplemented on top of
+       traceframe_walk_blocks.
+       (build_traceframe_info_xml): New.
+       (traceframe_read_info): New.
+       * server.h (traceframe_read_info): Declare.
+
 2011-02-11  Yao Qi  <yao@codesourcery.com>
 
        * configure.ac: Call AC_PROG_RANLIB.
index 9e1973929029d5bb955225cb1b547a128e8eae3f..ebfcca4e5870279260f7935b472316929de0259c 100644 (file)
@@ -1118,6 +1118,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 +1178,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
@@ -1485,6 +1536,7 @@ 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+");
        }
 
       return;
index c567ccbc9bfe98ef99d1cf4c85b2bbb025187e47..53f4e0d17db018a57f97d5c5a16531d5250f6110 100644 (file)
@@ -575,6 +575,8 @@ int traceframe_read_sdata (int tfnum, ULONGEST offset,
                           unsigned char *buf, ULONGEST length,
                           ULONGEST *nbytes);
 
+int traceframe_read_info (int tfnum, struct buffer *buffer);
+
 /* If a thread is determined to be collecting a fast tracepoint, this
    structure holds the collect status.  */
 
index c5b3f5612653e4f47bd7824d081a99b86c0efc6d..fb5f522ec6690864d8ef2b42d319648d9237c37d 100644 (file)
@@ -4741,9 +4741,34 @@ agent_tsv_read (struct traceframe *tframe, int n)
 
 #ifndef IN_PROCESS_AGENT
 
+/* Callback for traceframe_walk_blocks, used to find a given block
+   type in a traceframe.  */
+
+static int
+match_blocktype (char blocktype, unsigned char *dataptr, void *data)
+{
+  char *wantedp = data;
+
+  if (*wantedp == blocktype)
+    return 1;
+
+  return 0;
+}
+
+/* Walk over all traceframe blocks of the traceframe buffer starting
+   at DATABASE, of DATASIZE bytes long, and call CALLBACK for each
+   block found, passing in DATA unmodified.  If CALLBACK returns true,
+   this returns a pointer to where the block is found.  Returns NULL
+   if no callback call returned true, indicating that all blocks have
+   been walked.  */
+
 static unsigned char *
-traceframe_find_block_type (unsigned char *database, unsigned int datasize,
-                           int tfnum, char type_wanted)
+traceframe_walk_blocks (unsigned char *database, unsigned int datasize,
+                       int tfnum,
+                       int (*callback) (char blocktype,
+                                        unsigned char *dataptr,
+                                        void *data),
+                       void *data)
 {
   unsigned char *dataptr;
 
@@ -4769,9 +4794,10 @@ traceframe_find_block_type (unsigned char *database, unsigned int datasize,
          datasize = dataptr - database;
          dataptr = database = trace_buffer_lo;
        }
+
       blocktype = *dataptr++;
 
-      if (type_wanted == blocktype)
+      if ((*callback) (blocktype, dataptr, data))
        return dataptr;
 
       switch (blocktype)
@@ -4805,6 +4831,18 @@ traceframe_find_block_type (unsigned char *database, unsigned int datasize,
   return NULL;
 }
 
+/* Look for the block of type TYPE_WANTED in the trameframe starting
+   at DATABASE of DATASIZE bytes long.  TFNUM is the traceframe
+   number.  */
+
+static unsigned char *
+traceframe_find_block_type (unsigned char *database, unsigned int datasize,
+                           int tfnum, char type_wanted)
+{
+  return traceframe_walk_blocks (database, datasize, tfnum,
+                                match_blocktype, &type_wanted);
+}
+
 static unsigned char *
 traceframe_find_regblock (struct traceframe *tframe, int tfnum)
 {
@@ -5044,6 +5082,72 @@ traceframe_read_sdata (int tfnum, ULONGEST offset,
   return 0;
 }
 
+/* Callback for traceframe_walk_blocks.  Builds a traceframe-info
+   object.  DATA is pointer to a struct buffer holding the
+   traceframe-info object being built.  */
+
+static int
+build_traceframe_info_xml (char blocktype, unsigned char *dataptr, void *data)
+{
+  struct buffer *buffer = data;
+
+  switch (blocktype)
+    {
+    case 'M':
+      {
+       unsigned short mlen;
+       CORE_ADDR maddr;
+
+       memcpy (&maddr, dataptr, sizeof (maddr));
+       dataptr += sizeof (maddr);
+       memcpy (&mlen, dataptr, sizeof (mlen));
+       dataptr += sizeof (mlen);
+       buffer_xml_printf (buffer,
+                          "<memory start=\"0x%s\" length=\"0x%s\"/>\n",
+                          paddress (maddr), phex_nz (mlen, sizeof (mlen)));
+       break;
+      }
+    case 'V':
+    case 'R':
+    case 'S':
+      {
+       break;
+      }
+    default:
+      warning ("Unhandled trace block type (%d) '%c ' "
+              "while building trace frame info.",
+              blocktype, blocktype);
+      break;
+    }
+
+  return 0;
+}
+
+/* Build a traceframe-info object for traceframe number TFNUM into
+   BUFFER.  */
+
+int
+traceframe_read_info (int tfnum, struct buffer *buffer)
+{
+  struct traceframe *tframe;
+
+  trace_debug ("traceframe_read_info");
+
+  tframe = find_traceframe (tfnum);
+
+  if (!tframe)
+    {
+      trace_debug ("traceframe %d not found", tfnum);
+      return 1;
+    }
+
+  buffer_grow_str (buffer, "<traceframe-info>\n");
+  traceframe_walk_blocks (tframe->data, tframe->data_size,
+                         tfnum, build_traceframe_info_xml, buffer);
+  buffer_grow_str0 (buffer, "</traceframe-info>\n");
+  return 0;
+}
+
 /* Return the first fast tracepoint whose jump pad contains PC.  */
 
 static struct tracepoint *
index c79f6e2eef420afa16280044284755f1288fe694..da04932c9e3a80a33b885a9c0282dc3d581753f8 100644 (file)
@@ -1205,6 +1205,7 @@ enum {
   PACKET_qXfer_osdata,
   PACKET_qXfer_threads,
   PACKET_qXfer_statictrace_read,
+  PACKET_qXfer_traceframe_info,
   PACKET_qGetTIBAddr,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
@@ -3683,6 +3684,8 @@ static struct protocol_feature remote_protocol_features[] = {
     PACKET_qXfer_osdata },
   { "qXfer:threads:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_threads },
+  { "qXfer:traceframe-info:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_traceframe_info },
   { "QPassSignals", PACKET_DISABLE, remote_supported_packet,
     PACKET_QPassSignals },
   { "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet,
@@ -8211,6 +8214,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
       return remote_read_qxfer (ops, "threads", annex, readbuf, offset, len,
                                &remote_protocol_packets[PACKET_qXfer_threads]);
 
+    case TARGET_OBJECT_TRACEFRAME_INFO:
+      gdb_assert (annex == NULL);
+      return remote_read_qxfer
+       (ops, "traceframe-info", annex, readbuf, offset, len,
+        &remote_protocol_packets[PACKET_qXfer_traceframe_info]);
     default:
       return -1;
     }
@@ -10157,6 +10165,26 @@ remote_set_circular_trace_buffer (int val)
     error (_("Bogus reply from target: %s"), reply);
 }
 
+static struct traceframe_info *
+remote_traceframe_info (void)
+{
+  char *text;
+
+  text = target_read_stralloc (&current_target,
+                              TARGET_OBJECT_TRACEFRAME_INFO, NULL);
+  if (text != NULL)
+    {
+      struct traceframe_info *info;
+      struct cleanup *back_to = make_cleanup (xfree, text);
+
+      info = parse_traceframe_info (text);
+      do_cleanups (back_to);
+      return info;
+    }
+
+  return NULL;
+}
+
 static void
 init_remote_ops (void)
 {
@@ -10248,6 +10276,7 @@ Specify the serial device it is connected to\n\
     = remote_static_tracepoint_marker_at;
   remote_ops.to_static_tracepoint_markers_by_strid
     = remote_static_tracepoint_markers_by_strid;
+  remote_ops.to_traceframe_info = remote_traceframe_info;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
@@ -10670,6 +10699,10 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_siginfo_write],
                          "qXfer:siginfo:write", "write-siginfo-object", 0);
 
+  add_packet_config_cmd
+    (&remote_protocol_packets[PACKET_qXfer_traceframe_info],
+     "qXfer:trace-frame-info:read", "traceframe-info", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
                         "qGetTLSAddr", "get-thread-local-storage-address",
                         0);
index ad695a171b33319d2b9f2c07c376c277f2887b5a..edf03f150a2e70f49ccdd134b3a9f7965f5c12a3 100644 (file)
@@ -681,6 +681,7 @@ update_current_target (void)
       INHERIT (to_set_permissions, t);
       INHERIT (to_static_tracepoint_marker_at, t);
       INHERIT (to_static_tracepoint_markers_by_strid, t);
+      INHERIT (to_traceframe_info, t);
       INHERIT (to_magic, t);
       /* Do not inherit to_memory_map.  */
       /* Do not inherit to_flash_erase.  */
@@ -890,6 +891,9 @@ update_current_target (void)
   de_fault (to_static_tracepoint_markers_by_strid,
            (VEC(static_tracepoint_marker_p) * (*) (const char *))
            tcomplain);
+  de_fault (to_traceframe_info,
+           (struct traceframe_info * (*) (void))
+           tcomplain);
 #undef de_fault
 
   /* Finally, position the target-stack beneath the squashed
index 4625d520e52b00fb8580c15d103146e87d23966b..e856dde8de67e33fef7deeab62c8561f1b7f9b56 100644 (file)
@@ -36,7 +36,7 @@ struct trace_status;
 struct uploaded_tsv;
 struct uploaded_tp;
 struct static_tracepoint_marker;
-
+struct traceframe_info;
 struct expression;
 
 /* This include file defines the interface between the main part
@@ -275,6 +275,8 @@ enum target_object
      The size of the data transfered is always 8 bytes (the size of an
      address on ia64).  */
   TARGET_OBJECT_HPUX_SOLIB_GOT,
+  /* Traceframe info, in XML format.  */
+  TARGET_OBJECT_TRACEFRAME_INFO,
   /* Possible future objects: TARGET_OBJECT_FILE, ...  */
 };
 
@@ -736,6 +738,12 @@ struct target_ops
     VEC(static_tracepoint_marker_p) *(*to_static_tracepoint_markers_by_strid)
       (const char *id);
 
+    /* Return a traceframe info object describing the current
+       traceframe's contents.  This method should not cache data;
+       higher layers take care of caching, invalidating, and
+       re-fetching when necessary.  */
+    struct traceframe_info *(*to_traceframe_info) (void);
+
     int to_magic;
     /* Need sub-structure for target machine related rather than comm related?
      */
@@ -1458,6 +1466,9 @@ extern int target_search_memory (CORE_ADDR start_addr,
 #define target_static_tracepoint_markers_by_strid(marker_id) \
   (*current_target.to_static_tracepoint_markers_by_strid) (marker_id)
 
+#define target_traceframe_info() \
+  (*current_target.to_traceframe_info) ()
+
 /* Command logging facility.  */
 
 #define target_log_command(p)                                          \
index ffc31a95503342038abe1745b39b6a9c145eaa44..8117531431026127e5e39b5f461e51a612512522 100644 (file)
@@ -130,6 +130,29 @@ extern void output_command (char *, int);
 typedef struct trace_state_variable tsv_s;
 DEF_VEC_O(tsv_s);
 
+/* Defines a [START, START + LENGTH) memory range.  */
+
+struct mem_range
+{
+  /* Lowest address in the range.  */
+  CORE_ADDR start;
+
+  /* Length of the range.  */
+  int length;
+};
+
+typedef struct mem_range mem_range_s;
+
+DEF_VEC_O(mem_range_s);
+
+/* An object describing the contents of a traceframe.  */
+
+struct traceframe_info
+{
+  /* Collected memory.  */
+  VEC(mem_range_s) *memory;
+};
+
 static VEC(tsv_s) *tvariables;
 
 /* The next integer to assign to a variable.  */
@@ -148,6 +171,12 @@ static struct symbol *traceframe_fun;
 /* Symtab and line for last traceframe collected.  */
 static struct symtab_and_line traceframe_sal;
 
+/* The traceframe info of the current traceframe.  NULL if we haven't
+   yet attempted to fetch it, or if the target does not support
+   fetching this object, or if we're not inspecting a traceframe
+   presently.  */
+static struct traceframe_info *traceframe_info;
+
 /* Tracing command lists.  */
 static struct cmd_list_element *tfindlist;
 
@@ -208,6 +237,29 @@ current_trace_status ()
   return &trace_status;
 }
 
+/* Destroy INFO.  */
+
+static void
+free_traceframe_info (struct traceframe_info *info)
+{
+  if (info != NULL)
+    {
+      VEC_free (mem_range_s, info->memory);
+
+      xfree (info);
+    }
+}
+
+/* Free and and clear the traceframe info cache of the current
+   traceframe.  */
+
+static void
+clear_traceframe_info (void)
+{
+  free_traceframe_info (traceframe_info);
+  traceframe_info = NULL;
+}
+
 /* Set traceframe number to NUM.  */
 static void
 set_traceframe_num (int num)
@@ -1597,6 +1649,7 @@ start_tracing (void)
   set_tracepoint_num (-1);
   set_traceframe_context (NULL);
   current_trace_status()->running = 1;
+  clear_traceframe_info ();
 }
 
 /* tstart command:
@@ -1964,6 +2017,7 @@ tfind_1 (enum trace_find_type type, int num,
   registers_changed ();
   target_dcache_invalidate ();
   set_traceframe_num (target_frameno);
+  clear_traceframe_info ();
   set_tracepoint_num (tp ? tp->number : target_tracept);
   if (target_frameno == -1)
     set_traceframe_context (NULL);
@@ -2915,6 +2969,8 @@ set_traceframe_number (int num)
   /* Changing the traceframe changes our view of registers and of the
      frame chain.  */
   registers_changed ();
+
+  clear_traceframe_info ();
 }
 
 /* A cleanup used when switching away and back from tfind mode.  */
@@ -4108,6 +4164,56 @@ tfile_has_registers (struct target_ops *ops)
   return traceframe_number != -1;
 }
 
+/* Callback for traceframe_walk_blocks.  Builds a traceframe_info
+   object for the tfile target's current traceframe.  */
+
+static int
+build_traceframe_info (char blocktype, void *data)
+{
+  struct traceframe_info *info = data;
+
+  switch (blocktype)
+    {
+    case 'M':
+      {
+       struct mem_range *r;
+       ULONGEST maddr;
+       unsigned short mlen;
+
+       tfile_read ((gdb_byte *) &maddr, 8);
+       tfile_read ((gdb_byte *) &mlen, 2);
+
+       r = VEC_safe_push (mem_range_s, info->memory, NULL);
+
+       r->start = maddr;
+       r->length = mlen;
+       break;
+      }
+    case 'V':
+    case 'R':
+    case 'S':
+      {
+       break;
+      }
+    default:
+      warning (_("Unhandled trace block type (%d) '%c ' "
+                "while building trace frame info."),
+              blocktype, blocktype);
+      break;
+    }
+
+  return 0;
+}
+
+static struct traceframe_info *
+tfile_traceframe_info (void)
+{
+  struct traceframe_info *info = XCNEW (struct traceframe_info);
+
+  traceframe_walk_blocks (build_traceframe_info, 0, info);
+  return info;
+}
+
 static void
 init_tfile_ops (void)
 {
@@ -4129,6 +4235,7 @@ init_tfile_ops (void)
   tfile_ops.to_has_memory = tfile_has_memory;
   tfile_ops.to_has_stack = tfile_has_stack;
   tfile_ops.to_has_registers = tfile_has_registers;
+  tfile_ops.to_traceframe_info = tfile_traceframe_info;
   tfile_ops.to_magic = OPS_MAGIC;
 }
 
@@ -4380,6 +4487,116 @@ sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var)
     return allocate_value (builtin_type (gdbarch)->builtin_void);
 }
 
+#if !defined(HAVE_LIBEXPAT)
+
+struct traceframe_info *
+parse_traceframe_info (const char *tframe_info)
+{
+  static int have_warned;
+
+  if (!have_warned)
+    {
+      have_warned = 1;
+      warning (_("Can not parse XML trace frame info; XML support "
+                "was disabled at compile time"));
+    }
+
+  return NULL;
+}
+
+#else /* HAVE_LIBEXPAT */
+
+#include "xml-support.h"
+
+/* Handle the start of a <memory> element.  */
+
+static void
+traceframe_info_start_memory (struct gdb_xml_parser *parser,
+                             const struct gdb_xml_element *element,
+                             void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+  struct traceframe_info *info = user_data;
+  struct mem_range *r = VEC_safe_push (mem_range_s, info->memory, NULL);
+  ULONGEST *start_p, *length_p;
+
+  start_p = xml_find_attribute (attributes, "start")->value;
+  length_p = xml_find_attribute (attributes, "length")->value;
+
+  r->start = *start_p;
+  r->length = *length_p;
+}
+
+/* Discard the constructed trace frame info (if an error occurs).  */
+
+static void
+free_result (void *p)
+{
+  struct traceframe_info *result = p;
+
+  free_traceframe_info (result);
+}
+
+/* The allowed elements and attributes for an XML memory map.  */
+
+static const struct gdb_xml_attribute memory_attributes[] = {
+  { "start", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+  { "length", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element traceframe_info_children[] = {
+  { "memory", memory_attributes, NULL,
+    GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+    traceframe_info_start_memory, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element traceframe_info_elements[] = {
+  { "traceframe-info", NULL, traceframe_info_children, GDB_XML_EF_NONE,
+    NULL, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+/* Parse a traceframe-info XML document.  */
+
+struct traceframe_info *
+parse_traceframe_info (const char *tframe_info)
+{
+  struct traceframe_info *result;
+  struct cleanup *back_to;
+
+  result = XCNEW (struct traceframe_info);
+  back_to = make_cleanup (free_result, result);
+
+  if (gdb_xml_parse_quick (_("trace frame info"),
+                          "traceframe-info.dtd", traceframe_info_elements,
+                          tframe_info, result) == 0)
+    {
+      /* Parsed successfully, keep the result.  */
+      discard_cleanups (back_to);
+
+      return result;
+    }
+
+  do_cleanups (back_to);
+  return NULL;
+}
+
+#endif /* HAVE_LIBEXPAT */
+
+/* Returns the traceframe_info object for the current traceframe.
+   This is where we avoid re-fetching the object from the target if we
+   already have it cached.  */
+
+struct traceframe_info *
+get_traceframe_info (void)
+{
+  if (traceframe_info == NULL)
+    traceframe_info = target_traceframe_info ();
+
+  return traceframe_info;
+}
+
 /* module initialization */
 void
 _initialize_tracepoint (void)
index 817491807f65b95544c1660d3042ed2d7fd0bf48..276501e51742fba442f9ccafef117bd4fa1496f2 100644 (file)
@@ -236,4 +236,6 @@ extern void tfind_1 (enum trace_find_type type, int num,
 
 extern void trace_save (const char *filename, int target_does_save);
 
+extern struct traceframe_info *parse_traceframe_info (const char *tframe_info);
+
 #endif /* TRACEPOINT_H */