* 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.
This commit is contained in:
Pedro Alves 2011-02-14 11:13:12 +00:00
parent 4e07d55ffb
commit b3b9301ef4
13 changed files with 568 additions and 6 deletions

View 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.

View 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,

View 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

View 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

View 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.

View 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;

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

View 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 *

View 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);

View 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

View 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) \

View 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)

View 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 */