From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32499 invoked by alias); 20 Nov 2014 10:47:41 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 32264 invoked by uid 89); 20 Nov 2014 10:47:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mga11.intel.com Received: from mga11.intel.com (HELO mga11.intel.com) (192.55.52.93) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 20 Nov 2014 10:47:28 +0000 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga102.fm.intel.com with ESMTP; 20 Nov 2014 02:47:27 -0800 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by FMSMGA003.fm.intel.com with ESMTP; 20 Nov 2014 02:37:59 -0800 Received: from ulvlx001.iul.intel.com (ulvlx001.iul.intel.com [172.28.207.17]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id sAKAlPY1008474; Thu, 20 Nov 2014 10:47:25 GMT Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id sAKAlPPP010221; Thu, 20 Nov 2014 11:47:25 +0100 Received: (from mmetzger@localhost) by ulvlx001.iul.intel.com with œ id sAKAlOlJ010217; Thu, 20 Nov 2014 11:47:25 +0100 From: Markus Metzger To: palves@redhat.com Cc: gdb-patches@sourceware.org Subject: [PATCH v2 01/13] btrace: add struct btrace_data Date: Thu, 20 Nov 2014 10:47:00 -0000 Message-Id: <1416480444-9943-2-git-send-email-markus.t.metzger@intel.com> In-Reply-To: <1416480444-9943-1-git-send-email-markus.t.metzger@intel.com> References: <1416480444-9943-1-git-send-email-markus.t.metzger@intel.com> X-IsSubscribed: yes X-SW-Source: 2014-11/txt/msg00466.txt.bz2 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. 2014-11-20 Markus Metzger * 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): 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. * 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. --- gdb/Makefile.in | 9 ++- gdb/btrace.c | 154 ++++++++++++++++++++++++++++++++------------- gdb/btrace.h | 6 +- gdb/common/btrace-common.c | 82 ++++++++++++++++++++++++ gdb/common/btrace-common.h | 50 +++++++++++++-- gdb/gdbserver/Makefile.in | 8 ++- gdb/gdbserver/linux-low.c | 37 ++++++++--- gdb/nat/linux-btrace.c | 36 ++++++++--- gdb/nat/linux-btrace.h | 2 +- gdb/remote.c | 4 +- gdb/target-debug.h | 2 + gdb/target-delegates.c | 8 +-- gdb/target.c | 2 +- gdb/target.h | 8 +-- gdb/x86-linux-nat.c | 2 +- 15 files changed, 325 insertions(+), 85 deletions(-) create mode 100644 gdb/common/btrace-common.c diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 1da8af6..344ff94 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -852,7 +852,8 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.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/errors.c common/common-debug.c common/common-exceptions.c \ + common/btrace-common.c LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c @@ -1039,7 +1040,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 TSOBS = inflow.o @@ -2172,6 +2173,10 @@ common-exceptions.o: ${srcdir}/common/common-exceptions.c $(COMPILE) $(srcdir)/common/common-exceptions.c $(POSTCOMPILE) +btrace-common.o: ${srcdir}/common/btrace-common.c + $(COMPILE) $(srcdir)/common/btrace-common.c + $(POSTCOMPILE) + # # gdb/target/ dependencies # diff --git a/gdb/btrace.c b/gdb/btrace.c index b8b5139..470a676 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -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); +} diff --git a/gdb/btrace.h b/gdb/btrace.h index f83a80f..3954581 100644 --- a/gdb/btrace.h +++ b/gdb/btrace.h @@ -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 */ diff --git a/gdb/common/btrace-common.c b/gdb/common/btrace-common.c new file mode 100644 index 0000000..869d0cb --- /dev/null +++ b/gdb/common/btrace-common.c @@ -0,0 +1,82 @@ +/* Copyright (C) 2014 Free Software Foundation, Inc. + + Contributed by Intel Corp. + + 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 . */ + +#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 _("Intel(R) 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.")); +} diff --git a/gdb/common/btrace-common.h b/gdb/common/btrace-common.h index 339e684..27e7a95 100644 --- a/gdb/common/btrace-common.h +++ b/gdb/common/btrace-common.h @@ -26,6 +26,7 @@ inferior. For presentation purposes, the branch trace is represented as a list of sequential control-flow blocks, one such list per thread. */ +#include "common-defs.h" #include "vec.h" /* A branch trace block. @@ -45,13 +46,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 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 +117,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 */ diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 8b0318a..98897d9 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -172,7 +172,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@ @@ -186,7 +187,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@ @@ -581,6 +582,9 @@ linux-waitpid.o: ../nat/linux-waitpid.c mips-linux-watch.o: ../nat/mips-linux-watch.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 diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 01f11b7..dcaa829 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -102,6 +102,7 @@ #ifdef HAVE_LINUX_BTRACE # include "nat/linux-btrace.h" +# include "btrace-common.h" #endif #ifndef HAVE_ELF32_AUXV_T @@ -5968,12 +5969,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) { @@ -5982,20 +5984,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, "\n"); - buffer_grow_str (buffer, "\n"); + switch (btrace.format) + { + case BTRACE_FORMAT_NONE: + buffer_grow_str0 (buffer, "E.No Trace."); + break; + + case BTRACE_FORMAT_BTS: + buffer_grow_str (buffer, "\n"); + buffer_grow_str (buffer, "\n"); - for (i = 0; VEC_iterate (btrace_block_s, btrace, i, block); i++) - buffer_xml_printf (buffer, "\n", - paddress (block->begin), paddress (block->end)); + for (i = 0; + VEC_iterate (btrace_block_s, btrace.variant.bts.blocks, i, block); + i++) + buffer_xml_printf (buffer, "\n", + paddress (block->begin), paddress (block->end)); - buffer_grow_str0 (buffer, "\n"); + buffer_grow_str0 (buffer, "\n"); + break; + + default: + buffer_grow_str0 (buffer, "E.Unknown Trace Format."); - VEC_free (btrace_block_s, btrace); + btrace_data_fini (&btrace); + return -1; + } + btrace_data_fini (&btrace); return 0; } #endif /* HAVE_LINUX_BTRACE */ diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c index 37c85c0..916f6b3 100644 --- a/gdb/nat/linux-btrace.c +++ b/gdb/nat/linux-btrace.c @@ -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) { diff --git a/gdb/nat/linux-btrace.h b/gdb/nat/linux-btrace.h index e4b2604..2a08df7 100644 --- a/gdb/nat/linux-btrace.h +++ b/gdb/nat/linux-btrace.h @@ -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); diff --git a/gdb/remote.c b/gdb/remote.c index 4b9b099..249deaa 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -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; diff --git a/gdb/target-debug.h b/gdb/target-debug.h index 3dd705c..60da35c 100644 --- a/gdb/target-debug.h +++ b/gdb/target-debug.h @@ -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) diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c index 9beb5ff..00956ba 100644 --- a/gdb/target-delegates.c +++ b/gdb/target-delegates.c @@ -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); diff --git a/gdb/target.c b/gdb/target.c index ab5f2b9..891183f 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -3380,7 +3380,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) { diff --git a/gdb/target.h b/gdb/target.h index d363b61..dee587f 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -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 ()); @@ -2226,7 +2224,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); diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c index b2141eb..d9ba33e 100644 --- a/gdb/x86-linux-nat.c +++ b/gdb/x86-linux-nat.c @@ -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) { -- 1.8.3.1