mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-12-01 07:50:49 +00:00
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.
This commit is contained in:
parent
4e07d55ffb
commit
b3b9301ef4
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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 *
|
||||
|
33
gdb/remote.c
33
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 (¤t_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);
|
||||
|
@ -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
|
||||
|
13
gdb/target.h
13
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) \
|
||||
|
217
gdb/tracepoint.c
217
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)
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user