aboutsummaryrefslogtreecommitdiff
path: root/gdb/tracepoint.c
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 /gdb/tracepoint.c
parent4e07d55ffbd3d926ab776b2ce3fd13e96d214269 (diff)
downloadgdb-b3b9301ef4f284b2f2f3dd276cf63600507fe47a.zip
gdb-b3b9301ef4f284b2f2f3dd276cf63600507fe47a.tar.gz
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.
Diffstat (limited to 'gdb/tracepoint.c')
-rw-r--r--gdb/tracepoint.c217
1 files changed, 217 insertions, 0 deletions
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)