btrace: add struct btrace_data

Add a structure to hold the branch trace data and an enum to describe
the format of that data.  So far, only BTS is supported.  Also added
a NONE format to indicate that no branch trace data is available.

This will make it easier to support different branch trace formats in
the future.

2015-02-09  Markus Metzger  <markus.t.metzger@intel.com>

	* Makefile.in (SFILES): Add common/btrace-common.c.
	(COMMON_OBS): Add common/btrace-common.o.
	(btrace-common.o): Add build rules.
	* btrace.c (parse_xml_btrace): Update parameters.
	(parse_xml_btrace_block): Set format field.
	(btrace_add_pc, btrace_fetch): Use struct btrace_data.
	(do_btrace_data_cleanup, make_cleanup_btrace_data): New.
	(btrace_compute_ftrace): Split into this and...
	(btrace_compute_ftrace_bts): ...this.
	(btrace_stitch_trace): Split into this and...
	(btrace_stitch_bts): ...this.
	* btrace.h (parse_xml_btrace): Update parameters.
	(make_cleanup_btrace_data): New.
	* common/btrace-common.c: New.
	* common/btrace-common.h: Include common-defs.h.
	(btrace_block_s): Update comment.
	(btrace_format): New.
	(btrace_format_string): New.
	(btrace_data_bts): New.
	(btrace_data): New.
	(btrace_data_init, btrace_data_fini, btrace_data_empty): New.
	* remote.c (remote_read_btrace): Update parameters.
	* target.c (target_read_btrace): Update parameters.
	* target.h (target_read_btrace): Update parameters.
	(target_ops)<to_read_btrace>: Update parameters.
	* x86-linux-nat.c (x86_linux_read_btrace): Update parameters.
	* target-delegates.c: Regenerate.
	* target-debug (target_debug_print_struct_btrace_data_p): New.
	* nat/linux-btrace.c (linux_read_btrace): Split into this and...
	(linux_read_bts): ...this.
	* nat/linux-btrace.h (linux_read_btrace): Update parameters.

gdbserver/
	* Makefile.in (SFILES): Add common/btrace-common.c.
	(OBS): Add common/btrace-common.o.
	(btrace-common.o): Add build rules.
	* linux-low: Include btrace-common.h.
	(linux_low_read_btrace): Use struct btrace_data.  Call
	btrace_data_init and btrace_data_fini.
This commit is contained in:
Markus Metzger 2013-11-13 15:31:07 +01:00
parent 989f98793c
commit 734b0e4bda
17 changed files with 367 additions and 84 deletions

View File

@ -1,3 +1,37 @@
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
* Makefile.in (SFILES): Add common/btrace-common.c.
(COMMON_OBS): Add common/btrace-common.o.
(btrace-common.o): Add build rules.
* btrace.c (parse_xml_btrace): Update parameters.
(parse_xml_btrace_block): Set format field.
(btrace_add_pc, btrace_fetch): Use struct btrace_data.
(do_btrace_data_cleanup, make_cleanup_btrace_data): New.
(btrace_compute_ftrace): Split into this and...
(btrace_compute_ftrace_bts): ...this.
(btrace_stitch_trace): Split into this and...
(btrace_stitch_bts): ...this.
* btrace.h (parse_xml_btrace): Update parameters.
(make_cleanup_btrace_data): New.
* common/btrace-common.c: New.
* common/btrace-common.h: Include common-defs.h.
(btrace_block_s): Update comment.
(btrace_format): New.
(btrace_format_string): New.
(btrace_data_bts): New.
(btrace_data): New.
(btrace_data_init, btrace_data_fini, btrace_data_empty): New.
* remote.c (remote_read_btrace): Update parameters.
* target.c (target_read_btrace): Update parameters.
* target.h (target_read_btrace): Update parameters.
(target_ops)<to_read_btrace>: Update parameters.
* x86-linux-nat.c (x86_linux_read_btrace): Update parameters.
* target-delegates.c: Regenerate.
* target-debug (target_debug_print_struct_btrace_data_p): New.
* nat/linux-btrace.c (linux_read_btrace): Split into this and...
(linux_read_bts): ...this.
* nat/linux-btrace.h (linux_read_btrace): Update parameters.
2015-02-06 Doug Evans <dje@google.com>
* remote-m32r-sdi.c: Include symfile.h.

View File

@ -873,6 +873,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
common/format.c common/filestuff.c btrace.c record-btrace.c ctf.c \
target/waitstatus.c common/print-utils.c common/rsp-low.c \
common/errors.c common/common-debug.c common/common-exceptions.c \
common/btrace-common.c \
$(SUBDIR_GCC_COMPILE_SRCS)
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@ -1060,7 +1061,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \
format.o registry.o btrace.o record-btrace.o waitstatus.o \
print-utils.o rsp-low.o errors.o common-debug.o debug.o \
common-exceptions.o \
common-exceptions.o btrace-common.o \
$(SUBDIR_GCC_COMPILE_OBS)
TSOBS = inflow.o
@ -2234,6 +2235,10 @@ mingw-strerror.o: ${srcdir}/common/mingw-strerror.c
$(COMPILE) $(srcdir)/common/mingw-strerror.c
$(POSTCOMPILE)
btrace-common.o: ${srcdir}/common/btrace-common.c
$(COMPILE) $(srcdir)/common/btrace-common.c
$(POSTCOMPILE)
#
# gdb/target/ dependencies
#

View File

@ -585,25 +585,22 @@ ftrace_update_insns (struct btrace_function *bfun, CORE_ADDR pc)
ftrace_debug (bfun, "update insn");
}
/* Compute the function branch trace from a block branch trace BTRACE for
a thread given by BTINFO. */
/* Compute the function branch trace from BTS trace. */
static void
btrace_compute_ftrace (struct btrace_thread_info *btinfo,
VEC (btrace_block_s) *btrace)
btrace_compute_ftrace_bts (struct btrace_thread_info *btinfo,
const struct btrace_data_bts *btrace)
{
struct btrace_function *begin, *end;
struct gdbarch *gdbarch;
unsigned int blk;
int level;
DEBUG ("compute ftrace");
gdbarch = target_gdbarch ();
begin = btinfo->begin;
end = btinfo->end;
level = begin != NULL ? -btinfo->level : INT_MAX;
blk = VEC_length (btrace_block_s, btrace);
blk = VEC_length (btrace_block_s, btrace->blocks);
while (blk != 0)
{
@ -612,7 +609,7 @@ btrace_compute_ftrace (struct btrace_thread_info *btinfo,
blk -= 1;
block = VEC_index (btrace_block_s, btrace, blk);
block = VEC_index (btrace_block_s, btrace->blocks, blk);
pc = block->begin;
for (;;)
@ -675,12 +672,34 @@ btrace_compute_ftrace (struct btrace_thread_info *btinfo,
btinfo->level = -level;
}
/* Compute the function branch trace from a block branch trace BTRACE for
a thread given by BTINFO. */
static void
btrace_compute_ftrace (struct btrace_thread_info *btinfo,
struct btrace_data *btrace)
{
DEBUG ("compute ftrace");
switch (btrace->format)
{
case BTRACE_FORMAT_NONE:
return;
case BTRACE_FORMAT_BTS:
btrace_compute_ftrace_bts (btinfo, &btrace->variant.bts);
return;
}
internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
}
/* Add an entry for the current PC. */
static void
btrace_add_pc (struct thread_info *tp)
{
VEC (btrace_block_s) *btrace;
struct btrace_data btrace;
struct btrace_block *block;
struct regcache *regcache;
struct cleanup *cleanup;
@ -689,14 +708,17 @@ btrace_add_pc (struct thread_info *tp)
regcache = get_thread_regcache (tp->ptid);
pc = regcache_read_pc (regcache);
btrace = NULL;
cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
btrace_data_init (&btrace);
btrace.format = BTRACE_FORMAT_BTS;
btrace.variant.bts.blocks = NULL;
block = VEC_safe_push (btrace_block_s, btrace, NULL);
cleanup = make_cleanup_btrace_data (&btrace);
block = VEC_safe_push (btrace_block_s, btrace.variant.bts.blocks, NULL);
block->begin = pc;
block->end = pc;
btrace_compute_ftrace (&tp->btrace, btrace);
btrace_compute_ftrace (&tp->btrace, &btrace);
do_cleanups (cleanup);
}
@ -760,31 +782,24 @@ btrace_teardown (struct thread_info *tp)
btrace_clear (tp);
}
/* Adjust the block trace in order to stitch old and new trace together.
BTRACE is the new delta trace between the last and the current stop.
BTINFO is the old branch trace until the last stop.
May modify BTRACE as well as the existing trace in BTINFO.
Return 0 on success, -1 otherwise. */
/* Stitch branch trace in BTS format. */
static int
btrace_stitch_trace (VEC (btrace_block_s) **btrace,
const struct btrace_thread_info *btinfo)
btrace_stitch_bts (struct btrace_data_bts *btrace,
const struct btrace_thread_info *btinfo)
{
struct btrace_function *last_bfun;
struct btrace_insn *last_insn;
btrace_block_s *first_new_block;
/* If we don't have trace, there's nothing to do. */
if (VEC_empty (btrace_block_s, *btrace))
return 0;
last_bfun = btinfo->end;
gdb_assert (last_bfun != NULL);
/* Beware that block trace starts with the most recent block, so the
chronologically first block in the new trace is the last block in
the new trace's block vector. */
first_new_block = VEC_last (btrace_block_s, *btrace);
gdb_assert (!VEC_empty (btrace_block_s, btrace->blocks));
first_new_block = VEC_last (btrace_block_s, btrace->blocks);
last_insn = VEC_last (btrace_insn_s, last_bfun->insn);
/* If the current PC at the end of the block is the same as in our current
@ -796,9 +811,9 @@ btrace_stitch_trace (VEC (btrace_block_s) **btrace,
In the second case, the delta trace vector should contain exactly one
entry for the partial block containing the current PC. Remove it. */
if (first_new_block->end == last_insn->pc
&& VEC_length (btrace_block_s, *btrace) == 1)
&& VEC_length (btrace_block_s, btrace->blocks) == 1)
{
VEC_pop (btrace_block_s, *btrace);
VEC_pop (btrace_block_s, btrace->blocks);
return 0;
}
@ -834,6 +849,32 @@ btrace_stitch_trace (VEC (btrace_block_s) **btrace,
return 0;
}
/* Adjust the block trace in order to stitch old and new trace together.
BTRACE is the new delta trace between the last and the current stop.
BTINFO is the old branch trace until the last stop.
May modifx BTRACE as well as the existing trace in BTINFO.
Return 0 on success, -1 otherwise. */
static int
btrace_stitch_trace (struct btrace_data *btrace,
const struct btrace_thread_info *btinfo)
{
/* If we don't have trace, there's nothing to do. */
if (btrace_data_empty (btrace))
return 0;
switch (btrace->format)
{
case BTRACE_FORMAT_NONE:
return 0;
case BTRACE_FORMAT_BTS:
return btrace_stitch_bts (&btrace->variant.bts, btinfo);
}
internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
}
/* Clear the branch trace histories in BTINFO. */
static void
@ -855,13 +896,12 @@ btrace_fetch (struct thread_info *tp)
{
struct btrace_thread_info *btinfo;
struct btrace_target_info *tinfo;
VEC (btrace_block_s) *btrace;
struct btrace_data btrace;
struct cleanup *cleanup;
int errcode;
DEBUG ("fetch thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
btrace = NULL;
btinfo = &tp->btrace;
tinfo = btinfo->target;
if (tinfo == NULL)
@ -873,7 +913,8 @@ btrace_fetch (struct thread_info *tp)
if (btinfo->replay != NULL)
return;
cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
btrace_data_init (&btrace);
cleanup = make_cleanup_btrace_data (&btrace);
/* Let's first try to extend the trace we already have. */
if (btinfo->end != NULL)
@ -890,7 +931,7 @@ btrace_fetch (struct thread_info *tp)
errcode = target_read_btrace (&btrace, tinfo, BTRACE_READ_NEW);
/* If we got any new trace, discard what we have. */
if (errcode == 0 && !VEC_empty (btrace_block_s, btrace))
if (errcode == 0 && !btrace_data_empty (&btrace))
btrace_clear (tp);
}
@ -909,10 +950,10 @@ btrace_fetch (struct thread_info *tp)
error (_("Failed to read branch trace."));
/* Compute the trace, provided we have any. */
if (!VEC_empty (btrace_block_s, btrace))
if (!btrace_data_empty (&btrace))
{
btrace_clear_history (btinfo);
btrace_compute_ftrace (btinfo, btrace);
btrace_compute_ftrace (btinfo, &btrace);
}
do_cleanups (cleanup);
@ -984,16 +1025,30 @@ parse_xml_btrace_block (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC (gdb_xml_value_s) *attributes)
{
VEC (btrace_block_s) **btrace;
struct btrace_data *btrace;
struct btrace_block *block;
ULONGEST *begin, *end;
btrace = user_data;
block = VEC_safe_push (btrace_block_s, *btrace, NULL);
switch (btrace->format)
{
case BTRACE_FORMAT_BTS:
break;
case BTRACE_FORMAT_NONE:
btrace->format = BTRACE_FORMAT_BTS;
btrace->variant.bts.blocks = NULL;
break;
default:
gdb_xml_error (parser, _("Btrace format error."));
}
begin = xml_find_attribute (attributes, "begin")->value;
end = xml_find_attribute (attributes, "end")->value;
block = VEC_safe_push (btrace_block_s, btrace->variant.bts.blocks, NULL);
block->begin = *begin;
block->end = *end;
}
@ -1025,18 +1080,19 @@ static const struct gdb_xml_element btrace_elements[] = {
/* See btrace.h. */
VEC (btrace_block_s) *
parse_xml_btrace (const char *buffer)
void
parse_xml_btrace (struct btrace_data *btrace, const char *buffer)
{
VEC (btrace_block_s) *btrace = NULL;
struct cleanup *cleanup;
int errcode;
#if defined (HAVE_LIBEXPAT)
cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
btrace->format = BTRACE_FORMAT_NONE;
cleanup = make_cleanup_btrace_data (btrace);
errcode = gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements,
buffer, &btrace);
buffer, btrace);
if (errcode != 0)
error (_("Error parsing branch trace."));
@ -1048,8 +1104,6 @@ parse_xml_btrace (const char *buffer)
error (_("Cannot process branch trace. XML parsing is not supported."));
#endif /* !defined (HAVE_LIBEXPAT) */
return btrace;
}
/* See btrace.h. */
@ -1526,3 +1580,19 @@ btrace_is_empty (struct thread_info *tp)
return btrace_insn_cmp (&begin, &end) == 0;
}
/* Forward the cleanup request. */
static void
do_btrace_data_cleanup (void *arg)
{
btrace_data_fini (arg);
}
/* See btrace.h. */
struct cleanup *
make_cleanup_btrace_data (struct btrace_data *data)
{
return make_cleanup (do_btrace_data_cleanup, data);
}

View File

@ -235,8 +235,8 @@ extern void btrace_clear (struct thread_info *);
/* Clear the branch trace for all threads when an object file goes away. */
extern void btrace_free_objfile (struct objfile *);
/* Parse a branch trace xml document into a block vector. */
extern VEC (btrace_block_s) *parse_xml_btrace (const char*);
/* Parse a branch trace xml document XML into DATA. */
extern void parse_xml_btrace (struct btrace_data *data, const char *xml);
/* Dereference a branch trace instruction iterator. Return a pointer to the
instruction the iterator points to. */
@ -339,5 +339,7 @@ extern int btrace_is_replaying (struct thread_info *tp);
/* Return non-zero if the branch trace for TP is empty; zero otherwise. */
extern int btrace_is_empty (struct thread_info *tp);
/* Create a cleanup for DATA. */
extern struct cleanup *make_cleanup_btrace_data (struct btrace_data *data);
#endif /* BTRACE_H */

View File

@ -0,0 +1,83 @@
/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
Contributed by Intel Corp. <markus.t.metzger@intel.com>
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "common-defs.h"
#include "btrace-common.h"
/* See btrace-common.h. */
const char *
btrace_format_string (enum btrace_format format)
{
switch (format)
{
case BTRACE_FORMAT_NONE:
return _("No or unknown format");
case BTRACE_FORMAT_BTS:
return _("Branch Trace Store");
}
internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
}
/* See btrace-common.h. */
void
btrace_data_init (struct btrace_data *data)
{
data->format = BTRACE_FORMAT_NONE;
}
/* See btrace-common.h. */
void
btrace_data_fini (struct btrace_data *data)
{
switch (data->format)
{
case BTRACE_FORMAT_NONE:
/* Nothing to do. */
return;
case BTRACE_FORMAT_BTS:
VEC_free (btrace_block_s, data->variant.bts.blocks);
return;
}
internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
}
/* See btrace-common.h. */
int
btrace_data_empty (struct btrace_data *data)
{
switch (data->format)
{
case BTRACE_FORMAT_NONE:
return 1;
case BTRACE_FORMAT_BTS:
return VEC_empty (btrace_block_s, data->variant.bts.blocks);
}
internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
}

View File

@ -45,13 +45,42 @@ struct btrace_block
CORE_ADDR end;
};
/* Branch trace is represented as a vector of branch trace blocks starting with
the most recent block. */
typedef struct btrace_block btrace_block_s;
/* Define functions operating on a vector of branch trace blocks. */
typedef struct btrace_block btrace_block_s;
DEF_VEC_O (btrace_block_s);
/* Enumeration of btrace formats. */
enum btrace_format
{
/* No branch trace format. */
BTRACE_FORMAT_NONE,
/* Branch trace is in Branch Trace Store (BTS) format.
Actually, the format is a sequence of blocks derived from BTS. */
BTRACE_FORMAT_BTS
};
/* Branch trace in BTS format. */
struct btrace_data_bts
{
/* Branch trace is represented as a vector of branch trace blocks starting
with the most recent block. */
VEC (btrace_block_s) *blocks;
};
/* The branch trace data. */
struct btrace_data
{
enum btrace_format format;
union
{
/* Format == BTRACE_FORMAT_BTS. */
struct btrace_data_bts bts;
} variant;
};
/* Target specific branch trace information. */
struct btrace_target_info;
@ -87,4 +116,16 @@ enum btrace_error
BTRACE_ERR_OVERFLOW
};
/* Return a string representation of FORMAT. */
extern const char *btrace_format_string (enum btrace_format format);
/* Initialize DATA. */
extern void btrace_data_init (struct btrace_data *data);
/* Cleanup DATA. */
extern void btrace_data_fini (struct btrace_data *data);
/* Return non-zero if DATA is empty; zero otherwise. */
extern int btrace_data_empty (struct btrace_data *data);
#endif /* BTRACE_COMMON_H */

View File

@ -1,3 +1,12 @@
2015-02-09 Markus Metzger <markus.t.metzger@intel.com>
* Makefile.in (SFILES): Add common/btrace-common.c.
(OBS): Add common/btrace-common.o.
(btrace-common.o): Add build rules.
* linux-low: Include btrace-common.h.
(linux_low_read_btrace): Use struct btrace_data. Call
btrace_data_init and btrace_data_fini.
2015-02-06 Pedro Alves <palves@redhat.com>
* thread-db.c (find_new_threads_callback): Add debug output.

View File

@ -173,7 +173,8 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/nat/mips-linux-watch.c $(srcdir)/common/print-utils.c \
$(srcdir)/common/rsp-low.c $(srcdir)/common/errors.c \
$(srcdir)/common/common-debug.c $(srcdir)/common/cleanups.c \
$(srcdir)/common/common-exceptions.c $(srcdir)/symbol.c
$(srcdir)/common/common-exceptions.c $(srcdir)/symbol.c \
$(srcdir)/common/btrace-common.c
DEPFILES = @GDBSERVER_DEPFILES@
@ -187,7 +188,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
mem-break.o hostio.o event-loop.o tracepoint.o xml-utils.o \
common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
common-exceptions.o symbol.o \
common-exceptions.o symbol.o btrace-common.o \
$(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
GDBREPLAY_OBS = gdbreplay.o version.o
GDBSERVER_LIBS = @GDBSERVER_LIBS@
@ -594,6 +595,9 @@ ppc-linux.o: ../nat/ppc-linux.c
linux-personality.o: ../nat/linux-personality.c
$(COMPILE) $<
$(POSTCOMPILE)
btrace-common.o: ../common/btrace-common.c
$(COMPILE) $<
$(POSTCOMPILE)
aarch64.c : $(srcdir)/../regformats/aarch64.dat $(regdat_sh)
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/aarch64.dat aarch64.c

View File

@ -103,6 +103,7 @@
#ifdef HAVE_LINUX_BTRACE
# include "nat/linux-btrace.h"
# include "btrace-common.h"
#endif
#ifndef HAVE_ELF32_AUXV_T
@ -5971,12 +5972,13 @@ static int
linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
int type)
{
VEC (btrace_block_s) *btrace;
struct btrace_data btrace;
struct btrace_block *block;
enum btrace_error err;
int i;
btrace = NULL;
btrace_data_init (&btrace);
err = linux_read_btrace (&btrace, tinfo, type);
if (err != BTRACE_ERR_NONE)
{
@ -5985,20 +5987,37 @@ linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
else
buffer_grow_str0 (buffer, "E.Generic Error.");
btrace_data_fini (&btrace);
return -1;
}
buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
switch (btrace.format)
{
case BTRACE_FORMAT_NONE:
buffer_grow_str0 (buffer, "E.No Trace.");
break;
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));
case BTRACE_FORMAT_BTS:
buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
buffer_grow_str0 (buffer, "</btrace>\n");
for (i = 0;
VEC_iterate (btrace_block_s, btrace.variant.bts.blocks, i, block);
i++)
buffer_xml_printf (buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
paddress (block->begin), paddress (block->end));
VEC_free (btrace_block_s, btrace);
buffer_grow_str0 (buffer, "</btrace>\n");
break;
default:
buffer_grow_str0 (buffer, "E.Unknown Trace Format.");
btrace_data_fini (&btrace);
return -1;
}
btrace_data_fini (&btrace);
return 0;
}
#endif /* HAVE_LINUX_BTRACE */

View File

@ -495,12 +495,13 @@ linux_btrace_has_changed (struct btrace_target_info *tinfo)
return header->data_head != tinfo->data_head;
}
/* See linux-btrace.h. */
/* Read branch trace data in BTS format for the thread given by TINFO into
BTRACE using the TYPE reading method. */
enum btrace_error
linux_read_btrace (VEC (btrace_block_s) **btrace,
struct btrace_target_info *tinfo,
enum btrace_read_type type)
static enum btrace_error
linux_read_bts (struct btrace_data_bts *btrace,
struct btrace_target_info *tinfo,
enum btrace_read_type type)
{
volatile struct perf_event_mmap_page *header;
const uint8_t *begin, *end, *start;
@ -522,7 +523,7 @@ linux_read_btrace (VEC (btrace_block_s) **btrace,
data_head = header->data_head;
/* Delete any leftover trace from the previous iteration. */
VEC_free (btrace_block_s, *btrace);
VEC_free (btrace_block_s, btrace->blocks);
if (type == BTRACE_READ_DELTA)
{
@ -559,7 +560,7 @@ linux_read_btrace (VEC (btrace_block_s) **btrace,
else
end = perf_event_buffer_end (tinfo);
*btrace = perf_event_read_bts (tinfo, begin, end, start, size);
btrace->blocks = perf_event_read_bts (tinfo, begin, end, start, size);
/* The stopping thread notifies its ptracer before it is scheduled out.
On multi-core systems, the debugger might therefore run while the
@ -575,12 +576,27 @@ linux_read_btrace (VEC (btrace_block_s) **btrace,
/* Prune the incomplete last block (i.e. the first one of inferior execution)
if we're not doing a delta read. There is no way of filling in its zeroed
BEGIN element. */
if (!VEC_empty (btrace_block_s, *btrace) && type != BTRACE_READ_DELTA)
VEC_pop (btrace_block_s, *btrace);
if (!VEC_empty (btrace_block_s, btrace->blocks)
&& type != BTRACE_READ_DELTA)
VEC_pop (btrace_block_s, btrace->blocks);
return BTRACE_ERR_NONE;
}
/* See linux-btrace.h. */
enum btrace_error
linux_read_btrace (struct btrace_data *btrace,
struct btrace_target_info *tinfo,
enum btrace_read_type type)
{
/* We read btrace in BTS format. */
btrace->format = BTRACE_FORMAT_BTS;
btrace->variant.bts.blocks = NULL;
return linux_read_bts (&btrace->variant.bts, tinfo, type);
}
#else /* !HAVE_LINUX_PERF_EVENT_H */
/* See linux-btrace.h. */
@ -610,7 +626,7 @@ linux_disable_btrace (struct btrace_target_info *tinfo)
/* See linux-btrace.h. */
enum btrace_error
linux_read_btrace (VEC (btrace_block_s) **btrace,
linux_read_btrace (struct btrace_data *btrace,
struct btrace_target_info *tinfo,
enum btrace_read_type type)
{

View File

@ -70,7 +70,7 @@ extern struct btrace_target_info *linux_enable_btrace (ptid_t ptid);
extern enum btrace_error linux_disable_btrace (struct btrace_target_info *ti);
/* See to_read_btrace in target.h. */
extern enum btrace_error linux_read_btrace (VEC (btrace_block_s) **btrace,
extern enum btrace_error linux_read_btrace (struct btrace_data *btrace,
struct btrace_target_info *btinfo,
enum btrace_read_type type);

View File

@ -11419,7 +11419,7 @@ remote_teardown_btrace (struct target_ops *self,
static enum btrace_error
remote_read_btrace (struct target_ops *self,
VEC (btrace_block_s) **btrace,
struct btrace_data *btrace,
struct btrace_target_info *tinfo,
enum btrace_read_type type)
{
@ -11459,7 +11459,7 @@ remote_read_btrace (struct target_ops *self,
return BTRACE_ERR_UNKNOWN;
cleanup = make_cleanup (xfree, xml);
*btrace = parse_xml_btrace (xml);
parse_xml_btrace (btrace, xml);
do_cleanups (cleanup);
return BTRACE_ERR_NONE;

View File

@ -144,6 +144,8 @@
target_debug_do_print (host_address_to_string (X))
#define target_debug_print_const_struct_frame_unwind_p(X) \
target_debug_do_print (host_address_to_string (X))
#define target_debug_print_struct_btrace_data_p(X) \
target_debug_do_print (host_address_to_string (X))
static void
target_debug_print_struct_target_waitstatus_p (struct target_waitstatus *status)

View File

@ -3191,20 +3191,20 @@ debug_teardown_btrace (struct target_ops *self, struct btrace_target_info *arg1)
}
static enum btrace_error
delegate_read_btrace (struct target_ops *self, VEC (btrace_block_s) **arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
delegate_read_btrace (struct target_ops *self, struct btrace_data *arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
{
self = self->beneath;
return self->to_read_btrace (self, arg1, arg2, arg3);
}
static enum btrace_error
tdefault_read_btrace (struct target_ops *self, VEC (btrace_block_s) **arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
tdefault_read_btrace (struct target_ops *self, struct btrace_data *arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
{
tcomplain ();
}
static enum btrace_error
debug_read_btrace (struct target_ops *self, VEC (btrace_block_s) **arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
debug_read_btrace (struct target_ops *self, struct btrace_data *arg1, struct btrace_target_info *arg2, enum btrace_read_type arg3)
{
enum btrace_error result;
fprintf_unfiltered (gdb_stdlog, "-> %s->to_read_btrace (...)\n", debug_target.to_shortname);
@ -3212,7 +3212,7 @@ debug_read_btrace (struct target_ops *self, VEC (btrace_block_s) **arg1, struct
fprintf_unfiltered (gdb_stdlog, "<- %s->to_read_btrace (", debug_target.to_shortname);
target_debug_print_struct_target_ops_p (&debug_target);
fputs_unfiltered (", ", gdb_stdlog);
target_debug_print_VEC__btrace_block_s__pp (arg1);
target_debug_print_struct_btrace_data_p (arg1);
fputs_unfiltered (", ", gdb_stdlog);
target_debug_print_struct_btrace_target_info_p (arg2);
fputs_unfiltered (", ", gdb_stdlog);

View File

@ -3414,7 +3414,7 @@ target_teardown_btrace (struct btrace_target_info *btinfo)
/* See target.h. */
enum btrace_error
target_read_btrace (VEC (btrace_block_s) **btrace,
target_read_btrace (struct btrace_data *btrace,
struct btrace_target_info *btinfo,
enum btrace_read_type type)
{

View File

@ -1022,11 +1022,9 @@ struct target_ops
TARGET_DEFAULT_NORETURN (tcomplain ());
/* Read branch trace data for the thread indicated by BTINFO into DATA.
DATA is cleared before new trace is added.
The branch trace will start with the most recent block and continue
towards older blocks. */
DATA is cleared before new trace is added. */
enum btrace_error (*to_read_btrace) (struct target_ops *self,
VEC (btrace_block_s) **data,
struct btrace_data *data,
struct btrace_target_info *btinfo,
enum btrace_read_type type)
TARGET_DEFAULT_NORETURN (tcomplain ());
@ -2230,7 +2228,7 @@ extern void target_disable_btrace (struct btrace_target_info *btinfo);
extern void target_teardown_btrace (struct btrace_target_info *btinfo);
/* See to_read_btrace in struct target_ops. */
extern enum btrace_error target_read_btrace (VEC (btrace_block_s) **,
extern enum btrace_error target_read_btrace (struct btrace_data *,
struct btrace_target_info *,
enum btrace_read_type);

View File

@ -470,7 +470,7 @@ x86_linux_teardown_btrace (struct target_ops *self,
static enum btrace_error
x86_linux_read_btrace (struct target_ops *self,
VEC (btrace_block_s) **data,
struct btrace_data *data,
struct btrace_target_info *btinfo,
enum btrace_read_type type)
{