This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[unavailable values part 1, 02/17] query the target about what has been collected in a traceframe (docs included)


This adds a new qXfer:traceframe-info:read packet and corresponding
TARGET_OBJECT_TRACEFRAME_INFO object, to query the target (remote or
tfile) what exactly has been collected in a traceframe
(memory ranges, registers, TSVs, etc.).  gdbserver bits to implement
the packet are also in the patch below.  Docs changes to 
document the new packet are also included.

Only memory is actually reported and parsed in this patch.  Future
patches may add more bits (tsvs, static trace data, ...).  Following
patches will use this info to know which addresses in inferior
memory are available or unavailable.

-- 
Pedro Alves

2011-02-07  Pedro Alves  <pedro@codesourcery.com>

	gdb/
	* 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.

---
 gdb/Makefile.in                  |    2 
 gdb/doc/gdb.texinfo              |   78 ++++++++++++++
 gdb/features/traceframe-info.dtd |   13 ++
 gdb/gdbserver/server.c           |   52 +++++++++
 gdb/gdbserver/server.h           |    2 
 gdb/gdbserver/tracepoint.c       |  110 +++++++++++++++++++
 gdb/remote.c                     |   33 +++++
 gdb/target.c                     |    4 
 gdb/target.h                     |   13 ++
 gdb/tracepoint.c                 |  217 +++++++++++++++++++++++++++++++++++++++
 gdb/tracepoint.h                 |    2 
 11 files changed, 521 insertions(+), 5 deletions(-)

Index: src/gdb/target.h
===================================================================
--- src.orig/gdb/target.h	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/target.h	2011-02-07 13:16:08.406706005 +0000
@@ -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_AD
 #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: src/gdb/target.c
===================================================================
--- src.orig/gdb/target.c	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/target.c	2011-02-07 13:16:08.406706005 +0000
@@ -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: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/remote.c	2011-02-07 13:16:08.436706001 +0000
@@ -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_pr
     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 *
       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 va
     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 connecte
     = 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
   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: src/gdb/tracepoint.h
===================================================================
--- src.orig/gdb/tracepoint.h	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/tracepoint.h	2011-02-07 13:16:08.436706001 +0000
@@ -236,4 +236,6 @@ extern void tfind_1 (enum trace_find_typ
 
 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 */
Index: src/gdb/tracepoint.c
===================================================================
--- src.orig/gdb/tracepoint.c	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/tracepoint.c	2011-02-07 13:16:08.446706002 +0000
@@ -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
   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 *
   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 *gdbarc
     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: src/gdb/features/traceframe-info.dtd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/features/traceframe-info.dtd	2011-02-07 13:16:49.486706001 +0000
@@ -0,0 +1,13 @@
+<!-- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- traceframe-info: Root element with versioning -->
+<!ELEMENT traceframe-info  (memory)* >
+<!ATTLIST traceframe-info  version CDATA   #FIXED  "1.0">
+
+<!ELEMENT memory        EMPTY>
+<!ATTLIST memory        start   CDATA   #REQUIRED
+                        length  CDATA   #REQUIRED>
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/Makefile.in	2011-02-07 13:16:08.446706002 +0000
@@ -493,7 +493,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: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/gdbserver/server.c	2011-02-07 13:16:08.446706002 +0000
@@ -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_
 	    strcat (own_buf, ";FastTracepoints+");
 	  strcat (own_buf, ";StaticTracepoints+");
 	  strcat (own_buf, ";qXfer:statictrace:read+");
+	  strcat (own_buf, ";qXfer:traceframe-info:read+");
 	}
 
       return;
Index: src/gdb/gdbserver/tracepoint.c
===================================================================
--- src.orig/gdb/gdbserver/tracepoint.c	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/gdbserver/tracepoint.c	2011-02-07 13:16:08.456706003 +0000
@@ -4741,9 +4741,34 @@ agent_tsv_read (struct traceframe *tfram
 
 #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 cha
 	  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 cha
   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, ULONGE
   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: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/gdbserver/server.h	2011-02-07 13:16:08.456706003 +0000
@@ -575,6 +575,8 @@ int traceframe_read_sdata (int tfnum, UL
 			   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: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2011-02-07 13:16:03.496706001 +0000
+++ src/gdb/doc/gdb.texinfo	2011-02-07 13:16:08.466706005 +0000
@@ -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 Descr
 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 w
 * 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 fea
 @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{qX
 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} p
 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
 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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]