From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14170 invoked by alias); 17 Dec 2012 16:02:29 -0000 Received: (qmail 13875 invoked by uid 22791); 17 Dec 2012 16:02:21 -0000 X-SWARE-Spam-Status: No, hits=-7.8 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,TW_BT,TW_EG,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mga11.intel.com (HELO mga11.intel.com) (192.55.52.93) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 17 Dec 2012 16:02:07 +0000 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP; 17 Dec 2012 08:02:01 -0800 X-ExtLoop1: 1 Received: from swsutil001.isw.intel.com ([10.237.237.11]) by fmsmga002.fm.intel.com with ESMTP; 17 Dec 2012 08:01:56 -0800 Received: from ulslx001.iul.intel.com (ulslx001.iul.intel.com [172.28.207.63]) by swsutil001.isw.intel.com (8.13.6/8.13.6/MailSET/Hub) with ESMTP id qBHG1s66019668; Mon, 17 Dec 2012 16:01:54 GMT Received: from ulslx001.iul.intel.com (localhost [127.0.0.1]) by ulslx001.iul.intel.com with ESMTP id qBHG1s4k026482; Mon, 17 Dec 2012 17:01:54 +0100 Received: (from mmetzger@localhost) by ulslx001.iul.intel.com with id qBHG1sYP026478; Mon, 17 Dec 2012 17:01:54 +0100 From: markus.t.metzger@intel.com To: jan.kratochvil@redhat.com, palves@redhat.com, tromey@redhat.com, kettenis@gnu.org Cc: gdb-patches@sourceware.org, markus.t.metzger@gmail.com, Markus Metzger Subject: [patch v6 01/12] thread, btrace: add generic branch trace support Date: Mon, 17 Dec 2012 16:02:00 -0000 Message-Id: <1355760101-26237-2-git-send-email-markus.t.metzger@intel.com> In-Reply-To: <1355760101-26237-1-git-send-email-markus.t.metzger@intel.com> References: <1355760101-26237-1-git-send-email-markus.t.metzger@intel.com> X-IsSubscribed: yes 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 X-SW-Source: 2012-12/txt/msg00562.txt.bz2 From: Markus Metzger Add branch trace information to struct thread_info to hold the branch trace information for that thread. Add functions to enable/disable, and get a thread's branch trace, as well as for iterating over it. Iteration uses a per-thread iterator stored in the thread_info's branch trace information. Iterators are reset implicitly when a thread's branch trace changes. 2012-12-17 Markus Metzger * target.h: Include btrace.h. (struct target_ops): Add btrace ops. * target.c (update_current_target): Initialize btrace ops. (target_supports_btrace): New function. (target_enable_btrace): New function. (target_disable_btrace): New function. (target_read_btrace): New function. (target_btrace_has_changed): New function. * btrace.h: New file. * btrace.c: New file. * Makefile.in: Add btrace.c. * gdbthread.h: Include btrace.h. (struct thread_info): Add btrace field. * thread.c: Include btrace.h. (clear_thread_inferior_resources): Call disable_btrace. * infcmd.c: Include btrace.h. (detach_command): Call disconnect_btrace. * common/btrace-common.h: New file. --- gdb/Makefile.in | 4 +- gdb/btrace.c | 168 ++++++++++++++++++++++++++++++++++++++++++++ gdb/btrace.h | 83 ++++++++++++++++++++++ gdb/common/btrace-common.h | 62 ++++++++++++++++ gdb/gdbthread.h | 4 + gdb/infcmd.c | 2 + gdb/target.c | 69 ++++++++++++++++++ gdb/target.h | 35 +++++++++ gdb/thread.c | 3 + 9 files changed, 428 insertions(+), 2 deletions(-) create mode 100644 gdb/btrace.c create mode 100644 gdb/btrace.h create mode 100644 gdb/common/btrace-common.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 244694c..d6e1dbb 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -754,7 +754,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ regset.c sol-thread.c windows-termcap.c \ common/gdb_vecs.c common/common-utils.c common/xml-utils.c \ common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.c \ - common/format.c + common/format.c btrace.c LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c @@ -921,7 +921,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ gdb_vecs.o jit.o progspace.o skip.o probe.o \ common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \ - format.o registry.o + format.o registry.o btrace.o TSOBS = inflow.o diff --git a/gdb/btrace.c b/gdb/btrace.c new file mode 100644 index 0000000..667a738 --- /dev/null +++ b/gdb/btrace.c @@ -0,0 +1,168 @@ +/* Branch trace support for GDB, the GNU debugger. + + Copyright (C) 2012 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.h" +#include "gdbthread.h" +#include "regcache.h" +#include "exceptions.h" +#include "inferior.h" +#include "target.h" + +/* See btrace.h. */ + +void +enable_btrace (struct thread_info *tp) +{ + if (tp->btrace.target != NULL) + return; + + if (!target_supports_btrace ()) + error (_("Target does not support branch tracing.")); + + tp->btrace.target = target_enable_btrace (tp->ptid); +} + +/* See btrace.h. */ + +void +disable_btrace (struct thread_info *tp) +{ + struct btrace_thread_info *btp = &tp->btrace; + int errcode = 0; + + if (btp->target == NULL) + return; + + if (!target_supports_btrace ()) + return; + + target_disable_btrace (btp->target); + btp->target = NULL; + + VEC_free (btrace_block_s, btp->btrace); +} + +/* See btrace.h. */ + +void +disconnect_btrace (void) +{ + struct thread_info *tp; + + ALL_THREADS (tp) + disable_btrace (tp); +} + +/* Update the thread's branch trace data in case of new trace. */ + +static void +update_btrace (struct thread_info *tp) +{ + struct btrace_thread_info *btp = &tp->btrace; + + if (btp->target != NULL && target_btrace_has_changed (btp->target)) + { + btp->btrace = target_read_btrace (btp->target); + btp->iterator = -1; + + /* The first block ends at the current pc. */ + if (!VEC_empty (btrace_block_s, btp->btrace)) + { + struct regcache *regcache; + struct btrace_block *head; + + regcache = get_thread_regcache (tp->ptid); + head = VEC_index (btrace_block_s, btp->btrace, 0); + if (head != NULL && head->end == 0) + head->end = regcache_read_pc (regcache); + } + } +} + +/* See btrace.h. */ + +VEC (btrace_block_s) * +get_btrace (struct thread_info *tp) +{ + update_btrace (tp); + + return tp->btrace.btrace; +} + +/* See btrace.h. */ + +struct btrace_block * +read_btrace (struct thread_info *tp, int index) +{ + struct btrace_thread_info *btp = &tp->btrace; + + if (index < 0) + error (_("Invalid index: %d."), index); + + update_btrace (tp); + btp->iterator = index; + + if (btp->iterator >= VEC_length (btrace_block_s, btp->btrace)) + { + btp->iterator = VEC_length (btrace_block_s, btp->btrace); + return NULL; + } + + return VEC_index (btrace_block_s, btp->btrace, btp->iterator); +} + +/* See btrace.h. */ + +struct btrace_block * +prev_btrace (struct thread_info *tp) +{ + struct btrace_thread_info *btp = &tp->btrace; + + update_btrace (tp); + btp->iterator += 1; + + if (btp->iterator >= VEC_length (btrace_block_s, btp->btrace)) + { + btp->iterator = VEC_length (btrace_block_s, btp->btrace); + return NULL; + } + + return VEC_index (btrace_block_s, btp->btrace, btp->iterator); +} + +/* See btrace.h. */ + +struct btrace_block * +next_btrace (struct thread_info *tp) +{ + struct btrace_thread_info *btp = &tp->btrace; + + update_btrace (tp); + btp->iterator -= 1; + + if (btp->iterator <= -1) + { + btp->iterator = -1; + return NULL; + } + + return VEC_index (btrace_block_s, btp->btrace, btp->iterator); +} diff --git a/gdb/btrace.h b/gdb/btrace.h new file mode 100644 index 0000000..df9df23 --- /dev/null +++ b/gdb/btrace.h @@ -0,0 +1,83 @@ +/* Branch trace support for GDB, the GNU debugger. + + Copyright (C) 2012 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 . */ + +#ifndef BTRACE_H +#define BTRACE_H + +/* Branch tracing (btrace) is a per-thread control-flow execution trace of the + inferior. For presentation purposes, the branch trace is represented as a + list of sequential control-flow blocks, one such list per thread. */ + +#include "btrace-common.h" + +struct thread_info; + +/* Branch trace information per thread. + + This represents the branch trace configuration as well as the entry point + into the branch trace data. For the latter, it also contains the index into + an array of branch trace blocks used for iterating though the branch trace + blocks of a thread. */ +struct btrace_thread_info +{ + /* The target branch trace information for this thread. + + This contains the branch trace configuration as well as any + target-specific information necessary for implementing branch tracing on + the underlying architecture. */ + struct btrace_target_info *target; + + /* The current branch trace for this thread. */ + VEC (btrace_block_s) *btrace; + + /* The current iterator position in the above trace vector. + In additon to valid vector indices, the iterator can be: + + -1 one before the head + VEC_length() one after the tail */ + int iterator; +}; + +/* Enable branch tracing for a thread. */ +extern void enable_btrace (struct thread_info *tp); + +/* Disable branch tracing for a thread. + This will also delete the current branch trace data. */ +extern void disable_btrace (struct thread_info *); + +/* Disconnect branch tracing on detach. */ +extern void disconnect_btrace (void); + +/* Return the current branch trace vector for a thread, or NULL if there is no + branch trace data available. */ +extern VEC (btrace_block_s) *get_btrace (struct thread_info *); + +/* Functions to iterate over a thread's branch trace. + There is one global iterator per thread. The iterator is reset implicitly + when branch trace for this thread changes. + On success, read_btrace sets the iterator to the returned trace entry. + Returns the selected block or NULL if there is no trace or the iterator is + out of bounds. */ +extern struct btrace_block *read_btrace (struct thread_info *, int); +extern struct btrace_block *prev_btrace (struct thread_info *); +extern struct btrace_block *next_btrace (struct thread_info *); + +#endif /* BTRACE_H */ diff --git a/gdb/common/btrace-common.h b/gdb/common/btrace-common.h new file mode 100644 index 0000000..90372ba --- /dev/null +++ b/gdb/common/btrace-common.h @@ -0,0 +1,62 @@ +/* Branch trace support for GDB, the GNU debugger. + + Copyright (C) 2012 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 . */ + +#ifndef BTRACE_COMMON_H +#define BTRACE_COMMON_H + +/* Branch tracing (btrace) is a per-thread control-flow execution trace of the + inferior. For presentation purposes, the branch trace is represented as a + list of sequential control-flow blocks, one such list per thread. */ + +#ifdef GDBSERVER +# include "server.h" +#else +# include "defs.h" +#endif + +#include "vec.h" + +/* A branch trace block. + + This represents a block of sequential control-flow. Adjacent blocks will be + connected via calls, returns, or jumps. The latter can be direct or + indirect, conditional or unconditional. Branches can further be + asynchronous, e.g. interrupts. */ +struct btrace_block +{ + /* The address of the first instruction in the block. */ + CORE_ADDR begin; + + /* The address of the last instruction in the 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. */ +DEF_VEC_O (btrace_block_s); + +/* Target specific branch trace information. */ +struct btrace_target_info; + +#endif /* BTRACE_COMMON_H */ diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index 0250555..69320f3 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -28,6 +28,7 @@ struct symtab; #include "frame.h" #include "ui-out.h" #include "inferior.h" +#include "btrace.h" /* Frontend view of the thread state. Possible extensions: stepping, finishing, until(ling),... */ @@ -227,6 +228,9 @@ struct thread_info /* Function that is called to free PRIVATE. If this is NULL, then xfree will be called on PRIVATE. */ void (*private_dtor) (struct private_thread_info *); + + /* Branch trace information for this thread. */ + struct btrace_thread_info btrace; }; /* Create an empty thread list, or empty the existing one. */ diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 4e38725..56e4403 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -56,6 +56,7 @@ #include "inf-loop.h" #include "continuations.h" #include "linespec.h" +#include "btrace.h" /* Functions exported for general use, in inferior.h: */ @@ -2745,6 +2746,7 @@ detach_command (char *args, int from_tty) error (_("The program is not being run.")); disconnect_tracing (from_tty); + disconnect_btrace (); target_detach (args, from_tty); diff --git a/gdb/target.c b/gdb/target.c index ebd8085..db7a3c6 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -4149,6 +4149,75 @@ target_ranged_break_num_registers (void) return -1; } +/* See target.h. */ +int +target_supports_btrace (void) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + if (t->to_supports_btrace != NULL) + return t->to_supports_btrace (); + + return 0; +} + +/* See target.h. */ +struct btrace_target_info * +target_enable_btrace (ptid_t ptid) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + if (t->to_enable_btrace != NULL) + return t->to_enable_btrace (ptid); + + tcomplain (); + return NULL; +} + +/* See target.h. */ +void +target_disable_btrace (struct btrace_target_info *btinfo) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + if (t->to_disable_btrace != NULL) + return t->to_disable_btrace (btinfo); + + tcomplain (); +} + +/* See target.h. */ +int +target_btrace_has_changed (struct btrace_target_info *btinfo) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + if (t->to_btrace_has_changed != NULL) + return t->to_btrace_has_changed (btinfo); + + tcomplain (); + return 0; +} + +/* See target.h. */ +VEC (btrace_block_s) * +target_read_btrace (struct btrace_target_info *btinfo) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + if (t->to_read_btrace != NULL) + return t->to_read_btrace (btinfo); + + tcomplain (); + return NULL; +} + + static void debug_to_prepare_to_store (struct regcache *regcache) { diff --git a/gdb/target.h b/gdb/target.h index a832ef8..4f6f35b 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -62,6 +62,7 @@ struct expression; #include "memattr.h" #include "vec.h" #include "gdb_signals.h" +#include "btrace.h" enum strata { @@ -857,6 +858,22 @@ struct target_ops /* Is the target able to use agent in current state? */ int (*to_can_use_agent) (void); + /* Check whether the target supports branch tracing. */ + int (*to_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 *(*to_enable_btrace) (ptid_t ptid); + + /* Disable branch tracing and deallocate @tinfo. */ + void (*to_disable_btrace) (struct btrace_target_info *tinfo); + + /* Check whether branch trace changed on the target. */ + int (*to_btrace_has_changed) (struct btrace_target_info *); + + /* Read branch trace data. */ + VEC (btrace_block_s) *(*to_read_btrace) (struct btrace_target_info *); + int to_magic; /* Need sub-structure for target machine related rather than comm related? */ @@ -1897,4 +1914,22 @@ extern void update_target_permissions (void); /* Blank target vector entries are initialized to target_ignore. */ void target_ignore (void); +/* Check whether the target supports branch tracing. */ +extern int target_supports_btrace (void); + +/* Enable branch tracing for @ptid. + Returns a branch tracing target info object. */ +extern struct btrace_target_info *target_enable_btrace (ptid_t ptid); + +/* Disable branch tracing. Deallocates @btinfo. */ +extern void target_disable_btrace (struct btrace_target_info *btinfo); + +/* Check whether there is no branch tracing data available. */ +extern int target_btrace_has_changed (struct btrace_target_info *btinfo); + +/* Read branch tracing data. + Returns a vector of branch trace blocks with the latest entry at index 0. */ +extern VEC (btrace_block_s) *target_read_btrace (struct btrace_target_info *); + + #endif /* !defined (TARGET_H) */ diff --git a/gdb/thread.c b/gdb/thread.c index 7e8eec5..47d8a6e 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -34,6 +34,7 @@ #include "regcache.h" #include "gdb.h" #include "gdb_string.h" +#include "btrace.h" #include #include @@ -117,6 +118,8 @@ clear_thread_inferior_resources (struct thread_info *tp) bpstat_clear (&tp->control.stop_bpstat); + disable_btrace (tp); + do_all_intermediate_continuations_thread (tp, 1); do_all_continuations_thread (tp, 1); } -- 1.7.6.5