Add the gdb remote target operations for branch tracing.
We define the following packets: Qbtrace:bts enable branch tracing for the current thread returns "OK" or "Enn" Qbtrace:off disable branch tracing for the current thread returns "OK" or "Enn" qXfer:btrace:read read the full branch trace data for the current thread gdb/ * target.h (enum target_object): Add TARGET_OBJECT_BTRACE. * remote.c: Include btrace.h. (struct btrace_target_info): New struct. (remote_supports_btrace): New function. (send_Qbtrace): New function. (remote_enable_btrace): New function. (remote_disable_btrace): New function. (remote_teardown_btrace): New function. (remote_read_btrace): New function. (init_remote_ops): Add btrace ops. (enum <unnamed>): Add btrace packets. (struct protocol_feature remote_protocol_features[]): Add btrace packets. (_initialize_remote): Add packet configuration for branch tracing. gdbserver/ * target.h (struct target_ops): Add btrace ops. (target_supports_btrace): New macro. (target_enable_btrace): New macro. (target_disable_btrace): New macro. (target_read_btrace): New macro. * gdbthread.h (struct thread_info): Add btrace field. * server.c: Include btrace-common.h. (handle_btrace_general_set): New function. (handle_btrace_enable): New function. (handle_btrace_disable): New function. (handle_general_set): Call handle_btrace_general_set. (handle_qxfer_btrace): New function. (struct qxfer qxfer_packets[]): Add btrace entry. * inferiors.c (remove_thread): Disable btrace. * linux-low: Include linux-btrace.h. (linux_low_enable_btrace): New function. (linux_low_read_btrace): New function. (linux_target_ops): Add btrace ops. * configure.srv (i[34567]86-*-linux*): Add linux-btrace.o. Add srv_linux_btrace=yes. (x86_64-*-linux*): Add linux-btrace.o. Add srv_linux_btrace=yes. * configure.ac: Define HAVE_LINUX_BTRACE. * config.in: Regenerated. * configure: Regenerated.
This commit is contained in:
parent
5cc22e4cf7
commit
9accd112a6
13 changed files with 489 additions and 2 deletions
|
@ -1,3 +1,19 @@
|
|||
2013-03-11 Markus Metzger <markus.t.metzger@intel.com>
|
||||
|
||||
* target.h (enum target_object): Add TARGET_OBJECT_BTRACE.
|
||||
* remote.c: Include btrace.h.
|
||||
(struct btrace_target_info): New struct.
|
||||
(remote_supports_btrace): New function.
|
||||
(send_Qbtrace): New function.
|
||||
(remote_enable_btrace): New function.
|
||||
(remote_disable_btrace): New function.
|
||||
(remote_teardown_btrace): New function.
|
||||
(remote_read_btrace): New function.
|
||||
(init_remote_ops): Add btrace ops.
|
||||
(enum <unnamed>): Add btrace packets.
|
||||
(struct protocol_feature remote_protocol_features[]): Add btrace packets.
|
||||
(_initialize_remote): Add packet configuration for branch tracing.
|
||||
|
||||
2013-03-11 Markus Metzger <markus.t.metzger@intel.com>
|
||||
|
||||
* features/btrace.dtd: New file.
|
||||
|
|
|
@ -1,3 +1,31 @@
|
|||
2013-03-11 Markus Metzger <markus.t.metzger@intel.com>
|
||||
|
||||
* target.h (struct target_ops): Add btrace ops.
|
||||
(target_supports_btrace): New macro.
|
||||
(target_enable_btrace): New macro.
|
||||
(target_disable_btrace): New macro.
|
||||
(target_read_btrace): New macro.
|
||||
* gdbthread.h (struct thread_info): Add btrace field.
|
||||
* server.c: Include btrace-common.h.
|
||||
(handle_btrace_general_set): New function.
|
||||
(handle_btrace_enable): New function.
|
||||
(handle_btrace_disable): New function.
|
||||
(handle_general_set): Call handle_btrace_general_set.
|
||||
(handle_qxfer_btrace): New function.
|
||||
(struct qxfer qxfer_packets[]): Add btrace entry.
|
||||
* inferiors.c (remove_thread): Disable btrace.
|
||||
* linux-low: Include linux-btrace.h.
|
||||
(linux_low_enable_btrace): New function.
|
||||
(linux_low_read_btrace): New function.
|
||||
(linux_target_ops): Add btrace ops.
|
||||
* configure.srv (i[34567]86-*-linux*): Add linux-btrace.o.
|
||||
Add srv_linux_btrace=yes.
|
||||
(x86_64-*-linux*): Add linux-btrace.o.
|
||||
Add srv_linux_btrace=yes.
|
||||
* configure.ac: Define HAVE_LINUX_BTRACE.
|
||||
* config.in: Regenerated.
|
||||
* configure: Regenerated.
|
||||
|
||||
2013-03-11 Markus Metzger <markus.t.metzger@intel.com>
|
||||
|
||||
* server.c (handle_qxfer): Preserve error message if -3 is
|
||||
|
|
|
@ -73,6 +73,9 @@
|
|||
/* Define to 1 if you have the `dl' library (-ldl). */
|
||||
#undef HAVE_LIBDL
|
||||
|
||||
/* Define if the target supports branch tracing. */
|
||||
#undef HAVE_LINUX_BTRACE
|
||||
|
||||
/* Define to 1 if you have the <linux/elf.h> header file. */
|
||||
#undef HAVE_LINUX_ELF_H
|
||||
|
||||
|
|
6
gdb/gdbserver/configure
vendored
6
gdb/gdbserver/configure
vendored
|
@ -5344,6 +5344,12 @@ $as_echo "#define HAVE_PTRACE_GETFPXREGS 1" >>confdefs.h
|
|||
fi
|
||||
fi
|
||||
|
||||
if test "${srv_linux_btrace}" = "yes"; then
|
||||
|
||||
$as_echo "#define HAVE_LINUX_BTRACE 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
if test "$ac_cv_header_sys_procfs_h" = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for lwpid_t in sys/procfs.h" >&5
|
||||
$as_echo_n "checking for lwpid_t in sys/procfs.h... " >&6; }
|
||||
|
|
|
@ -292,6 +292,11 @@ if test "${srv_linux_regsets}" = "yes"; then
|
|||
fi
|
||||
fi
|
||||
|
||||
if test "${srv_linux_btrace}" = "yes"; then
|
||||
AC_DEFINE(HAVE_LINUX_BTRACE, 1,
|
||||
[Define if the target supports branch tracing.])
|
||||
fi
|
||||
|
||||
if test "$ac_cv_header_sys_procfs_h" = yes; then
|
||||
BFD_HAVE_SYS_PROCFS_TYPE(lwpid_t)
|
||||
BFD_HAVE_SYS_PROCFS_TYPE(psaddr_t)
|
||||
|
|
|
@ -112,10 +112,11 @@ case "${target}" in
|
|||
srv_xmlfiles="${srv_xmlfiles} $srv_amd64_linux_xmlfiles"
|
||||
fi
|
||||
srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
|
||||
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
|
||||
srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
|
||||
srv_linux_usrregs=yes
|
||||
srv_linux_regsets=yes
|
||||
srv_linux_thread_db=yes
|
||||
srv_linux_btrace=yes
|
||||
ipa_obj="${ipa_i386_linux_regobj} linux-i386-ipa.o"
|
||||
;;
|
||||
i[34567]86-*-lynxos*) srv_regobj="i386.o"
|
||||
|
@ -314,11 +315,12 @@ case "${target}" in
|
|||
;;
|
||||
x86_64-*-linux*) srv_regobj="$srv_amd64_linux_regobj $srv_i386_linux_regobj"
|
||||
srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
|
||||
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
|
||||
srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
|
||||
srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles"
|
||||
srv_linux_usrregs=yes # This is for i386 progs.
|
||||
srv_linux_regsets=yes
|
||||
srv_linux_thread_db=yes
|
||||
srv_linux_btrace=yes
|
||||
ipa_obj="${ipa_amd64_linux_regobj} linux-amd64-ipa.o"
|
||||
;;
|
||||
x86_64-*-mingw*) srv_regobj="$srv_amd64_regobj"
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "server.h"
|
||||
|
||||
struct btrace_target_info;
|
||||
|
||||
struct thread_info
|
||||
{
|
||||
struct inferior_list_entry entry;
|
||||
|
@ -57,6 +59,9 @@ struct thread_info
|
|||
Each item in the list holds the current step of the while-stepping
|
||||
action. */
|
||||
struct wstep_state *while_stepping;
|
||||
|
||||
/* Branch trace target information for this thread. */
|
||||
struct btrace_target_info *btrace;
|
||||
};
|
||||
|
||||
extern struct inferior_list all_threads;
|
||||
|
|
|
@ -161,6 +161,9 @@ free_one_thread (struct inferior_list_entry *inf)
|
|||
void
|
||||
remove_thread (struct thread_info *thread)
|
||||
{
|
||||
if (thread->btrace != NULL)
|
||||
target_disable_btrace (thread->btrace);
|
||||
|
||||
remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
|
||||
free_one_thread (&thread->entry);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,10 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LINUX_BTRACE
|
||||
# include "linux-btrace.h"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ELF32_AUXV_T
|
||||
/* Copied from glibc's elf.h. */
|
||||
typedef struct
|
||||
|
@ -5821,6 +5825,47 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
|
|||
return len;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_BTRACE
|
||||
|
||||
/* Enable branch tracing. */
|
||||
|
||||
static struct btrace_target_info *
|
||||
linux_low_enable_btrace (ptid_t ptid)
|
||||
{
|
||||
struct btrace_target_info *tinfo;
|
||||
|
||||
tinfo = linux_enable_btrace (ptid);
|
||||
if (tinfo != NULL)
|
||||
tinfo->ptr_bits = register_size (0) * 8;
|
||||
|
||||
return tinfo;
|
||||
}
|
||||
|
||||
/* Read branch trace data as btrace xml document. */
|
||||
|
||||
static void
|
||||
linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
|
||||
int type)
|
||||
{
|
||||
VEC (btrace_block_s) *btrace;
|
||||
struct btrace_block *block;
|
||||
int i;
|
||||
|
||||
btrace = linux_read_btrace (tinfo, type);
|
||||
|
||||
buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
|
||||
buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
|
||||
|
||||
for (i = 0; VEC_iterate (btrace_block_s, btrace, i, block); i++)
|
||||
buffer_xml_printf (buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
|
||||
paddress (block->begin), paddress (block->end));
|
||||
|
||||
buffer_grow_str (buffer, "</btrace>\n");
|
||||
|
||||
VEC_free (btrace_block_s, btrace);
|
||||
}
|
||||
#endif /* HAVE_LINUX_BTRACE */
|
||||
|
||||
static struct target_ops linux_target_ops = {
|
||||
linux_create_inferior,
|
||||
linux_attach,
|
||||
|
@ -5885,6 +5930,18 @@ static struct target_ops linux_target_ops = {
|
|||
linux_get_min_fast_tracepoint_insn_len,
|
||||
linux_qxfer_libraries_svr4,
|
||||
linux_supports_agent,
|
||||
#ifdef HAVE_LINUX_BTRACE
|
||||
linux_supports_btrace,
|
||||
linux_low_enable_btrace,
|
||||
linux_disable_btrace,
|
||||
linux_low_read_btrace,
|
||||
#else
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <signal.h>
|
||||
#endif
|
||||
#include "gdb_wait.h"
|
||||
#include "btrace-common.h"
|
||||
|
||||
/* The thread set with an `Hc' packet. `Hc' is deprecated in favor of
|
||||
`vCont'. Note the multi-process extensions made `vCont' a
|
||||
|
@ -396,6 +397,88 @@ write_qxfer_response (char *buf, const void *data, int len, int is_more)
|
|||
PBUFSIZ - 2) + 1;
|
||||
}
|
||||
|
||||
/* Handle btrace enabling. */
|
||||
|
||||
static const char *
|
||||
handle_btrace_enable (struct thread_info *thread)
|
||||
{
|
||||
if (thread->btrace != NULL)
|
||||
return "E.Btrace already enabled.";
|
||||
|
||||
thread->btrace = target_enable_btrace (thread->entry.id);
|
||||
if (thread->btrace == NULL)
|
||||
return "E.Could not enable btrace.";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle btrace disabling. */
|
||||
|
||||
static const char *
|
||||
handle_btrace_disable (struct thread_info *thread)
|
||||
{
|
||||
|
||||
if (thread->btrace == NULL)
|
||||
return "E.Branch tracing not enabled.";
|
||||
|
||||
if (target_disable_btrace (thread->btrace) != 0)
|
||||
return "E.Could not disable branch tracing.";
|
||||
|
||||
thread->btrace = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle the "Qbtrace" packet. */
|
||||
|
||||
static int
|
||||
handle_btrace_general_set (char *own_buf)
|
||||
{
|
||||
struct thread_info *thread;
|
||||
const char *err;
|
||||
char *op;
|
||||
|
||||
if (strncmp ("Qbtrace:", own_buf, strlen ("Qbtrace:")) != 0)
|
||||
return 0;
|
||||
|
||||
op = own_buf + strlen ("Qbtrace:");
|
||||
|
||||
if (!target_supports_btrace ())
|
||||
{
|
||||
strcpy (own_buf, "E.Target does not support branch tracing.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ptid_equal (general_thread, null_ptid)
|
||||
|| ptid_equal (general_thread, minus_one_ptid))
|
||||
{
|
||||
strcpy (own_buf, "E.Must select a single thread.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
thread = find_thread_ptid (general_thread);
|
||||
if (thread == NULL)
|
||||
{
|
||||
strcpy (own_buf, "E.No such thread.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = NULL;
|
||||
|
||||
if (strcmp (op, "bts") == 0)
|
||||
err = handle_btrace_enable (thread);
|
||||
else if (strcmp (op, "off") == 0)
|
||||
err = handle_btrace_disable (thread);
|
||||
else
|
||||
err = "E.Bad Qbtrace operation. Use bts or off.";
|
||||
|
||||
if (err != 0)
|
||||
strcpy (own_buf, err);
|
||||
else
|
||||
write_ok (own_buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle all of the extended 'Q' packets. */
|
||||
|
||||
static void
|
||||
|
@ -552,6 +635,9 @@ handle_general_set (char *own_buf)
|
|||
return;
|
||||
}
|
||||
|
||||
if (handle_btrace_general_set (own_buf))
|
||||
return;
|
||||
|
||||
/* Otherwise we didn't know what packet it was. Say we didn't
|
||||
understand it. */
|
||||
own_buf[0] = 0;
|
||||
|
@ -1251,9 +1337,77 @@ handle_qxfer_fdpic (const char *annex, gdb_byte *readbuf,
|
|||
return (*the_target->read_loadmap) (annex, offset, readbuf, len);
|
||||
}
|
||||
|
||||
/* Handle qXfer:btrace:read. */
|
||||
|
||||
static int
|
||||
handle_qxfer_btrace (const char *annex,
|
||||
gdb_byte *readbuf, const gdb_byte *writebuf,
|
||||
ULONGEST offset, LONGEST len)
|
||||
{
|
||||
static struct buffer cache;
|
||||
struct thread_info *thread;
|
||||
int type;
|
||||
|
||||
if (the_target->read_btrace == NULL || writebuf != NULL)
|
||||
return -2;
|
||||
|
||||
if (!target_running ())
|
||||
return -1;
|
||||
|
||||
if (ptid_equal (general_thread, null_ptid)
|
||||
|| ptid_equal (general_thread, minus_one_ptid))
|
||||
{
|
||||
strcpy (own_buf, "E.Must select a single thread.");
|
||||
return -3;
|
||||
}
|
||||
|
||||
thread = find_thread_ptid (general_thread);
|
||||
if (thread == NULL)
|
||||
{
|
||||
strcpy (own_buf, "E.No such thread.");
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (thread->btrace == NULL)
|
||||
{
|
||||
strcpy (own_buf, "E.Btrace not enabled.");
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (strcmp (annex, "all") == 0)
|
||||
type = btrace_read_all;
|
||||
else if (strcmp (annex, "new") == 0)
|
||||
type = btrace_read_new;
|
||||
else
|
||||
{
|
||||
strcpy (own_buf, "E.Bad annex.");
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
buffer_free (&cache);
|
||||
|
||||
target_read_btrace (thread->btrace, &cache, type);
|
||||
}
|
||||
else if (offset > cache.used_size)
|
||||
{
|
||||
buffer_free (&cache);
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (len > cache.used_size - offset)
|
||||
len = cache.used_size - offset;
|
||||
|
||||
memcpy (readbuf, cache.buffer + offset, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct qxfer qxfer_packets[] =
|
||||
{
|
||||
{ "auxv", handle_qxfer_auxv },
|
||||
{ "btrace", handle_qxfer_btrace },
|
||||
{ "fdpic", handle_qxfer_fdpic},
|
||||
{ "features", handle_qxfer_features },
|
||||
{ "libraries", handle_qxfer_libraries },
|
||||
|
@ -1656,6 +1810,13 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
|||
if (target_supports_agent ())
|
||||
strcat (own_buf, ";QAgent+");
|
||||
|
||||
if (target_supports_btrace ())
|
||||
{
|
||||
strcat (own_buf, ";Qbtrace:bts+");
|
||||
strcat (own_buf, ";Qbtrace:off+");
|
||||
strcat (own_buf, ";qXfer:btrace:read+");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#define TARGET_H
|
||||
|
||||
struct emit_ops;
|
||||
struct btrace_target_info;
|
||||
struct buffer;
|
||||
|
||||
/* Ways to "resume" a thread. */
|
||||
|
||||
|
@ -397,6 +399,21 @@ struct target_ops
|
|||
|
||||
/* Return true if target supports debugging agent. */
|
||||
int (*supports_agent) (void);
|
||||
|
||||
/* Check whether the target supports branch tracing. */
|
||||
int (*supports_btrace) (void);
|
||||
|
||||
/* Enable branch tracing for @ptid and allocate a branch trace target
|
||||
information struct for reading and for disabling branch trace. */
|
||||
struct btrace_target_info *(*enable_btrace) (ptid_t ptid);
|
||||
|
||||
/* Disable branch tracing. */
|
||||
int (*disable_btrace) (struct btrace_target_info *tinfo);
|
||||
|
||||
/* Read branch trace data into buffer. We use an int to specify the type
|
||||
to break a cyclic dependency. */
|
||||
void (*read_btrace) (struct btrace_target_info *, struct buffer *, int type);
|
||||
|
||||
};
|
||||
|
||||
extern struct target_ops *the_target;
|
||||
|
@ -520,6 +537,18 @@ int kill_inferior (int);
|
|||
(the_target->supports_agent ? \
|
||||
(*the_target->supports_agent) () : 0)
|
||||
|
||||
#define target_supports_btrace() \
|
||||
(the_target->supports_btrace ? (*the_target->supports_btrace) () : 0)
|
||||
|
||||
#define target_enable_btrace(ptid) \
|
||||
(*the_target->enable_btrace) (ptid)
|
||||
|
||||
#define target_disable_btrace(tinfo) \
|
||||
(*the_target->disable_btrace) (tinfo)
|
||||
|
||||
#define target_read_btrace(tinfo, buffer, type) \
|
||||
(*the_target->read_btrace) (tinfo, buffer, type)
|
||||
|
||||
/* Start non-stop mode, returns 0 on success, -1 on failure. */
|
||||
|
||||
int start_non_stop (int nonstop);
|
||||
|
|
170
gdb/remote.c
170
gdb/remote.c
|
@ -68,6 +68,7 @@
|
|||
#include "ax.h"
|
||||
#include "ax-gdb.h"
|
||||
#include "agent.h"
|
||||
#include "btrace.h"
|
||||
|
||||
/* Temp hacks for tracepoint encoding migration. */
|
||||
static char *target_buf;
|
||||
|
@ -1281,6 +1282,9 @@ enum {
|
|||
PACKET_QDisableRandomization,
|
||||
PACKET_QAgent,
|
||||
PACKET_QTBuffer_size,
|
||||
PACKET_Qbtrace_off,
|
||||
PACKET_Qbtrace_bts,
|
||||
PACKET_qXfer_btrace,
|
||||
PACKET_MAX
|
||||
};
|
||||
|
||||
|
@ -3994,6 +3998,10 @@ static struct protocol_feature remote_protocol_features[] = {
|
|||
remote_supported_packet, PACKET_QTBuffer_size},
|
||||
{ "tracenz", PACKET_DISABLE,
|
||||
remote_string_tracing_feature, -1 },
|
||||
{ "Qbtrace:off", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_off },
|
||||
{ "Qbtrace:bts", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_bts },
|
||||
{ "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
|
||||
PACKET_qXfer_btrace }
|
||||
};
|
||||
|
||||
static char *remote_support_xml;
|
||||
|
@ -8795,6 +8803,10 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
|
|||
return remote_read_qxfer (ops, "uib", annex, readbuf, offset, len,
|
||||
&remote_protocol_packets[PACKET_qXfer_uib]);
|
||||
|
||||
case TARGET_OBJECT_BTRACE:
|
||||
return remote_read_qxfer (ops, "btrace", annex, readbuf, offset, len,
|
||||
&remote_protocol_packets[PACKET_qXfer_btrace]);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -11146,6 +11158,150 @@ remote_can_use_agent (void)
|
|||
return (remote_protocol_packets[PACKET_QAgent].support != PACKET_DISABLE);
|
||||
}
|
||||
|
||||
struct btrace_target_info
|
||||
{
|
||||
/* The ptid of the traced thread. */
|
||||
ptid_t ptid;
|
||||
};
|
||||
|
||||
/* Check whether the target supports branch tracing. */
|
||||
|
||||
static int
|
||||
remote_supports_btrace (void)
|
||||
{
|
||||
if (remote_protocol_packets[PACKET_Qbtrace_off].support != PACKET_ENABLE)
|
||||
return 0;
|
||||
if (remote_protocol_packets[PACKET_Qbtrace_bts].support != PACKET_ENABLE)
|
||||
return 0;
|
||||
if (remote_protocol_packets[PACKET_qXfer_btrace].support != PACKET_ENABLE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Enable branch tracing. */
|
||||
|
||||
static struct btrace_target_info *
|
||||
remote_enable_btrace (ptid_t ptid)
|
||||
{
|
||||
struct btrace_target_info *tinfo = NULL;
|
||||
struct packet_config *packet = &remote_protocol_packets[PACKET_Qbtrace_bts];
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
char *buf = rs->buf;
|
||||
char *endbuf = rs->buf + get_remote_packet_size ();
|
||||
|
||||
if (packet->support != PACKET_ENABLE)
|
||||
error (_("Target does not support branch tracing."));
|
||||
|
||||
set_general_thread (ptid);
|
||||
|
||||
buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
|
||||
putpkt (rs->buf);
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
|
||||
if (packet_ok (rs->buf, packet) == PACKET_ERROR)
|
||||
{
|
||||
if (rs->buf[0] == 'E' && rs->buf[1] == '.')
|
||||
error (_("Could not enable branch tracing for %s: %s"),
|
||||
target_pid_to_str (ptid), rs->buf + 2);
|
||||
else
|
||||
error (_("Could not enable branch tracing for %s."),
|
||||
target_pid_to_str (ptid));
|
||||
}
|
||||
|
||||
tinfo = xzalloc (sizeof (*tinfo));
|
||||
tinfo->ptid = ptid;
|
||||
|
||||
return tinfo;
|
||||
}
|
||||
|
||||
/* Disable branch tracing. */
|
||||
|
||||
static void
|
||||
remote_disable_btrace (struct btrace_target_info *tinfo)
|
||||
{
|
||||
struct packet_config *packet = &remote_protocol_packets[PACKET_Qbtrace_off];
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
char *buf = rs->buf;
|
||||
char *endbuf = rs->buf + get_remote_packet_size ();
|
||||
|
||||
if (packet->support != PACKET_ENABLE)
|
||||
error (_("Target does not support branch tracing."));
|
||||
|
||||
set_general_thread (tinfo->ptid);
|
||||
|
||||
buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
|
||||
putpkt (rs->buf);
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
|
||||
if (packet_ok (rs->buf, packet) == PACKET_ERROR)
|
||||
{
|
||||
if (rs->buf[0] == 'E' && rs->buf[1] == '.')
|
||||
error (_("Could not disable branch tracing for %s: %s"),
|
||||
target_pid_to_str (tinfo->ptid), rs->buf + 2);
|
||||
else
|
||||
error (_("Could not disable branch tracing for %s."),
|
||||
target_pid_to_str (tinfo->ptid));
|
||||
}
|
||||
|
||||
xfree (tinfo);
|
||||
}
|
||||
|
||||
/* Teardown branch tracing. */
|
||||
|
||||
static void
|
||||
remote_teardown_btrace (struct btrace_target_info *tinfo)
|
||||
{
|
||||
/* We must not talk to the target during teardown. */
|
||||
xfree (tinfo);
|
||||
}
|
||||
|
||||
/* Read the branch trace. */
|
||||
|
||||
static VEC (btrace_block_s) *
|
||||
remote_read_btrace (struct btrace_target_info *tinfo,
|
||||
enum btrace_read_type type)
|
||||
{
|
||||
struct packet_config *packet = &remote_protocol_packets[PACKET_qXfer_btrace];
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
VEC (btrace_block_s) *btrace = NULL;
|
||||
const char *annex;
|
||||
char *xml;
|
||||
|
||||
if (packet->support != PACKET_ENABLE)
|
||||
error (_("Target does not support branch tracing."));
|
||||
|
||||
#if !defined(HAVE_LIBEXPAT)
|
||||
error (_("Cannot process branch tracing result. XML parsing not supported."));
|
||||
#endif
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case btrace_read_all:
|
||||
annex = "all";
|
||||
break;
|
||||
case btrace_read_new:
|
||||
annex = "new";
|
||||
break;
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("Bad branch tracing read type: %u."),
|
||||
(unsigned int) type);
|
||||
}
|
||||
|
||||
xml = target_read_stralloc (¤t_target,
|
||||
TARGET_OBJECT_BTRACE, annex);
|
||||
if (xml != NULL)
|
||||
{
|
||||
struct cleanup *cleanup = make_cleanup (xfree, xml);
|
||||
|
||||
btrace = parse_xml_btrace (xml);
|
||||
do_cleanups (cleanup);
|
||||
}
|
||||
|
||||
return btrace;
|
||||
}
|
||||
|
||||
static void
|
||||
init_remote_ops (void)
|
||||
{
|
||||
|
@ -11263,6 +11419,11 @@ Specify the serial device it is connected to\n\
|
|||
remote_ops.to_traceframe_info = remote_traceframe_info;
|
||||
remote_ops.to_use_agent = remote_use_agent;
|
||||
remote_ops.to_can_use_agent = remote_can_use_agent;
|
||||
remote_ops.to_supports_btrace = remote_supports_btrace;
|
||||
remote_ops.to_enable_btrace = remote_enable_btrace;
|
||||
remote_ops.to_disable_btrace = remote_disable_btrace;
|
||||
remote_ops.to_teardown_btrace = remote_teardown_btrace;
|
||||
remote_ops.to_read_btrace = remote_read_btrace;
|
||||
}
|
||||
|
||||
/* Set up the extended remote vector by making a copy of the standard
|
||||
|
@ -11790,6 +11951,15 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
|
|||
add_packet_config_cmd (&remote_protocol_packets[PACKET_QTBuffer_size],
|
||||
"QTBuffer:size", "trace-buffer-size", 0);
|
||||
|
||||
add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_off],
|
||||
"Qbtrace:off", "disable-btrace", 0);
|
||||
|
||||
add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_bts],
|
||||
"Qbtrace:bts", "enable-btrace", 0);
|
||||
|
||||
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_btrace],
|
||||
"qXfer:btrace", "read-btrace", 0);
|
||||
|
||||
/* Keep the old ``set remote Z-packet ...'' working. Each individual
|
||||
Z sub-packet has its own set and show commands, but users may
|
||||
have sets to this variable in their .gdbinit files (or in their
|
||||
|
|
|
@ -288,6 +288,8 @@ enum target_object
|
|||
TARGET_OBJECT_DARWIN_DYLD_INFO,
|
||||
/* OpenVMS Unwind Information Block. */
|
||||
TARGET_OBJECT_OPENVMS_UIB,
|
||||
/* Branch trace data, in XML format. */
|
||||
TARGET_OBJECT_BTRACE
|
||||
/* Possible future objects: TARGET_OBJECT_FILE, ... */
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue