diff options
author | Pedro Alves <palves@redhat.com> | 2011-02-14 11:13:12 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2011-02-14 11:13:12 +0000 |
commit | b3b9301ef4f284b2f2f3dd276cf63600507fe47a (patch) | |
tree | 9bd1640020d2fdb0b3e05644c08fbbf7341e7cfb /gdb/tracepoint.c | |
parent | 4e07d55ffbd3d926ab776b2ce3fd13e96d214269 (diff) | |
download | gdb-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.c | 217 |
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) |