summaryrefslogtreecommitdiff
path: root/gdb/gdbserver
diff options
context:
space:
mode:
authorPedro Alves <pedro@codesourcery.com>2011-02-14 11:13:10 +0000
committerPedro Alves <pedro@codesourcery.com>2011-02-14 11:13:10 +0000
commitc6fad41d782803bbb365e9465fba42b0876e1793 (patch)
treee1983919bfa0712d4804558e8bc2e82787803fdf /gdb/gdbserver
parentba02454a11a324b99f309ee4c1534a6af5d702b8 (diff)
downloadgdb-c6fad41d782803bbb365e9465fba42b0876e1793.tar.gz
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/gdbserver')
-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
4 files changed, 176 insertions, 3 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 470b383e216..682c86f4296 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 9e197392902..ebfcca4e587 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 c567ccbc9bf..53f4e0d17db 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 c5b3f561265..fb5f522ec66 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 *