aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2011-02-14 11:13:12 +0000
committerPedro Alves <palves@redhat.com>2011-02-14 11:13:12 +0000
commitb3b9301ef4f284b2f2f3dd276cf63600507fe47a (patch)
tree9bd1640020d2fdb0b3e05644c08fbbf7341e7cfb
parent4e07d55ffbd3d926ab776b2ce3fd13e96d214269 (diff)
downloadfsf-binutils-gdb-b3b9301ef4f284b2f2f3dd276cf63600507fe47a.zip
fsf-binutils-gdb-b3b9301ef4f284b2f2f3dd276cf63600507fe47a.tar.gz
fsf-binutils-gdb-b3b9301ef4f284b2f2f3dd276cf63600507fe47a.tar.bz2
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.
-rw-r--r--gdb/ChangeLog34
-rw-r--r--gdb/Makefile.in2
-rw-r--r--gdb/doc/ChangeLog12
-rw-r--r--gdb/doc/gdb.texinfo78
-rw-r--r--gdb/gdbserver/ChangeLog15
-rw-r--r--gdb/gdbserver/server.c52
-rw-r--r--gdb/gdbserver/server.h2
-rw-r--r--gdb/gdbserver/tracepoint.c110
-rw-r--r--gdb/remote.c33
-rw-r--r--gdb/target.c4
-rw-r--r--gdb/target.h13
-rw-r--r--gdb/tracepoint.c217
-rw-r--r--gdb/tracepoint.h2
13 files changed, 568 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index aa54988..d74fc1e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 5f91e35..f991cb0 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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,
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index d10f912..1dfda73 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -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
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6a3c7de..332fdef 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -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
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 470b383..682c86f 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -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.
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 9e19739..ebfcca4 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -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;
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index c567ccb..53f4e0d 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -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. */
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index c5b3f56..fb5f522 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -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 *
diff --git a/gdb/remote.c b/gdb/remote.c
index c79f6e2..da04932 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -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);
diff --git a/gdb/target.c b/gdb/target.c
index ad695a1..edf03f1 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -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
diff --git a/gdb/target.h b/gdb/target.h
index 4625d52..e856dde 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -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) \
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index ffc31a9..8117531 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -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)
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
index 8174918..276501e 100644
--- a/gdb/tracepoint.h
+++ b/gdb/tracepoint.h
@@ -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 */