* [PATCH 05/16] cli, btrace: add btrace cli
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
@ 2012-05-10 15:16 ` markus.t.metzger
2012-05-10 16:44 ` Eli Zaretskii
2012-05-10 15:16 ` [PATCH 01/16] disas: add precise instructions flag markus.t.metzger
` (15 subsequent siblings)
16 siblings, 1 reply; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:16 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add branch trace commands:
- "btrace enable/disable" perform the obvious operation
"" on the current thread.
"all" on each existing thread.
"auto" on each newly created thread.
Actually, "btrace enable auto" turns on automatic enabling for new threads,
and "btrace disable auto" turns it off, again.
- "btrace list" prints the blocks that have been traced.
The output may be configured using modifiers. It prints:
- the block number
/a the begin and end code address of that block
/f the function containing the block
/l the source lines contained in the block
With the /t modifier, it prints the total number of blocks and exits.
It accepts an optional range argument specifying the range of blocks to be
listed. If no argument is given, all blocks are listed.
The block number can be used to print the trace for one particular block or
for a range of blocks.
- "btrace" prints the branch trace disassembly for the current thread.
Branch trace is printed block-by-block. Typically, one block at a time is
printed.
By default, the disassembly for the next block is printed, thus iterating
over the full branch trace.
The command supports the /m and /r modifiers accepted by the disassemble
command.
In addition, the command supports the following arguments:
- "<n>" set the iterator to the <n>-th block
- "+[<n>]" advance the iterator by <n> (default: 1)
- "-[<n>]" advance the iterator by -<n> (default: 1)
- "<l>-<h>" set the iterator to the <h>'th block and
print the blocks in the range in reverse (i.e. original
control flow) order.
Mixed source and disassembly does not work very well for inlined functions,
a problem that it shares with the disassemble command.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* command.h (enum command_class): Add class_btrace
* btrace.c (thread_callback): New function
(for_each_thread): New function
(do_enable_btrace): New function
(safe_do_enable_btrace): New function
(do_disable_btrace): New function
(safe_do_disable_btrace): New function
(cmd_btrace_enable): New function
(cmd_btrace_enable_all): New function
(cmd_btrace_enable_auto): New function
(cmd_btrace_disable): New function
(cmd_btrace_disable_all): New function
(cmd_btrace_disable_auto): New function
(cmd_btrace_list): New function
(cmd_btrace): New function
(_initialize_btrace): New function
---
gdb/btrace.c | 604 +++++++++++++++++++++++++++++++++++++++
gdb/command.h | 2 +-
gdb/testsuite/gdb.base/page.exp | 3 +-
3 files changed, 607 insertions(+), 2 deletions(-)
diff --git a/gdb/btrace.c b/gdb/btrace.c
index e66a986..2b57ca7 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -23,8 +23,24 @@
#include "gdbthread.h"
#include "frame.h"
#include "exceptions.h"
+#include "observer.h"
+#include "command.h"
+#include "cli/cli-cmds.h"
+#include "cli/cli-utils.h"
+#include "arch-utils.h"
+#include "disasm.h"
#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+
+/* A new thread observer enabling branch tracing for the new thread. */
+static struct observer *btrace_thread_observer;
+
+/* Branch tracing command list. */
+static struct cmd_list_element *btcmdlist;
+static struct cmd_list_element *btencmdlist;
+static struct cmd_list_element *btdiscmdlist;
#if !defined(EALREADY)
/* Remap EALREADY for systems that do not define it, e.g. mingw. */
@@ -252,3 +268,591 @@ next_btrace (struct thread_info *tinfo)
return VEC_index (btrace_block_s, btinfo->btrace, btinfo->iterator);
}
+
+static int
+thread_callback (struct thread_info *tinfo, void *arg)
+{
+ observer_new_thread_ftype *tfun = arg;
+ tfun (tinfo);
+
+ return 0;
+}
+
+static void
+for_each_thread (observer_new_thread_ftype *tfun)
+{
+ iterate_over_threads (thread_callback, tfun);
+}
+
+static void
+do_enable_btrace (struct thread_info *tinfo)
+{
+ int errcode = enable_btrace (tinfo);
+ if (errcode)
+ {
+ int pid = ptid_get_lwp (tinfo->ptid);
+ if (!pid)
+ pid = ptid_get_pid (tinfo->ptid);
+
+ error (_("Couldn't enable branch tracing for %d: %s"),
+ pid, safe_strerror (errcode));
+ }
+}
+
+static void
+safe_do_enable_btrace (struct thread_info *tinfo)
+{
+ if (!target_supports_btrace ())
+ warning (_("Target does not support branch tracing."));
+ else
+ {
+ volatile struct gdb_exception error;
+
+ TRY_CATCH (error, RETURN_MASK_ERROR)
+ {
+ do_enable_btrace (tinfo);
+ }
+ if (error.message)
+ warning (_("%s"), error.message);
+ }
+}
+
+static void
+do_disable_btrace (struct thread_info *tinfo)
+{
+ int errcode = disable_btrace (tinfo);
+ if (errcode)
+ {
+ int pid = ptid_get_lwp (tinfo->ptid);
+ if (!pid)
+ pid = ptid_get_pid (tinfo->ptid);
+
+ error (_("Couldn't disable branch tracing for %d: %s"),
+ pid, safe_strerror (errcode));
+ }
+}
+
+static void
+safe_do_disable_btrace (struct thread_info *tinfo)
+{
+ if (!target_supports_btrace ())
+ warning (_("Target does not support branch tracing."));
+ else
+ {
+ volatile struct gdb_exception error;
+
+ TRY_CATCH (error, RETURN_MASK_ERROR)
+ {
+ do_disable_btrace (tinfo);
+ }
+ if (error.message)
+ warning (_("%s"), error.message);
+ }
+}
+
+static int
+do_enable_btrace_list (struct thread_info *tinfo, void *arg)
+{
+ char *range = (char *)arg;
+
+ if (number_is_in_list (range, tinfo->num))
+ {
+ /* Switching threads makes it easier for targets like kgdb, where we need
+ to switch cpus, as well. */
+ switch_to_thread (tinfo->ptid);
+ safe_do_enable_btrace (tinfo);
+ }
+
+ return 0;
+}
+
+static void
+cmd_btrace_enable (char *args, int from_tty)
+{
+ if (args)
+ {
+ ptid_t ptid = inferior_ptid;
+
+ iterate_over_threads (do_enable_btrace_list, args);
+
+ switch_to_thread (ptid);
+ }
+ else
+ {
+ struct thread_info *tinfo = find_thread_ptid (inferior_ptid);
+ if (!tinfo)
+ error (_("Couldn't enable branch tracing: no inferior thread."));
+ else
+ do_enable_btrace (tinfo);
+ }
+}
+
+static void
+cmd_btrace_enable_all (char *args, int from_tty)
+{
+ if (args)
+ error (_("Invalid argument."));
+ else
+ for_each_thread (safe_do_enable_btrace);
+}
+
+static void
+cmd_btrace_enable_auto (char *args, int from_tty)
+{
+ if (args)
+ error (_("Invalid argument."));
+ else if (btrace_thread_observer)
+ error (_("Automatic branch trace enabling already on."));
+ else
+ btrace_thread_observer =
+ observer_attach_new_thread (safe_do_enable_btrace);
+}
+
+static int
+do_disable_btrace_list (struct thread_info *tinfo, void *arg)
+{
+ char *range = (char *)arg;
+
+ if (number_is_in_list (range, tinfo->num))
+ {
+ /* Switching threads makes it easier for targets like kgdb, where we need
+ to switch cpus, as well. */
+ switch_to_thread (tinfo->ptid);
+ safe_do_disable_btrace (tinfo);
+ }
+
+ return 0;
+}
+
+static void
+cmd_btrace_disable (char *args, int from_tty)
+{
+ if (args)
+ {
+ ptid_t ptid = inferior_ptid;
+
+ iterate_over_threads (do_disable_btrace_list, args);
+
+ switch_to_thread (ptid);
+ }
+ else
+ {
+ struct thread_info *tinfo = find_thread_ptid (inferior_ptid);
+ if (!tinfo)
+ error (_("Couldn't disable branch tracing: no inferior thread."));
+ else
+ do_disable_btrace (tinfo);
+ }
+}
+
+static void
+cmd_btrace_disable_all (char *args, int from_tty)
+{
+ if (args)
+ error (_("Invalid argument."));
+ else
+ for_each_thread (safe_do_disable_btrace);
+}
+
+static void
+cmd_btrace_disable_auto (char *args, int from_tty)
+{
+ if (args)
+ error (_("Invalid argument."));
+ else if (!btrace_thread_observer)
+ error (_("Automatic branch trace enabling already off."));
+ else
+ {
+ observer_detach_new_thread (btrace_thread_observer);
+ btrace_thread_observer = NULL;
+ }
+}
+
+#define BTR_LIST_ADDRESS (1 << 0)
+#define BTR_LIST_FUNCTION (1 << 1)
+#define BTR_LIST_LINE (1 << 2)
+#define BTR_LIST_TOTAL (1 << 3)
+
+static void
+do_btrace_list_item (unsigned int block, struct btrace_block *trace,
+ unsigned int flags)
+{
+ struct gdbarch *gdbarch = get_current_arch ();
+ struct symtab *symtab = NULL;
+ struct symbol *symbol = NULL;
+
+ if (!trace)
+ return;
+
+ ui_out_field_fmt_int (current_uiout, 5, ui_left, "block", block);
+
+ if (flags & BTR_LIST_ADDRESS)
+ {
+ ui_out_field_core_addr (current_uiout, "begin", gdbarch, trace->begin);
+ ui_out_text (current_uiout, " - ");
+ ui_out_field_core_addr (current_uiout, "end", gdbarch, trace->end);
+ }
+
+ if (flags & BTR_LIST_FUNCTION)
+ {
+ ui_out_text (current_uiout, " in ");
+
+ symbol = find_pc_function (trace->begin);
+ if (symbol)
+ ui_out_field_string (current_uiout, "function",
+ SYMBOL_PRINT_NAME (symbol));
+ else
+ {
+ struct minimal_symbol *msymbol =
+ lookup_minimal_symbol_by_pc (trace->begin);
+ if (msymbol)
+ ui_out_field_string (current_uiout, "function",
+ SYMBOL_PRINT_NAME (msymbol));
+ else
+ ui_out_text (current_uiout, "??");
+ }
+
+ ui_out_text (current_uiout, " ()");
+ }
+
+ if (flags & BTR_LIST_LINE)
+ {
+ struct linetable *linetable = NULL;
+ const char *filename = NULL;
+
+ if (symbol)
+ symtab = symbol->symtab;
+ if (!symtab)
+ symtab = find_pc_symtab (trace->begin);
+ if (symtab)
+ {
+ linetable = symtab->linetable;
+ filename = symtab->filename;
+ }
+
+ if (filename)
+ {
+ ui_out_text (current_uiout, " at ");
+ ui_out_field_string (current_uiout, "file", filename);
+
+ if (linetable)
+ {
+ struct linetable_entry *line = linetable->item;
+ int nitems = linetable->nitems, i = 0;
+ int begin = INT_MAX, end = 0;
+
+ /* Skip all preceding entries. */
+ for (; i < (nitems - 1) && line[i + 1].pc <= trace->begin; ++i);
+
+ for (; i < nitems && line[i].pc <= trace->end; ++i)
+ {
+ begin = min (begin, line[i].line);
+ end = max (end, line[i].line);
+ }
+
+ if (begin <= end)
+ {
+ ui_out_text (current_uiout, ":");
+ ui_out_field_int (current_uiout, "lbegin", begin);
+
+ if (begin < end)
+ {
+ ui_out_text (current_uiout, "-");
+ ui_out_field_int (current_uiout, "lend", end);
+ }
+ }
+ }
+ }
+ }
+
+ ui_out_text (current_uiout, "\n");
+}
+
+static void
+do_btrace_list (VEC (btrace_block_s) *btrace, char *range,
+ unsigned int flags)
+{
+ struct gdbarch *gdbarch = get_current_arch ();
+ struct cleanup *ui_out_chain =
+ make_cleanup_ui_out_tuple_begin_end (current_uiout, "btrace blocks");
+ unsigned int block = 0;
+ struct btrace_block *trace;
+
+ while (VEC_iterate (btrace_block_s, btrace, block, trace))
+ {
+ ++block;
+
+ if (number_is_in_list (range, block))
+ do_btrace_list_item (block, trace, flags);
+ }
+
+ do_cleanups (ui_out_chain);
+}
+
+static void
+cmd_btrace_list (char *args, int from_tty)
+{
+ struct thread_info *thread = find_thread_ptid (inferior_ptid);
+ VEC (btrace_block_s) *btrace = get_btrace (thread);
+ unsigned int flags = BTR_LIST_FUNCTION | BTR_LIST_LINE;
+
+ /* Parse modifier. */
+ if (args)
+ {
+ if (*args == '/')
+ flags = 0;
+
+ while (*args == '/')
+ {
+ ++args;
+
+ if (*args == '\0')
+ error (_("Missing modifier."));
+
+ for (; *args; ++args)
+ {
+ if (isspace (*args))
+ break;
+
+ if (*args == '/')
+ continue;
+
+ switch (*args)
+ {
+ case 'a':
+ flags |= BTR_LIST_ADDRESS;
+ break;
+ case 'f':
+ flags |= BTR_LIST_FUNCTION;
+ break;
+ case 'l':
+ flags |= BTR_LIST_LINE;
+ break;
+ case 't':
+ flags |= BTR_LIST_TOTAL;
+ break;
+ default:
+ error (_("Invalid modifier: %c."), *args);
+ }
+ }
+
+ args = skip_spaces (args);
+ }
+ }
+
+ if (flags & BTR_LIST_TOTAL)
+ {
+ struct cleanup *ui_out_chain;
+ unsigned int total = VEC_length (btrace_block_s, btrace);
+
+ ui_out_chain =
+ make_cleanup_ui_out_tuple_begin_end (current_uiout, "btrace blocks");
+
+ ui_out_text (current_uiout, "total: ");
+ ui_out_field_int (current_uiout, "total", total);
+ ui_out_text (current_uiout, "\n");
+
+ do_cleanups (ui_out_chain);
+ }
+ else if (!btrace)
+ error (_("No trace"));
+ else
+ do_btrace_list (btrace, args, flags);
+}
+
+static void
+do_btrace (struct btrace_block *trace, int flags)
+{
+ struct gdbarch *gdbarch = get_current_arch ();
+
+ if (!trace)
+ {
+ error (_("No trace."));
+ return;
+ }
+
+ if (trace->end < trace->begin)
+ error (_("Bad trace: 0x%" BFD_VMA_FMT "x - 0x%" BFD_VMA_FMT "x."),
+ trace->begin, trace->end);
+
+ gdb_disassembly (gdbarch, current_uiout, 0, flags, -1,
+ trace->begin, trace->end + 1);
+}
+
+static void
+cmd_btrace (char *args, int from_tty)
+{
+ struct thread_info *thread = find_thread_ptid (inferior_ptid);
+ struct btrace_block *trace = NULL;
+ int flags = 0;
+
+ if (!thread)
+ {
+ error (_("No thread."));
+ return;
+ }
+
+ /* Parse modifier. We accept the same modifiers as the disas command. */
+ if (args)
+ {
+ while (*args == '/')
+ {
+ ++args;
+
+ if (*args == '\0')
+ error (_("Missing modifier."));
+
+ for (; *args; ++args)
+ {
+ if (isspace (*args))
+ break;
+
+ if (*args == '/')
+ continue;
+
+ switch (*args)
+ {
+ case 'm':
+ flags |= DISASSEMBLY_SOURCE;
+ flags |= DISASSEMBLY_PRECISE_INSN;
+ flags |= DISASSEMBLY_FILENAME;
+ break;
+ case 'r':
+ flags |= DISASSEMBLY_RAW_INSN;
+ break;
+ default:
+ error (_("Invalid modifier: %c."), *args);
+ }
+ }
+
+ args = skip_spaces (args);
+ }
+ }
+
+
+ if (!args || !*args)
+ trace = prev_btrace (thread);
+ else if (args[0] == '+')
+ {
+ size_t skip = 1;
+
+ args++;
+ if (args[0])
+ skip = get_number (&args);
+
+ while (skip--)
+ trace = prev_btrace (thread);
+ }
+ else if (args[0] == '-')
+ {
+ size_t skip = 1;
+
+ args++;
+ if (args[0])
+ skip = get_number (&args);
+
+ while (skip--)
+ trace = next_btrace (thread);
+ }
+ else
+ {
+ /* We store the relevant blocks into a separate vector, so we can display
+ them in reverse order. */
+ VEC (btrace_block_s) *btrace = NULL;
+ struct cleanup *cleanup;
+ struct get_number_or_range_state state;
+ unsigned int i;
+
+ cleanup = make_cleanup (xfree, btrace);
+ init_number_or_range (&state, args);
+ while (!state.finished)
+ {
+ int index = get_number_or_range (&state);
+ if (!index)
+ {
+ error (_("Args must be numbers or '$' variables."));
+ return;
+ }
+
+ trace = read_btrace (thread, index - 1);
+ if (!trace)
+ continue;
+
+ VEC_safe_push (btrace_block_s, btrace, trace);
+ }
+
+ i = VEC_length (btrace_block_s, btrace);
+ while (i--)
+ do_btrace (VEC_index (btrace_block_s, btrace, i), flags);
+
+ do_cleanups (cleanup);
+ return;
+ }
+
+ if (args && *args)
+ {
+ error (_("Junk after argument: %s"), args);
+ return;
+ }
+
+ do_btrace (trace, flags);
+}
+
+void _initialize_btrace (void);
+
+void
+_initialize_btrace (void)
+{
+ struct cmd_list_element *c;
+
+ add_cmd ("branchtrace", class_btrace, NULL,
+ _("Recording a branch trace."), &cmdlist);
+
+ add_prefix_cmd ("btrace", class_btrace, cmd_btrace, _("\
+Disassemble the selected branch trace block.\n\n\
+With a /m modifier, source lines are included (if available).\n\
+With a /r modifier, raw instructions in hex are included.\n\n\
+Without arguments, selects the chronologically preceding block.\n\
+With \"+[<n>]\" argument, selects the n-th chronologically preceding block.\n\
+With \"-[<n>]\" argument, selects the n-th chronologically succeeding block.\n\
+With one positive integer argument, selects the respective block.\n\
+With a range argument \"<l>-<h>\", selects the h-th block and disassembles \
+blocks in the range in reverse (i.e. original control flow) order.\n"),
+ &btcmdlist, "btrace ", 1, &cmdlist);
+
+ add_prefix_cmd ("enable", class_btrace, cmd_btrace_enable, _("\
+Enable branch trace recording for the current thread.\n"),
+ &btencmdlist, "btrace enable ", 1, &btcmdlist);
+
+ add_cmd ("all", class_btrace, cmd_btrace_enable_all, _("\
+Enable branch trace recording for all existing threads.\n"),
+ &btencmdlist);
+
+ add_cmd ("auto", class_btrace, cmd_btrace_enable_auto, _("\
+Enable branch trace recording for each new thread.\n"),
+ &btencmdlist);
+
+ add_prefix_cmd ("disable", class_btrace, cmd_btrace_disable, _("\
+Disable branch trace recording for the current thread.\n"),
+ &btdiscmdlist, "btrace disable ", 1, &btcmdlist);
+
+ add_cmd ("all", class_btrace, cmd_btrace_disable_all, _("\
+Disable branch trace recording for all existing threads.\n"),
+ &btdiscmdlist);
+
+ add_cmd ("auto", class_btrace, cmd_btrace_disable_auto, _("\
+Stop enabling branch trace recording for each new thread.\n"),
+ &btdiscmdlist);
+
+ add_cmd ("list", class_btrace, cmd_btrace_list, _("\
+List branch trace blocks.\n\n\
+Prints a list of all blocks for which branch trace is available.\n\
+With a /a modifier, addresses are included.\n\
+With a /f modifier, the function name is included (if available).\n\
+With a /l modifier, source lines are include (if available).\n\
+With a /t modifier, prints the total number of trace blocks and stops.\n\
+Without any modifier, behaves as if /fl were specified.\n\n\
+Without arguments, the full list of blocks is listed.\n\
+With a range (<start>[-<end>]) argument, the blocks in that range are listed.\n"),
+ &btcmdlist);
+}
diff --git a/gdb/command.h b/gdb/command.h
index c18e2dd..999ec1d 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -37,7 +37,7 @@ enum command_class
no_class = -1, class_run = 0, class_vars, class_stack, class_files,
class_support, class_info, class_breakpoint, class_trace,
class_alias, class_bookmark, class_obscure, class_maintenance,
- class_pseudo, class_tui, class_user, class_xdb,
+ class_pseudo, class_tui, class_user, class_xdb, class_btrace,
no_set_class /* Used for "show" commands that have no corresponding
"set" command. */
};
diff --git a/gdb/testsuite/gdb.base/page.exp b/gdb/testsuite/gdb.base/page.exp
index 0629807..d9b3899 100644
--- a/gdb/testsuite/gdb.base/page.exp
+++ b/gdb/testsuite/gdb.base/page.exp
@@ -25,6 +25,7 @@ gdb_test_sequence "help" "unpaged help" {
"List of classes of commands:"
""
"aliases -- Aliases of other commands"
+ "branchtrace -- Recording a branch trace"
"breakpoints -- Making program stop at certain points"
"data -- Examining data"
"files -- Specifying and examining files"
@@ -52,12 +53,12 @@ gdb_expect_list "paged help" \
"List of classes of commands:"
""
"aliases -- Aliases of other commands"
+ "branchtrace -- Recording a branch trace"
"breakpoints -- Making program stop at certain points"
"data -- Examining data"
"files -- Specifying and examining files"
"internals -- Maintenance commands"
"obscure -- Obscure features"
- "running -- Running the program"
}
gdb_test "q"
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH 05/16] cli, btrace: add btrace cli
2012-05-10 15:16 ` [PATCH 05/16] cli, btrace: add btrace cli markus.t.metzger
@ 2012-05-10 16:44 ` Eli Zaretskii
2012-05-11 8:17 ` Metzger, Markus T
0 siblings, 1 reply; 24+ messages in thread
From: Eli Zaretskii @ 2012-05-10 16:44 UTC (permalink / raw)
To: markus.t.metzger; +Cc: gdb-patches, markus.t.metzger, markus.t.metzger
> From: markus.t.metzger@intel.com
> Cc: markus.t.metzger@gmail.com, Markus Metzger <markus.t.metzger@intel.com>
> Date: Thu, 10 May 2012 17:13:19 +0200
>
> Add branch trace commands:
>
> - "btrace enable/disable" perform the obvious operation
>
> "" on the current thread.
> "all" on each existing thread.
> "auto" on each newly created thread.
>
> Actually, "btrace enable auto" turns on automatic enabling for new threads,
> and "btrace disable auto" turns it off, again.
>
> - "btrace list" prints the blocks that have been traced.
>
> The output may be configured using modifiers. It prints:
> - the block number
> /a the begin and end code address of that block
> /f the function containing the block
> /l the source lines contained in the block
>
> With the /t modifier, it prints the total number of blocks and exits.
>
> It accepts an optional range argument specifying the range of blocks to be
> listed. If no argument is given, all blocks are listed.
>
> The block number can be used to print the trace for one particular block or
> for a range of blocks.
>
> - "btrace" prints the branch trace disassembly for the current thread.
>
> Branch trace is printed block-by-block. Typically, one block at a time is
> printed.
>
> By default, the disassembly for the next block is printed, thus iterating
> over the full branch trace.
>
> The command supports the /m and /r modifiers accepted by the disassemble
> command.
>
> In addition, the command supports the following arguments:
> - "<n>" set the iterator to the <n>-th block
> - "+[<n>]" advance the iterator by <n> (default: 1)
> - "-[<n>]" advance the iterator by -<n> (default: 1)
> - "<l>-<h>" set the iterator to the <h>'th block and
> print the blocks in the range in reverse (i.e. original
> control flow) order.
>
> Mixed source and disassembly does not work very well for inlined functions,
> a problem that it shares with the disassemble command.
Thanks. I'm quite sure we want these new commands documented in the
user manual, and mentioned in NEWS.
^ permalink raw reply [flat|nested] 24+ messages in thread
* RE: [PATCH 05/16] cli, btrace: add btrace cli
2012-05-10 16:44 ` Eli Zaretskii
@ 2012-05-11 8:17 ` Metzger, Markus T
0 siblings, 0 replies; 24+ messages in thread
From: Metzger, Markus T @ 2012-05-11 8:17 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches, markus.t.metzger
[-- Attachment #1.1: Type: text/plain, Size: 820 bytes --]
> -----Original Message-----
> From: Eli Zaretskii [mailto:eliz@gnu.org]
> Sent: Thursday, May 10, 2012 6:43 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org; markus.t.metzger@gmail.com; Metzger,
> Markus T
> Subject: Re: [PATCH 05/16] cli, btrace: add btrace cli
[...]
> Thanks. I'm quite sure we want these new commands documented in the
> user manual, and mentioned in NEWS.
I expect some discussion on the commands and their exact spelling. I will add
documentation once the UI is clear, if that's OK.
I tried to summarize it in the cover letter. I hope it's sufficiently detailed
for
discussion. If it helps, I can send a documentation patch, as well, but I'm
afraid
I might end up redoing it completely.
It would be nice if you could point me to the files that need changing.
Regards,
Markus.
[-- Attachment #1.2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 7228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 417 bytes --]
--------------------------------------------------------------------------------------
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Douglas Lusk, Peter Gleissner, Hannes Schwaderer
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 01/16] disas: add precise instructions flag
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
2012-05-10 15:16 ` [PATCH 05/16] cli, btrace: add btrace cli markus.t.metzger
@ 2012-05-10 15:16 ` markus.t.metzger
2012-05-10 15:17 ` [PATCH 07/16] configure: autoreconf markus.t.metzger
` (14 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:16 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
When disassembling an address range with interleaved sources, the addresses that
are being disassembled may not exactly match the specified range.
Addresses may be:
- added after the specified range
- omitted at the beginning of the specified range
Add a new disassembly flag that fixes the above two cases.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* disasm.h: Add new flag DISASSEMBLY_PRECISE_INSN
* disasm.c (do_mixed_source_and_assembly): Adjust mle boundaries
---
gdb/disasm.c | 28 ++++++++++++++++++++++++----
gdb/disasm.h | 7 ++++---
2 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/gdb/disasm.c b/gdb/disasm.c
index e3d3349..4902d95 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -217,13 +217,22 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
/* First, skip all the preceding functions. */
- for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
+ /* If we want precise instructions, we only skip the line entries for which
+ the pc range between this and the next entry precedes the requested
+ instruction range. */
+ if (flags & DISASSEMBLY_PRECISE_INSN)
+ for (i = 0; i < nlines - 2 && le[i + 1].pc <= low; i++);
+ else
+ for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
/* Now, copy all entries before the end of this function. */
for (; i < nlines - 1 && le[i].pc < high; i++)
{
- if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
+ CORE_ADDR start = le[i].pc;
+ CORE_ADDR end = le[i + 1].pc;
+
+ if (le[i].line == le[i + 1].line && start == end)
continue; /* Ignore duplicates. */
/* Skip any end-of-function markers. */
@@ -233,8 +242,19 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
mle[newlines].line = le[i].line;
if (le[i].line > le[i + 1].line)
out_of_order = 1;
- mle[newlines].start_pc = le[i].pc;
- mle[newlines].end_pc = le[i + 1].pc;
+
+ /* If we want precise instructions, adjust the line ranges to only contain
+ instructions in the requested range. */
+ if (flags & DISASSEMBLY_PRECISE_INSN)
+ {
+ if (high < end)
+ end = high;
+ if (start < low)
+ start = low;
+ }
+
+ mle[newlines].start_pc = start;
+ mle[newlines].end_pc = end;
newlines++;
}
diff --git a/gdb/disasm.h b/gdb/disasm.h
index 646ee8e..5b459f4 100644
--- a/gdb/disasm.h
+++ b/gdb/disasm.h
@@ -19,9 +19,10 @@
#ifndef DISASM_H
#define DISASM_H
-#define DISASSEMBLY_SOURCE (0x1 << 0)
-#define DISASSEMBLY_RAW_INSN (0x1 << 1)
-#define DISASSEMBLY_OMIT_FNAME (0x1 << 2)
+#define DISASSEMBLY_SOURCE (0x1 << 0)
+#define DISASSEMBLY_RAW_INSN (0x1 << 1)
+#define DISASSEMBLY_OMIT_FNAME (0x1 << 2)
+#define DISASSEMBLY_PRECISE_INSN (0x1 << 3)
struct ui_out;
struct ui_file;
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 07/16] configure: autoreconf
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
2012-05-10 15:16 ` [PATCH 05/16] cli, btrace: add btrace cli markus.t.metzger
2012-05-10 15:16 ` [PATCH 01/16] disas: add precise instructions flag markus.t.metzger
@ 2012-05-10 15:17 ` markus.t.metzger
2012-05-10 15:17 ` [PATCH 02/16] source: add flags to print_source_lines () markus.t.metzger
` (13 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:17 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Ran autoreconf in gdb.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* config.in: Regenerate
* configure: Regenerate
gdb/gdbserver/
* config.in: Regenerate
* configure: Regenerate
---
gdb/config.in | 3 +++
gdb/configure | 13 +++++++++++++
gdb/gdbserver/config.in | 3 +++
gdb/gdbserver/configure | 2 +-
4 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/gdb/config.in b/gdb/config.in
index e54c1ea..966abd2 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -219,6 +219,9 @@
/* Define to 1 if you have the <link.h> header file. */
#undef HAVE_LINK_H
+/* Define to 1 if you have the <linux/perf_event.h> header file. */
+#undef HAVE_LINUX_PERF_EVENT_H
+
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
diff --git a/gdb/configure b/gdb/configure
index c1775b7..bf5144a 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -8887,6 +8887,19 @@ fi
done
+for ac_header in linux/perf_event.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "linux/perf_event.h" "ac_cv_header_linux_perf_event_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_perf_event_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_PERF_EVENT_H 1
+_ACEOF
+
+fi
+
+done
+
+
# ------------------------- #
# Checks for declarations. #
# ------------------------- #
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index 26742ac..11d2194 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -72,6 +72,9 @@
/* Define to 1 if you have the <linux/elf.h> header file. */
#undef HAVE_LINUX_ELF_H
+/* Define to 1 if you have the <linux/perf_event.h> header file. */
+#undef HAVE_LINUX_PERF_EVENT_H
+
/* Define if the target supports register sets. */
#undef HAVE_LINUX_REGSETS
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index 63e25c2..29e52e6 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -4419,7 +4419,7 @@ $as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cach
cd "$ac_popdir"
-for ac_header in sgtty.h termio.h termios.h sys/reg.h string.h proc_service.h sys/procfs.h thread_db.h linux/elf.h stdlib.h unistd.h errno.h fcntl.h signal.h sys/file.h malloc.h sys/ioctl.h netinet/in.h sys/socket.h netdb.h netinet/tcp.h arpa/inet.h sys/wait.h sys/un.h
+for ac_header in sgtty.h termio.h termios.h sys/reg.h string.h proc_service.h sys/procfs.h thread_db.h linux/elf.h stdlib.h unistd.h errno.h fcntl.h signal.h sys/file.h malloc.h sys/ioctl.h netinet/in.h sys/socket.h netdb.h netinet/tcp.h arpa/inet.h sys/wait.h sys/un.h linux/perf_event.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 02/16] source: add flags to print_source_lines ()
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (2 preceding siblings ...)
2012-05-10 15:17 ` [PATCH 07/16] configure: autoreconf markus.t.metzger
@ 2012-05-10 15:17 ` markus.t.metzger
2012-05-10 15:17 ` [PATCH 10/16] btrace, config: enable btrace for 32bit and 64bit linux native markus.t.metzger
` (12 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:17 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
The 4th parameter of print_source_lines is a boolean flag noerror. Generalize
this to be a bit vector of flags and make noerror one of the flag bits.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* symtab.h (print_source_lines_flags): New enum
* source.c (print_source_lines_base): Change noerror to flags
(print_source_lines): Change noerror to flags
---
gdb/source.c | 14 ++++++--------
gdb/symtab.h | 5 +++++
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/gdb/source.c b/gdb/source.c
index 27c5b0e..4dd7ed2 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -1225,10 +1225,8 @@ identify_source_line (struct symtab *s, int line, int mid_statement,
/* Print source lines from the file of symtab S,
starting with line number LINE and stopping before line number STOPLINE. */
-static void print_source_lines_base (struct symtab *s, int line, int stopline,
- int noerror);
static void
-print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
+print_source_lines_base (struct symtab *s, int line, int stopline, int flags)
{
int c;
int desc;
@@ -1256,13 +1254,13 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
else
{
desc = last_source_error;
- noerror = 1;
+ flags |= PRINT_SOURCE_LINES_NOERROR;
}
}
else
{
desc = last_source_error;
- noerror = 1;
+ flags |= PRINT_SOURCE_LINES_NOERROR;
noprint = 1;
}
@@ -1270,7 +1268,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
{
last_source_error = desc;
- if (!noerror)
+ if (!(flags & PRINT_SOURCE_LINES_NOERROR))
{
char *name = alloca (strlen (s->filename) + 100);
sprintf (name, "%d\t%s", line, s->filename);
@@ -1356,9 +1354,9 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
window otherwise it is simply printed. */
void
-print_source_lines (struct symtab *s, int line, int stopline, int noerror)
+print_source_lines (struct symtab *s, int line, int stopline, int flags)
{
- print_source_lines_base (s, line, stopline, noerror);
+ print_source_lines_base (s, line, stopline, flags);
}
\f
/* Print info on range of pc's in a specified line. */
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 61e7c0f..b252725 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1126,6 +1126,11 @@ extern void clear_solib (void);
extern int identify_source_line (struct symtab *, int, int, CORE_ADDR);
+/* Flags passed as 4th argument to print_source_lines. */
+enum print_source_lines_flags {
+ PRINT_SOURCE_LINES_NOERROR = (0x1 << 0)
+};
+
extern void print_source_lines (struct symtab *, int, int, int);
extern void forget_cached_source_info_for_objfile (struct objfile *);
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 10/16] btrace, config: enable btrace for 32bit and 64bit linux native
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (3 preceding siblings ...)
2012-05-10 15:17 ` [PATCH 02/16] source: add flags to print_source_lines () markus.t.metzger
@ 2012-05-10 15:17 ` markus.t.metzger
2012-05-10 15:17 ` [PATCH 04/16] thread, btrace: add generic branch trace support markus.t.metzger
` (11 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:17 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Install the btrace target ops for i386-linux-nat and amd64-linux-nat.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* amd64-linux-nat.c: Add include
(_initialize_amd64_linux_nat): Initialize btrace ops
* i386-linux.nat.c: Add include
(_initialize_i386_linux_nat): Initialize btrace ops
gdb/config/i386/
* linux.mh: Add linux-btrace.o
* linux64.mh: Add linux-btrace.o
---
gdb/amd64-linux-nat.c | 2 ++
gdb/config/i386/linux.mh | 3 ++-
gdb/config/i386/linux64.mh | 2 +-
gdb/i386-linux-nat.c | 2 ++
4 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index 5ebba3a..caea66a 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -25,6 +25,7 @@
#include "regset.h"
#include "linux-nat.h"
#include "amd64-linux-tdep.h"
+#include "linux-nat-btrace.h"
#include "gdb_assert.h"
#include "gdb_string.h"
@@ -841,6 +842,7 @@ _initialize_amd64_linux_nat (void)
t = linux_target ();
i386_use_watchpoints (t);
+ linux_nat_add_btrace_ops (t);
i386_dr_low.set_control = amd64_linux_dr_set_control;
i386_dr_low.set_addr = amd64_linux_dr_set_addr;
diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh
index 8316d87..cc45f83 100644
--- a/gdb/config/i386/linux.mh
+++ b/gdb/config/i386/linux.mh
@@ -4,7 +4,8 @@ NAT_FILE= config/nm-linux.h
NATDEPFILES= inf-ptrace.o fork-child.o \
i386-nat.o i386-linux-nat.o \
proc-service.o linux-thread-db.o \
- linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
+ linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
+ linux-btrace.o linux-nat-btrace.o
NAT_CDEPS = $(srcdir)/proc-service.list
# The dynamically loaded libthread_db needs access to symbols in the
diff --git a/gdb/config/i386/linux64.mh b/gdb/config/i386/linux64.mh
index d2b95fd..4fead06 100644
--- a/gdb/config/i386/linux64.mh
+++ b/gdb/config/i386/linux64.mh
@@ -3,7 +3,7 @@ NATDEPFILES= inf-ptrace.o fork-child.o \
i386-nat.o amd64-nat.o amd64-linux-nat.o \
linux-nat.o linux-osdata.o \
proc-service.o linux-thread-db.o linux-fork.o \
- linux-procfs.o linux-ptrace.o
+ linux-procfs.o linux-ptrace.o linux-btrace.o linux-nat-btrace.o
NAT_FILE= config/nm-linux.h
NAT_CDEPS = $(srcdir)/proc-service.list
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index ac1629a..00bddb6 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -25,6 +25,7 @@
#include "regset.h"
#include "target.h"
#include "linux-nat.h"
+#include "linux-nat-btrace.h"
#include "gdb_assert.h"
#include "gdb_string.h"
@@ -1020,6 +1021,7 @@ _initialize_i386_linux_nat (void)
t = linux_target ();
i386_use_watchpoints (t);
+ linux_nat_add_btrace_ops (t);
i386_dr_low.set_control = i386_linux_dr_set_control;
i386_dr_low.set_addr = i386_linux_dr_set_addr;
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 04/16] thread, btrace: add generic branch trace support
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (4 preceding siblings ...)
2012-05-10 15:17 ` [PATCH 10/16] btrace, config: enable btrace for 32bit and 64bit linux native markus.t.metzger
@ 2012-05-10 15:17 ` markus.t.metzger
2012-05-10 15:17 ` [PATCH 11/16] test, btrace: add branch trace tests markus.t.metzger
` (10 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:17 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
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-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* target.h: Add include
(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
(target_btrace_has_changed): New macro
* target.c (update_current_target): Initialize btrace ops
* btrace.h: New file
* btrace.c: New file
* Makefile.in: Add btrace.c
* gdbthread.h: Add include
(struct thread_info): Add btrace field
* thread.c: Add include
(free_thread): Call disable_btrace
* infcmd.c: Add include
(detach_command): Call disconnect_btrace
---
gdb/Makefile.in | 4 +-
gdb/btrace.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/btrace.h | 89 +++++++++++++++++++
gdb/gdbthread.h | 4 +
gdb/infcmd.c | 2 +
gdb/target.c | 20 +++++
gdb/target.h | 32 +++++++
gdb/thread.c | 3 +
8 files changed, 406 insertions(+), 2 deletions(-)
create mode 100644 gdb/btrace.c
create mode 100644 gdb/btrace.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4368f07..5fa7c12 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -744,7 +744,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
annotate.c common/signals.c copying.c dfp.c gdb.c inf-child.c \
regset.c sol-thread.c windows-termcap.c \
common/common-utils.c common/xml-utils.c \
- common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.c
+ common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.c btrace.c
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@@ -915,7 +915,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
inferior.o osdata.o gdb_usleep.o record.o gcore.o \
jit.o progspace.o skip.o probe.o \
- common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o
+ common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o btrace.o
TSOBS = inflow.o
diff --git a/gdb/btrace.c b/gdb/btrace.c
new file mode 100644
index 0000000..e66a986
--- /dev/null
+++ b/gdb/btrace.c
@@ -0,0 +1,254 @@
+/* Branch trace support for GDB, the GNU debugger.
+
+ Copyright (C) 2012 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 "btrace.h"
+#include "gdbthread.h"
+#include "frame.h"
+#include "exceptions.h"
+
+#include <errno.h>
+
+#if !defined(EALREADY)
+/* Remap EALREADY for systems that do not define it, e.g. mingw. */
+# define EALREADY EBUSY
+#endif
+
+int
+enable_btrace (struct thread_info *tinfo)
+{
+ if (!tinfo)
+ return EINVAL;
+
+ if (tinfo->btrace.target)
+ return EALREADY;
+
+ tinfo->btrace.target = target_enable_btrace (tinfo->ptid);
+ if (!tinfo->btrace.target)
+ return (errno ? errno : ENOSYS);
+
+ return 0;
+}
+
+int
+disable_btrace (struct thread_info *tinfo)
+{
+ struct btrace_thread_info *btinfo;
+ int errcode = 0;
+
+ if (!tinfo)
+ return EINVAL;
+
+ btinfo = &tinfo->btrace;
+
+ if (!btinfo->target)
+ return EALREADY;
+
+ /* When killing the inferior, we may have lost our target before we disable
+ branch tracing. */
+ if (target_supports_btrace ())
+ errcode = target_disable_btrace (btinfo->target);
+
+ if (!errcode)
+ {
+ VEC_free (btrace_block_s, btinfo->btrace);
+ btinfo->btrace = NULL;
+ btinfo->target = NULL;
+ }
+
+ return errcode;
+}
+
+static int
+do_disconnect_btrace (struct thread_info *tinfo, void *ignored)
+{
+ if (tinfo->btrace.target)
+ {
+ volatile struct gdb_exception error;
+
+ TRY_CATCH (error, RETURN_MASK_ERROR)
+ {
+ /* Switching threads makes it easier for targets like kgdb, where we
+ need to switch cpus, as well. */
+ switch_to_thread (tinfo->ptid);
+
+ disable_btrace (tinfo);
+ }
+ }
+
+ return 0;
+}
+
+void
+disconnect_btrace (void)
+{
+ ptid_t ptid = inferior_ptid;
+
+ iterate_over_threads (do_disconnect_btrace, NULL);
+
+ switch_to_thread (ptid);
+}
+
+static struct btrace_thread_info *
+get_btinfo (struct thread_info *tinfo)
+{
+ if (!tinfo)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ return &tinfo->btrace;
+}
+
+static int
+update_btrace (struct btrace_thread_info *btinfo)
+{
+ if (!btinfo)
+ return EINVAL;
+
+ if (btinfo->target && target_btrace_has_changed (btinfo->target))
+ {
+ btinfo->btrace = target_read_btrace (btinfo->target);
+ btinfo->iterator = -1;
+
+ if (!btinfo->btrace)
+ return (errno ? errno : ENOSYS);
+
+ /* The first block ends at the current pc. */
+ if (!VEC_empty (btrace_block_s, btinfo->btrace))
+ {
+ struct frame_info *frame = get_current_frame ();
+ if (frame)
+ {
+ struct btrace_block *head =
+ VEC_index (btrace_block_s, btinfo->btrace, 0);
+ if (head && !head->end)
+ head->end = get_frame_pc (frame);
+ }
+ }
+ }
+
+ return 0;
+}
+
+VEC (btrace_block_s) *
+get_btrace (struct thread_info *tinfo)
+{
+ struct btrace_thread_info *btinfo = get_btinfo (tinfo);
+ int errcode;
+
+ if (!btinfo)
+ return NULL;
+
+ errcode = update_btrace (btinfo);
+ if (errcode)
+ {
+ errno = errcode;
+ return NULL;
+ }
+ return btinfo->btrace;
+}
+
+struct btrace_block *
+read_btrace (struct thread_info *tinfo, int index)
+{
+ struct btrace_thread_info *btinfo = get_btinfo (tinfo);
+ int errcode;
+
+ if (!btinfo)
+ return NULL;
+
+ if (index < 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ errcode = update_btrace (btinfo);
+ if (errcode)
+ {
+ errno = errcode;
+ return NULL;
+ }
+
+ btinfo->iterator = index;
+
+ if (btinfo->iterator >= VEC_length (btrace_block_s, btinfo->btrace))
+ {
+ btinfo->iterator = VEC_length (btrace_block_s, btinfo->btrace);
+ return NULL;
+ }
+
+ return VEC_index (btrace_block_s, btinfo->btrace, btinfo->iterator);
+}
+
+struct btrace_block *
+prev_btrace (struct thread_info *tinfo)
+{
+ struct btrace_thread_info *btinfo = get_btinfo (tinfo);
+ int errcode;
+
+ if (!btinfo)
+ return NULL;
+
+ errcode = update_btrace (btinfo);
+ if (errcode)
+ {
+ errno = errcode;
+ return NULL;
+ }
+
+ btinfo->iterator += 1;
+
+ if (btinfo->iterator >= VEC_length (btrace_block_s, btinfo->btrace))
+ {
+ btinfo->iterator = VEC_length (btrace_block_s, btinfo->btrace);
+ return NULL;
+ }
+
+ return VEC_index (btrace_block_s, btinfo->btrace, btinfo->iterator);
+}
+
+struct btrace_block *
+next_btrace (struct thread_info *tinfo)
+{
+ struct btrace_thread_info *btinfo = get_btinfo (tinfo);
+ int errcode;
+
+ if (!btinfo)
+ return NULL;
+
+ errcode = update_btrace (btinfo);
+ if (errcode)
+ {
+ errno = errcode;
+ return NULL;
+ }
+
+ btinfo->iterator -= 1;
+
+ if (btinfo->iterator < 0)
+ {
+ btinfo->iterator = -1;
+ return NULL;
+ }
+
+ return VEC_index (btrace_block_s, btinfo->btrace, btinfo->iterator);
+}
diff --git a/gdb/btrace.h b/gdb/btrace.h
new file mode 100644
index 0000000..97f0f52
--- /dev/null
+++ b/gdb/btrace.h
@@ -0,0 +1,89 @@
+/* Branch trace support for GDB, the GNU debugger.
+
+ Copyright (C) 2012 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/>. */
+
+#ifndef BTRACE_H
+#define BTRACE_H
+
+#include "vec.h"
+#include "defs.h"
+
+struct thread_info;
+
+/* A branch trace block.
+
+ Beware that a block is not a branch. Rather, blocks are connected through
+ branches. */
+struct btrace_block
+{
+ CORE_ADDR begin;
+ 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;
+DEF_VEC_O (btrace_block_s);
+
+/* Target specific branch trace information. */
+struct btrace_target_info;
+
+/* Branch trace information per thread. */
+struct btrace_thread_info
+{
+ /* The target branch trace information for this thread. */
+ 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. */
+ int iterator;
+};
+
+/* Enable branch tracing for a thread.
+ Allocates the branch trace target information.
+ Returns 0 on success and an error value, otherwise. */
+extern int enable_btrace (struct thread_info *);
+
+/* Disable branch tracing for a thread.
+ Deallocates the branch trace target information as well as the current branch
+ trace data.
+ Returns 0 on success and an error value, otherwise. */
+extern int 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 ther is no
+ trace. */
+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 iteratoris
+ 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/gdbthread.h b/gdb/gdbthread.h
index fb8de16..055bac0 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),... */
@@ -225,6 +226,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 6a841e5..1f156a6 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: */
@@ -2678,6 +2679,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 cffea2c..6986385 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -702,6 +702,11 @@ update_current_target (void)
INHERIT (to_traceframe_info, t);
INHERIT (to_use_agent, t);
INHERIT (to_can_use_agent, t);
+ INHERIT (to_supports_btrace, t);
+ INHERIT (to_enable_btrace, t);
+ INHERIT (to_disable_btrace, t);
+ INHERIT (to_btrace_has_changed, t);
+ INHERIT (to_read_btrace, t);
INHERIT (to_magic, t);
INHERIT (to_supports_evaluation_of_breakpoint_conditions, t);
/* Do not inherit to_memory_map. */
@@ -940,6 +945,21 @@ update_current_target (void)
(int (*) (void))
return_zero);
de_fault (to_execution_direction, default_execution_direction);
+ de_fault (to_supports_btrace,
+ (int (*) (void))
+ return_zero);
+ de_fault (to_enable_btrace,
+ (struct btrace_target_info * (*) (ptid_t))
+ tcomplain);
+ de_fault (to_disable_btrace,
+ (int (*) (struct btrace_target_info *))
+ tcomplain);
+ de_fault (to_btrace_has_changed,
+ (int (*) (struct btrace_target_info *))
+ tcomplain);
+ de_fault (to_read_btrace,
+ (VEC (btrace_block_s) * (*) (struct btrace_target_info *))
+ tcomplain);
#undef de_fault
diff --git a/gdb/target.h b/gdb/target.h
index 50a0ea6..b54bbc1 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
{
@@ -849,6 +850,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. Deallocated @tinfo on success. */
+ int (*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?
*/
@@ -1710,6 +1727,21 @@ extern char *target_fileio_read_stralloc (const char *filename);
#define target_can_use_agent() \
(*current_target.to_can_use_agent) ()
+#define target_supports_btrace() \
+ (*current_target.to_supports_btrace) ()
+
+#define target_enable_btrace(ptid) \
+ (*current_target.to_enable_btrace) (ptid)
+
+#define target_disable_btrace(tinfo) \
+ (*current_target.to_disable_btrace) (tinfo)
+
+#define target_btrace_has_changed(tinfo) \
+ (*current_target.to_btrace_has_changed) (tinfo)
+
+#define target_read_btrace(tinfo) \
+ (*current_target.to_read_btrace) (tinfo)
+
/* Command logging facility. */
#define target_log_command(p) \
diff --git a/gdb/thread.c b/gdb/thread.c
index d361dd8..e234fff 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 <ctype.h>
#include <sys/types.h>
@@ -132,6 +133,8 @@ free_thread (struct thread_info *tp)
xfree (tp->private);
}
+ disable_btrace (tp);
+
xfree (tp->name);
xfree (tp);
}
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 11/16] test, btrace: add branch trace tests
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (5 preceding siblings ...)
2012-05-10 15:17 ` [PATCH 04/16] thread, btrace: add generic branch trace support markus.t.metzger
@ 2012-05-10 15:17 ` markus.t.metzger
2012-05-10 15:17 ` [PATCH 08/16] linux, btrace: perf_event based branch tracing markus.t.metzger
` (9 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:17 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add tests covering btrace enable/disable/auto and btrace list.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
* .gitignore: add gdb/testsuite/gdb.btrace/list.x
gdb/testsuite/
* configure.ac: Add gdb.btrace makefile
gdb/testsuite/lib/
* btrace.exp: New file
gdb/testsuite/gdb.btrace/
* Makefile.in: New file
* enable.exp: New file
* list.exp: New file
* list.s: New file
---
.gitignore | 2 +
gdb/testsuite/configure.ac | 2 +-
gdb/testsuite/gdb.btrace/Makefile.in | 13 ++
gdb/testsuite/gdb.btrace/dec.c | 4 +
gdb/testsuite/gdb.btrace/enable.exp | 83 ++++++++++++++
gdb/testsuite/gdb.btrace/inc.c | 4 +
gdb/testsuite/gdb.btrace/list.exp | 169 ++++++++++++++++++++++++++++
gdb/testsuite/gdb.btrace/list.s | 68 +++++++++++
gdb/testsuite/gdb.btrace/list_function.c | 12 ++
gdb/testsuite/gdb.btrace/list_function.exp | 59 ++++++++++
gdb/testsuite/lib/btrace.exp | 72 ++++++++++++
11 files changed, 487 insertions(+), 1 deletions(-)
create mode 100755 gdb/testsuite/gdb.btrace/Makefile.in
create mode 100644 gdb/testsuite/gdb.btrace/dec.c
create mode 100644 gdb/testsuite/gdb.btrace/enable.exp
create mode 100644 gdb/testsuite/gdb.btrace/inc.c
create mode 100644 gdb/testsuite/gdb.btrace/list.exp
create mode 100644 gdb/testsuite/gdb.btrace/list.s
create mode 100644 gdb/testsuite/gdb.btrace/list_function.c
create mode 100644 gdb/testsuite/gdb.btrace/list_function.exp
create mode 100644 gdb/testsuite/lib/btrace.exp
diff --git a/.gitignore b/.gitignore
index dc1bf3f..94e43b1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,3 +38,5 @@ lost+found
*.log
*.sum
+
+gdb/testsuite/gdb.btrace/list.x
diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac
index d9ab9f7..164a505 100644
--- a/gdb/testsuite/configure.ac
+++ b/gdb/testsuite/configure.ac
@@ -98,4 +98,4 @@ AC_OUTPUT([Makefile \
gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile \
gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile \
gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile \
- gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile])
+ gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile gdb.btrace/Makefile])
diff --git a/gdb/testsuite/gdb.btrace/Makefile.in b/gdb/testsuite/gdb.btrace/Makefile.in
new file mode 100755
index 0000000..16afe0a
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/Makefile.in
@@ -0,0 +1,13 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+.PHONY: all clean mostlyclean distclean realclean
+
+all info install-info dvi install uninstall installcheck check:
+ @echo "Nothing to be done for $@..."
+
+clean mostlyclean:
+ -rm -f *.o *.x *.diff *~ *.bad core
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log gdb.log gdb.sum
diff --git a/gdb/testsuite/gdb.btrace/dec.c b/gdb/testsuite/gdb.btrace/dec.c
new file mode 100644
index 0000000..abe1ff5
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/dec.c
@@ -0,0 +1,4 @@
+extern int dec (int x)
+{
+ return x - 1;
+}
diff --git a/gdb/testsuite/gdb.btrace/enable.exp b/gdb/testsuite/gdb.btrace/enable.exp
new file mode 100644
index 0000000..a312ee3
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/enable.exp
@@ -0,0 +1,83 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <markus.t.metzger@intel.com>
+#
+# 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/>.
+
+if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } {
+ verbose "Tests ignored for all but x86 based targets."
+ return
+}
+
+load_lib btrace.exp
+
+set testfile "list"
+
+# check for btrace support
+if { [skip_btrace_tests] } { continue }
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+
+# automatic enabling can be turned on without an inferior
+gdb_test_no_output "btrace enable auto" "btrace enable 1.0"
+
+# we cannot enable it twice
+gdb_test "btrace enable auto" "Automatic branch trace enabling already on." "btrace enable 1.1"
+
+# but we can disable it
+gdb_test_no_output "btrace disable auto" "btrace enable 1.2"
+
+# we cannot disable it twice
+gdb_test "btrace disable auto" "Automatic branch trace enabling already off." "btrace enable 1.3"
+
+# we cannot enable/disable trace without a thread
+gdb_test "btrace enable" "Couldn't enable branch tracing: no inferior thread." "btrace enable 2.0"
+gdb_test "btrace disable" "Couldn't disable branch tracing: no inferior thread." "btrace enable 2.1"
+
+
+# start a debuggee program
+if { [set binfile [btrace_assemble ${testfile}]] == "" } {
+ untested ${testfile}.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# automatic enabling is off.
+runto test_1
+
+# since we support btrace, we should be able to enable it
+gdb_test_no_output "btrace enable" "btrace enable 3.0"
+
+# btrace is now enabled; we should not be able to enable it twice
+gdb_test "btrace enable" "Couldn't enable branch tracing.*" "btrace enable 3.1"
+
+# btrace is still enabled; we should be able to disable it
+gdb_test_no_output "btrace disable" "btrace enable 3.2"
+
+# btrace is now disabled; we should not be able to disable it twice
+gdb_test "btrace disable" "Couldn't disable branch tracing.*" "btrace enable 3.3"
+
+# rerun with automatic enabling on
+gdb_test_no_output "btrace enable auto"
+runto test_1
+
+# btrace is implicitly enabled; we should not be able to enable it twice
+gdb_test "btrace enable" "Couldn't enable branch tracing.*" "btrace enable 4.0"
+
+return 0
diff --git a/gdb/testsuite/gdb.btrace/inc.c b/gdb/testsuite/gdb.btrace/inc.c
new file mode 100644
index 0000000..03966f3
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/inc.c
@@ -0,0 +1,4 @@
+extern int inc (int x)
+{
+ return x + 1;
+}
diff --git a/gdb/testsuite/gdb.btrace/list.exp b/gdb/testsuite/gdb.btrace/list.exp
new file mode 100644
index 0000000..de33b59
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/list.exp
@@ -0,0 +1,169 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <markus.t.metzger@intel.com>
+#
+# 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/>.
+
+if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } {
+ verbose "Tests ignored for all but x86 based targets."
+ return
+}
+
+load_lib btrace.exp
+
+set testfile "list"
+
+# check for btrace support
+if { [skip_btrace_tests] } { continue }
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+if { [set binfile [btrace_assemble ${testfile}]] == "" } {
+ untested ${testfile}.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# Automatically enable branch tracing.
+gdb_test_no_output "btr enable auto"
+
+# Make sure we don't die when enabling trace for a newly created thread.
+runto test_1
+# we expect some trace at this point, but we don't really know how much or how
+# it would look like. Ignore it.
+
+# Reset branch trace so we get predictable output.
+btrace_reset_trace
+
+gdb_test "stepi" "0x0*400200 in test_1_sub.*" ""
+
+gdb_test "btr list /af" "
+1 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)" "btrace list 1.1"
+
+# We assume 5 bytes for call.
+gdb_test "stepi" "0x0*400215 in test_1.*" ""
+
+# We assume 5 bytes for call.
+gdb_test "btr list /af" "
+1 *0x0*400215 - 0x0*400215 in test_1 \\(\\)\r
+2 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)" "btrace list 1.2"
+
+gdb_test "stepi" "0x0*400200 in test_1_sub.*" ""
+gdb_test "stepi" "0x0*40021a in test_1.*" ""
+
+# We assume 5 bytes for call.
+gdb_test "btr list /af" "
+1 *0x0*40021a - 0x0*40021a in test_1 \\(\\)\r
+2 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)\r
+3 *0x0*400215 - 0x0*400215 in test_1 \\(\\)\r
+4 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)" "btrace list 1.3"
+
+# List a single block.
+gdb_test "btr list /af 2" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)" "btrace list 1.4"
+
+# List a range of blocks.
+gdb_test "btr list /af 2-4" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)\r
+3 *0x0*400215 - 0x0*400215 in test_1 \\(\\)\r
+4 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)" "btrace list 1.5"
+
+# We ignore too big upper bounds.
+gdb_test "btr list /af 3-9" "
+3 *0x0*400215 - 0x0*400215 in test_1 \\(\\)\r
+4 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)" "btrace list 1.6"
+
+# If the entire range is out of bounds, the list is empty.
+gdb_test "btr list /a 9-18" "" "btrace list 1.7"
+
+# Check modifiers individually
+gdb_test "btr list /a 2" "
+2 *0x0*400200 - 0x0*400200" "btrace list 1.8"
+
+gdb_test "btr list /f 2" "
+2 *in test_1_sub \\(\\)" "btrace list 1.9"
+
+# Check order of modifiers
+gdb_test "btr list /fa 2" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)" "btrace list 1.10"
+
+gdb_test "btr list /f /a 2" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)" "btrace list 1.11"
+
+gdb_test "btr list /a /f 2" "
+2 *0x0*400200 - 0x0*400200 in test_1_sub \\(\\)" "btrace list 1.12"
+
+
+# Proceed to the next test.
+runto test_2
+
+# Reset branch trace so we get predictable output.
+btrace_reset_trace
+
+# We assume 1 byte for nop.
+gdb_test "stepi" "0x0*400231 in test_2.*" ""
+
+# We have not seen a branch, yet, so there is no trace.
+gdb_test "btr list" "No trace." "btrace list 2.1"
+
+gdb_test "stepi" "0x0*400220 in test_2_sub.*" ""
+
+gdb_test "btr list /af" "
+1 *0x0*400220 - 0x0*400220 in test_2_sub \\(\\)" "btrace list 2.2"
+
+# We assume 1 byte for nop.
+gdb_test "stepi" "0x0*400221 in test_2_sub.*" ""
+
+# We assume 1 byte for nop.
+gdb_test "btr list /af" "
+1 *0x0*400220 - 0x0*400221 in test_2_sub \\(\\)" "btrace list 2.3"
+
+# We assume 1 byte for nop.
+gdb_test "stepi" "0x0*400222 in test_2_sub.*" ""
+
+# We assume 1 byte for nop.
+gdb_test "btr list /af" "
+1 *0x0*400220 - 0x0*400222 in test_2_sub \\(\\)" "btrace list 2.4"
+
+
+# Proceed to the next test.
+runto test_3
+
+# Reset branch trace so we get predictable output.
+btrace_reset_trace
+
+gdb_test "stepi" "0x0*400260 in test_3.*" ""
+
+gdb_test "btr list /af" "
+1 *0x0*400260 - 0x0*400260 in test_3 \\(\\)" "btrace list 3.1"
+
+gdb_test "stepi" "0x0*400250 in test_3.*" ""
+
+gdb_test "btr list /af" "
+1 *0x0*400250 - 0x0*400250 in test_3 \\(\\)\r
+2 *0x0*400260 - 0x0*400260 in test_3 \\(\\)" "btrace list 3.2"
+
+# We assume 1 byte for nop.
+gdb_test "stepi" "0x0*400251 in test_3.*" ""
+
+# We assume 1 byte for nop.
+gdb_test "btr list /af" "
+1 *0x0*400250 - 0x0*400251 in test_3 \\(\\)\r
+2 *0x0*400260 - 0x0*400260 in test_3 \\(\\)" "btrace list 3.3"
+
+return 0
diff --git a/gdb/testsuite/gdb.btrace/list.s b/gdb/testsuite/gdb.btrace/list.s
new file mode 100644
index 0000000..7659a8b
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/list.s
@@ -0,0 +1,68 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <markus.t.metzger@intel.com>
+#
+# 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/>.
+
+ .text
+ .globl _start
+ .globl main
+ .globl test_1
+ .globl test_2
+ .globl test_3
+ .align 0x100 # 0x400100
+_start:
+ call main
+ hlt
+
+ .align 0x10 # 0x400110
+main:
+ call test_1
+ call test_2
+ call test_3
+ ret
+
+ .align 0x100 # 0x400200
+test_1_sub:
+ ret
+
+ .align 0x10 # 0x400210
+test_1:
+ call test_1_sub
+ call test_1_sub
+ nop
+ ret
+
+ .align 0x10 # 0x400220
+test_2_sub:
+ nop
+ nop
+ ret
+
+ .align 0x10 # 0x400230
+test_2:
+ nop
+ call test_2_sub
+ ret
+
+ .align 0x10 # 0x400240
+test_3:
+ jmp .L3.1
+ .align 0x10 # 0x400250
+.L3.2:
+ nop
+ ret
+ .align 0x10 # 0x400260
+.L3.1:
+ jmp .L3.2
diff --git a/gdb/testsuite/gdb.btrace/list_function.c b/gdb/testsuite/gdb.btrace/list_function.c
new file mode 100644
index 0000000..0372126
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/list_function.c
@@ -0,0 +1,12 @@
+extern int inc (int);
+extern int dec (int);
+
+extern int main (void)
+{
+ int x = 0;
+
+ x = inc (x);
+ x = dec (x);
+
+ return x; /* End of main breakpoint location */
+}
diff --git a/gdb/testsuite/gdb.btrace/list_function.exp b/gdb/testsuite/gdb.btrace/list_function.exp
new file mode 100644
index 0000000..9585289
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/list_function.exp
@@ -0,0 +1,59 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <markus.t.metzger@intel.com>
+#
+# 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/>.
+
+load_lib btrace.exp
+
+set testfile "list_function"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}.x
+
+set sources "${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/inc.c ${srcdir}/${subdir}/dec.c"
+
+# check for btrace support
+if { [skip_btrace_tests] } { continue }
+
+if { [gdb_compile "${sources}" "${binfile}" executable {debug}] != "" } {
+ untested list_function.exp
+ return -1
+}
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+set bp_location [gdb_get_line_number "End of main breakpoint location"]
+
+gdb_breakpoint $bp_location
+
+gdb_test_no_output "btr enable"
+
+gdb_continue_to_breakpoint "cont to $bp_location" ".*$srcfile:$bp_location.*"
+
+gdb_test "btr list /f" "
+1 *in main \\(\\)\r
+2 *in dec \\(\\)\r
+3 *in main \\(\\)\r
+4 *in inc \\(\\)" "btrace list function 1.0"
+
+return 0
diff --git a/gdb/testsuite/lib/btrace.exp b/gdb/testsuite/lib/btrace.exp
new file mode 100644
index 0000000..92ca50f
--- /dev/null
+++ b/gdb/testsuite/lib/btrace.exp
@@ -0,0 +1,72 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <markus.t.metzger@intel.com>
+#
+# 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/>.
+
+proc btrace_assemble { testfile } {
+ global srcdir
+ global objdir
+ global subdir
+
+ set srcfile ${srcdir}/${subdir}/${testfile}.s
+ set objfile ${objdir}/${subdir}/${testfile}.o
+ set binfile ${objdir}/${subdir}/${testfile}.x
+
+ if {[target_assemble ${srcfile} ${objfile} ""] != ""} { return "" }
+
+ if {[target_link ${objfile} ${binfile} "-Ttext 0x400100"] != ""} { return "" }
+
+ return ${binfile}
+}
+
+proc skip_btrace_tests {} {
+ global gdb_prompt
+
+ set testfile "list"
+ set skip 0
+
+ if { [set binfile [btrace_assemble ${testfile}]] == "" } {
+ return 1
+ }
+
+ gdb_exit
+ gdb_start
+ gdb_load $binfile
+
+ runto main
+
+ gdb_test_multiple "btrace enable" "check btrace support" {
+ -re "You can't do that when your target is.*" {
+ unsupported "target does not support btrace"
+ set skip 1
+ }
+ -re "Couldn't enable branch tracing.*Operation not supported" {
+ unsupported "target does not support btrace"
+ set skip 1
+ }
+ -re "$gdb_prompt $" {}
+ }
+ gdb_exit
+ remote_file build delete $testfile
+
+ return $skip
+}
+
+proc btrace_reset_trace {} {
+ gdb_test_no_output "btr disable"
+ gdb_test_no_output "btr enable"
+
+ gdb_test "btr list" "No trace." "reset btrace"
+}
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 08/16] linux, btrace: perf_event based branch tracing
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (6 preceding siblings ...)
2012-05-10 15:17 ` [PATCH 11/16] test, btrace: add branch trace tests markus.t.metzger
@ 2012-05-10 15:17 ` markus.t.metzger
2012-05-10 15:17 ` [PATCH 16/16] gdbserver, linux, btrace: add btrace support for linux-low markus.t.metzger
` (8 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:17 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Implement branch tracing on Linux based on perf_event such taht it can be shared
between gdb and gdbserver.
The actual btrace target ops will be implemented on top.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/common/
* linux_btrace.h: New file
* linux_btrace.c: New file
gdb/
* Makefile.in: Add linux-btrace rules
gdb/gdbserver/
* Makefile.in: Add linux-btrace rules
---
gdb/Makefile.in | 7 +-
gdb/common/linux-btrace.c | 368 +++++++++++++++++++++++++++++++++++++++++++++
gdb/common/linux-btrace.h | 76 +++++++++
gdb/gdbserver/Makefile.in | 6 +-
4 files changed, 455 insertions(+), 2 deletions(-)
create mode 100644 gdb/common/linux-btrace.c
create mode 100644 gdb/common/linux-btrace.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 5fa7c12..b3fdd4f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -826,7 +826,8 @@ gnulib/import/extra/snippet/arg-nonnull.h gnulib/import/extra/snippet/c++defs.h
gnulib/import/extra/snippet/warn-on-use.h \
gnulib/import/stddef.in.h gnulib/import/inttypes.in.h inline-frame.h skip.h \
common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
-common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h
+common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
+common/linux-btrace.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -1930,6 +1931,10 @@ vec.o: ${srcdir}/common/vec.c
$(COMPILE) $(srcdir)/common/vec.c
$(POSTCOMPILE)
+linux-btrace.o: ${srcdir}/common/linux-btrace.c
+ $(COMPILE) $(srcdir)/common/linux-btrace.c
+ $(POSTCOMPILE)
+
#
# gdb/tui/ dependencies
#
diff --git a/gdb/common/linux-btrace.c b/gdb/common/linux-btrace.c
new file mode 100644
index 0000000..76bca75
--- /dev/null
+++ b/gdb/common/linux-btrace.c
@@ -0,0 +1,368 @@
+/* Linux-dependent part of branch trace support for GDB, and GDBserver.
+
+ Copyright (C) 2012 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 "linux-btrace.h"
+#include "common-utils.h"
+#include <errno.h>
+
+#if HAVE_LINUX_PERF_EVENT_H
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+
+typedef unsigned char byte;
+
+/* A branch trace record in perf_event. */
+struct perf_event_bts
+{
+ unsigned long long from;
+ unsigned long long to;
+};
+
+/* A perf_event branch trace sample. */
+struct perf_event_sample
+{
+ struct perf_event_header header;
+ struct perf_event_bts bts;
+};
+
+static inline volatile struct perf_event_mmap_page *
+perf_event_header (struct btrace_target_info* tinfo)
+{
+ return tinfo->buffer;
+}
+
+static inline size_t
+perf_event_mmap_size (const struct btrace_target_info *tinfo)
+{
+ /* The branch trace buffer is preceded by a configuration page. */
+ return ((tinfo->size + 1) * PAGE_SIZE);
+}
+
+static inline size_t
+perf_event_buffer_size (struct btrace_target_info* tinfo)
+{
+ return (tinfo->size * PAGE_SIZE);
+}
+
+static inline const byte *
+perf_event_buffer_begin (struct btrace_target_info* tinfo)
+{
+ return ((const byte *) tinfo->buffer) + PAGE_SIZE;
+}
+
+static inline const byte *
+perf_event_buffer_end (struct btrace_target_info* tinfo)
+{
+ return perf_event_buffer_begin (tinfo) + perf_event_buffer_size (tinfo);
+}
+
+static inline int
+perf_event_skip_record (struct btrace_target_info* tinfo,
+ const struct perf_event_bts *bts)
+{
+ if (tinfo->ptr_bits)
+ {
+ int shift = tinfo->ptr_bits - 1;
+
+ /* Branch trace records branches from kernel space to user space. */
+ if (bts->from & (1ull << shift))
+ return 1;
+
+ /* Branch trace records branches from user space to kernel space. */
+ if (bts->to & (1ull << shift))
+ return 1;
+ }
+
+ return 0;
+}
+
+static inline int
+perf_event_check_sample (const struct perf_event_sample *sample)
+{
+ if (sample->header.type != PERF_RECORD_SAMPLE)
+ return EINVAL;
+
+ if (sample->header.size != sizeof (*sample))
+ return EINVAL;
+
+ return 0;
+}
+
+/* Branch trace is collected in a circular buffer [begin; end) as pairs of from
+ and to addresses (plus some header).
+
+ Start points into that buffer at the next sample position.
+ We read the collected samples backwards from start.
+
+ While reading the samples, we convert the information into a list of blocks.
+ For two adjacent samples s1 and s2, we form a block b such that b.begin =
+ s1.to and b.end = s2.from.
+
+ In case the buffer overflows during sampling, samples may be split. */
+static int
+perf_event_read_bts (struct btrace_target_info* tinfo,
+ const byte *begin, const byte *end, const byte *start,
+ int (*fun) (struct linux_btrace_block *, void *),
+ void *arg)
+{
+ struct perf_event_sample sample;
+ int read = 0, size = (end - begin), errcode = 0;
+ struct linux_btrace_block block = { 0, 0 };
+
+ if (start < begin)
+ return EINVAL;
+
+ if (end < start)
+ return EINVAL;
+
+ /* The buffer may contain a partial record as its last entry (i.e. when the
+ buffer size is not a mulitple of the sample size). */
+ read = sizeof (sample) - 1;
+
+ for (; read < size; read += sizeof (sample))
+ {
+ const struct perf_event_sample *psample;
+
+ /* Find the next perf_event sample. */
+ start -= sizeof (sample);
+ if (begin <= start)
+ psample = (const struct perf_event_sample *) start;
+ else
+ {
+ int missing = (begin - start);
+ start = (end - missing);
+
+ if (missing == sizeof (sample))
+ psample = (const struct perf_event_sample *) start;
+ else
+ {
+ byte *stack = (byte *) &sample;
+
+ memcpy (stack, start, missing);
+ memcpy (stack + missing, begin, sizeof (sample) - missing);
+
+ psample = &sample;
+ }
+ }
+
+ errcode = perf_event_check_sample (psample);
+ if (errcode)
+ break;
+
+ if (perf_event_skip_record (tinfo, &(psample->bts)))
+ continue;
+
+ /* We found a valid sample, so we can complete the current block. */
+ block.begin = psample->bts.to;
+
+ errcode = (*fun) (&block, arg);
+ if (errcode)
+ break;
+
+ /* Start the next block. */
+ block.end = psample->bts.from;
+ }
+
+ return errcode;
+}
+
+int
+linux_supports_btrace (void)
+{
+ return 1;
+}
+
+int
+linux_btrace_has_changed (struct btrace_target_info *tinfo)
+{
+ volatile struct perf_event_mmap_page *header = perf_event_header (tinfo);
+ if (!header)
+ return 0;
+
+ return (header->data_head != tinfo->data_head);
+}
+
+struct btrace_target_info *
+linux_enable_btrace (ptid_t ptid)
+{
+ struct btrace_target_info *tinfo;
+ int pid;
+
+ tinfo = xzalloc (sizeof (*tinfo));
+ if (!tinfo)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ tinfo->attr.size = sizeof (tinfo->attr);
+
+ tinfo->attr.type = PERF_TYPE_HARDWARE;
+ tinfo->attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
+ tinfo->attr.sample_period = 1;
+
+ /* We sample from and to address. */
+ tinfo->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
+
+ tinfo->attr.exclude_kernel = 1;
+ tinfo->attr.exclude_hv = 1;
+ tinfo->attr.exclude_idle = 1;
+
+ tinfo->ptr_bits = 0;
+
+ pid = ptid_get_lwp (ptid);
+ if (!pid)
+ pid = ptid_get_pid (ptid);
+
+ tinfo->file = syscall (SYS_perf_event_open, &(tinfo->attr), pid, -1, -1, 0);
+ if (tinfo->file < 0)
+ goto err;
+
+ /* We hard-code the trace buffer size.
+ At some later time, we should make this configurable. */
+ tinfo->size = 1;
+ tinfo->buffer = mmap (NULL, perf_event_mmap_size (tinfo),
+ PROT_READ, MAP_SHARED, tinfo->file, 0);
+ if (tinfo->buffer == MAP_FAILED)
+ goto err_file;
+
+ return tinfo;
+
+err_file:
+ close (tinfo->file);
+
+err:
+ xfree (tinfo);
+ return NULL;
+}
+
+int
+linux_disable_btrace (struct btrace_target_info *tinfo)
+{
+ int errcode;
+
+ if (!tinfo)
+ return -EINVAL;
+
+ errcode = munmap (tinfo->buffer, perf_event_mmap_size (tinfo));
+ if (errcode)
+ return errno;
+
+ close (tinfo->file);
+ xfree (tinfo);
+
+ return 0;
+}
+
+int
+linux_read_btrace (struct btrace_target_info *tinfo,
+ int (*fun) (struct linux_btrace_block *, void *),
+ void *arg)
+{
+ volatile struct perf_event_mmap_page *header;
+ const byte *begin, *end, *start;
+ unsigned long data_head, retries = 5;
+ size_t buffer_size;
+ int errcode = 0;
+
+ if (!tinfo)
+ return EINVAL;
+
+ header = perf_event_header (tinfo);
+ if (!header)
+ return ENOSYS;
+
+ buffer_size = perf_event_buffer_size (tinfo);
+
+ /* We may need to retry reading the trace. See below. */
+ while (retries--)
+ {
+ data_head = header->data_head;
+
+ /* If there new trace, let's read it. */
+ if (data_head != tinfo->data_head)
+ {
+ /* Data_head keeps growing; the buffer itself is circular. */
+ begin = perf_event_buffer_begin (tinfo);
+ start = begin + (data_head % buffer_size);
+
+ if (data_head <= buffer_size)
+ end = start;
+ else
+ end = perf_event_buffer_end (tinfo);
+
+ errcode = perf_event_read_bts (tinfo, begin, end, start, fun, arg);
+ }
+
+ /* The stopping thread notifies its ptracer before it is scheduled out.
+ On multi-core systems, the debugger might therefore run while the
+ kernel might be writing the last branch trace records.
+
+ Let's check whether the data head moved while we read the trace. */
+ if (data_head == header->data_head)
+ break;
+ }
+
+ tinfo->data_head = data_head;
+
+ return errcode;
+}
+
+#else /* HAVE_LINUX_PERF_EVENT_H */
+
+int
+linux_supports_btrace (void)
+{
+ return 0;
+}
+
+int
+linux_btrace_has_changed (struct btrace_target_info *tinfo)
+{
+ return 0;
+}
+
+struct btrace_target_info *
+linux_enable_btrace (ptid_t ptid)
+{
+ errno = ENOSYS;
+ return NULL;
+}
+
+int
+linux_disable_btrace (struct btrace_target_info *tinfo)
+{
+ return ENOSYS;
+}
+
+int
+linux_read_btrace (struct btrace_target_info *tinfo,
+ int (*fun) (struct linux_btrace_block *, void *),
+ void *arg)
+{
+ return ENOSYS;
+}
+
+#endif /* HAVE_LINUX_PERF_EVENT_H */
diff --git a/gdb/common/linux-btrace.h b/gdb/common/linux-btrace.h
new file mode 100644
index 0000000..22f435a
--- /dev/null
+++ b/gdb/common/linux-btrace.h
@@ -0,0 +1,76 @@
+/* Linux-dependent part of branch trace support for GDB, and GDBserver.
+
+ Copyright (C) 2012 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/>. */
+
+#ifndef LINUX_BTRACE_H
+#define LINUX_BTRACE_H
+
+#include "config.h"
+#include "ptid.h"
+#include <stddef.h>
+
+#if HAVE_LINUX_PERF_EVENT_H
+# include <linux/perf_event.h>
+#endif
+
+/* A branch trace block on linux.
+ GDB and GDBserver don't agree on the definition of CORE_ADDR. In order to
+ allow sharing the perf_event access code, we stick to unsigned long long;
+ that's also what perf_event delivers. */
+struct linux_btrace_block
+{
+ unsigned long long begin;
+ unsigned long long end;
+};
+
+/* Branch trace target information per thread. */
+struct btrace_target_info
+{
+#if HAVE_LINUX_PERF_EVENT_H
+ /* The Linux perf_event configuration for collecting the branch trace. */
+ struct perf_event_attr attr;
+
+ /* The mmap configuration mapping the branch trace perf_event buffer.
+
+ file .. the file descriptor
+ buffer .. the mmapped memory buffer
+ size .. the buffer's size in pages without the configuration page
+ data_head .. the data head from the last read */
+ int file;
+ void *buffer;
+ size_t size;
+ unsigned long data_head;
+#endif /* HAVE_LINUX_PERF_EVENT_H */
+
+ /* The size of a pointer in bits for this thread.
+ The information is used to identify kernel addresses in order to skip
+ records from/to kernel space. */
+ int ptr_bits;
+};
+
+extern int linux_supports_btrace (void);
+extern struct btrace_target_info *linux_enable_btrace (ptid_t);
+extern int linux_disable_btrace (struct btrace_target_info *);
+extern int linux_btrace_has_changed (struct btrace_target_info *);
+extern int linux_read_btrace (struct btrace_target_info *,
+ int (*) (struct linux_btrace_block *, void *),
+ void *);
+
+#endif /* LINUX_BTRACE_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 50786d5..1f256de 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -139,7 +139,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/vec.c \
$(srcdir)/common/common-utils.c $(srcdir)/common/xml-utils.c \
$(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \
- $(srcdir)/common/buffer.c
+ $(srcdir)/common/buffer.c $(srcdir)/common/linux-btrace.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -408,6 +408,7 @@ signals_h = $(srcdir)/../../include/gdb/signals.h $(signals_def)
ptid_h = $(srcdir)/../common/ptid.h
ax_h = $(srcdir)/ax.h
agent_h = $(srcdir)/../common/agent.h
+linux_btrace_h = $(srcdir)/../common/linux-btrace.h
linux_osdata_h = $(srcdir)/../common/linux-osdata.h
vec_h = $(srcdir)/../common/vec.h
# Since everything must include server.h, we make that depend on
@@ -514,6 +515,9 @@ buffer.o: ../common/buffer.c $(server_h)
agent.o: ../common/agent.c $(server_h) $(agent_h)
$(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER
+linux-btrace.o: ../common/linux-btrace.c $(linux_btrace_h) $(server_h)
+ $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER
+
# We build vasprintf with -DHAVE_CONFIG_H because we want that unit to
# include our config.h file. Otherwise, some system headers do not get
# included, and the compiler emits a warning about implicitly defined
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 16/16] gdbserver, linux, btrace: add btrace support for linux-low
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (7 preceding siblings ...)
2012-05-10 15:17 ` [PATCH 08/16] linux, btrace: perf_event based branch tracing markus.t.metzger
@ 2012-05-10 15:17 ` markus.t.metzger
2012-05-10 15:17 ` [PATCH 14/16] remote, btrace: add branch trace remote ops markus.t.metzger
` (7 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:17 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Implement btrace target ops in target linux-low using the common linux-btrace
functions.
Add linux-btrace.o to all targets that link linux-low.o. I'd rather not link it
to targets that do not support branch tracing, but this would require changing
the way target ops are defined for gdbserver.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/gdbserver/
* linux-low: Include linux-btrace.h
(linux_low_enable_btrace): New function
(linux_low_print_btrace_record): New function
(linux_low_read_btrace): New function
(linux_target_ops): Add btrace ops
* configure.srv: Add linux-btrace.o
---
gdb/gdbserver/configure.srv | 34 +++++++++++++++++-----------------
gdb/gdbserver/linux-low.c | 42 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 17 deletions(-)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index e6ae157..7f33dd1 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -47,7 +47,7 @@ case "${target}" in
srv_regobj="${srv_regobj} arm-with-vfpv3.o"
srv_regobj="${srv_regobj} arm-with-neon.o"
srv_tgtobj="linux-low.o linux-osdata.o linux-arm-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_xmlfiles="arm-with-iwmmxt.xml"
srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv2.xml"
srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv3.xml"
@@ -70,19 +70,19 @@ case "${target}" in
;;
bfin-*-*linux*) srv_regobj=reg-bfin.o
srv_tgtobj="linux-low.o linux-osdata.o linux-bfin-low.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_thread_db=yes
;;
crisv32-*-linux*) srv_regobj=reg-crisv32.o
srv_tgtobj="linux-low.o linux-osdata.o linux-crisv32-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
cris-*-linux*) srv_regobj=reg-cris.o
srv_tgtobj="linux-low.o linux-osdata.o linux-cris-low.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_thread_db=yes
;;
@@ -97,7 +97,7 @@ 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
@@ -129,12 +129,12 @@ case "${target}" in
;;
ia64-*-linux*) srv_regobj=reg-ia64.o
srv_tgtobj="linux-low.o linux-osdata.o linux-ia64-low.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
;;
m32r*-*-linux*) srv_regobj=reg-m32r.o
srv_tgtobj="linux-low.o linux-osdata.o linux-m32r-low.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_thread_db=yes
;;
@@ -144,7 +144,7 @@ case "${target}" in
srv_regobj=reg-m68k.o
fi
srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.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
@@ -155,7 +155,7 @@ case "${target}" in
srv_regobj=reg-m68k.o
fi
srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.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
@@ -165,7 +165,7 @@ case "${target}" in
srv_regobj="${srv_regobj} mips64-linux.o"
srv_regobj="${srv_regobj} mips64-dsp-linux.o"
srv_tgtobj="linux-low.o linux-osdata.o linux-mips-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_xmlfiles="mips-linux.xml"
srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
srv_xmlfiles="${srv_xmlfiles} mips-cpu.xml"
@@ -198,7 +198,7 @@ case "${target}" in
srv_regobj="${srv_regobj} powerpc-isa205-altivec64l.o"
srv_regobj="${srv_regobj} powerpc-isa205-vsx64l.o"
srv_tgtobj="linux-low.o linux-osdata.o linux-ppc-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_xmlfiles="rs6000/powerpc-32l.xml"
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml"
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell32l.xml"
@@ -241,7 +241,7 @@ case "${target}" in
srv_regobj="${srv_regobj} s390x-linux64v1.o"
srv_regobj="${srv_regobj} s390x-linux64v2.o"
srv_tgtobj="linux-low.o linux-osdata.o linux-s390-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_xmlfiles="s390-linux32.xml"
srv_xmlfiles="${srv_xmlfiles} s390-linux32v1.xml"
srv_xmlfiles="${srv_xmlfiles} s390-linux32v2.xml"
@@ -262,14 +262,14 @@ case "${target}" in
;;
sh*-*-linux*) srv_regobj=reg-sh.o
srv_tgtobj="linux-low.o linux-osdata.o linux-sh-low.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
;;
sparc*-*-linux*) srv_regobj=reg-sparc64.o
srv_tgtobj="linux-low.o linux-osdata.o linux-sparc-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
@@ -286,14 +286,14 @@ case "${target}" in
srv_xmlfiles="${srv_xmlfiles} tic6x-gp.xml"
srv_xmlfiles="${srv_xmlfiles} tic6x-c6xp.xml"
srv_tgtobj="linux-low.o linux-osdata.o linux-tic6x-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_linux_regsets=yes
srv_linux_usrregs=yes
srv_linux_thread_db=yes
;;
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
@@ -308,7 +308,7 @@ case "${target}" in
xtensa*-*-linux*) srv_regobj=reg-xtensa.o
srv_tgtobj="linux-low.o linux-osdata.o linux-xtensa-low.o linux-procfs.o"
- srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
+ srv_tgtobj="${srv_tgtobj} linux-ptrace.o linux-btrace.o"
srv_linux_regsets=yes
;;
*) echo "Error: target not supported by gdbserver."
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index bbb0693..a497d1b 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -20,6 +20,7 @@
#include "linux-low.h"
#include "linux-osdata.h"
#include "agent.h"
+#include "linux-btrace.h"
#include <sys/wait.h>
#include <stdio.h>
@@ -5731,6 +5732,42 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
return len;
}
+static int
+linux_low_print_btrace_record (struct linux_btrace_block *raw, void *arg)
+{
+ struct buffer *buffer = arg;
+
+ if (!raw)
+ return EINVAL;
+
+ if (!buffer)
+ return EINVAL;
+
+ buffer_xml_printf (buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
+ paddress (raw->begin), paddress (raw->end));
+
+ return 0;
+}
+
+static int
+linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer)
+{
+ int errcode;
+
+ if (!tinfo || !buffer)
+ return EINVAL;
+
+ if (!tinfo->ptr_bits)
+ tinfo->ptr_bits = register_size (0) * 8;
+
+ buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
+ buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
+ errcode = linux_read_btrace (tinfo, linux_low_print_btrace_record, buffer);
+ buffer_grow_str (buffer, "</btrace>\n");
+
+ return errcode;
+}
+
static struct target_ops linux_target_ops = {
linux_create_inferior,
linux_attach,
@@ -5795,6 +5832,11 @@ static struct target_ops linux_target_ops = {
linux_get_min_fast_tracepoint_insn_len,
linux_qxfer_libraries_svr4,
linux_supports_agent,
+ linux_supports_btrace,
+ linux_enable_btrace,
+ linux_disable_btrace,
+ linux_btrace_has_changed,
+ linux_low_read_btrace,
};
static void
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 14/16] remote, btrace: add branch trace remote ops
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (8 preceding siblings ...)
2012-05-10 15:17 ` [PATCH 16/16] gdbserver, linux, btrace: add btrace support for linux-low markus.t.metzger
@ 2012-05-10 15:17 ` markus.t.metzger
2012-05-10 15:17 ` [PATCH 03/16] source, disasm: optionally prefix source lines with filename markus.t.metzger
` (6 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:17 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add the gdb remote target operations for branch tracing. We define the following
packets:
qbtrace:<ptid> query if new trace data is available for a thread
returns "yes" or "no" or "Enn"
Qbtrace:on:<ptid> enable branch tracing for one thread
returns "OK" or "Enn"
Qbtrace:off:<ptid> disable branch tracing for one thread
returns "OK" or "Enn"
qXfer:btrace:read:<ptid> read the full branch trace data for one thread
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* target.h (enum target_object): Add TARGET_OBJECT_BTRACE
* remote.c (struct btrace_target_info): New struct
(remote_supports_btrace): New function
(remote_enable_btrace): New function
(remote_disable_btrace): New function
(remote_btrace_has_changed): 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 btrace packets
---
gdb/remote.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/target.h | 4 +-
2 files changed, 211 insertions(+), 1 deletions(-)
diff --git a/gdb/remote.c b/gdb/remote.c
index 68864d1..d1ed683 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -66,6 +66,7 @@
#include "ax.h"
#include "ax-gdb.h"
#include "agent.h"
+#include "btrace.h"
/* Temp hacks for tracepoint encoding migration. */
static char *target_buf;
@@ -1284,6 +1285,9 @@ enum {
PACKET_qXfer_fdpic,
PACKET_QDisableRandomization,
PACKET_QAgent,
+ PACKET_qbtrace,
+ PACKET_Qbtrace,
+ PACKET_qXfer_btrace,
PACKET_MAX
};
@@ -3925,6 +3929,10 @@ static struct protocol_feature remote_protocol_features[] = {
{ "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
{ "tracenz", PACKET_DISABLE,
remote_string_tracing_feature, -1 },
+ { "qbtrace", PACKET_DISABLE, remote_supported_packet, PACKET_qbtrace },
+ { "Qbtrace", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace },
+ { "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_btrace }
};
static char *remote_support_xml;
@@ -8588,6 +8596,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;
}
@@ -10900,6 +10912,188 @@ 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;
+};
+
+static int
+remote_supports_btrace (void)
+{
+ if (remote_protocol_packets[PACKET_qbtrace].support != PACKET_ENABLE)
+ return 0;
+ if (remote_protocol_packets[PACKET_Qbtrace].support != PACKET_ENABLE)
+ return 0;
+ if (remote_protocol_packets[PACKET_qXfer_btrace].support != PACKET_ENABLE)
+ return 0;
+
+ return 1;
+}
+
+static struct btrace_target_info *
+remote_enable_btrace (ptid_t ptid)
+{
+ struct packet_config *packet = &remote_protocol_packets[PACKET_Qbtrace];
+ struct remote_state *rs = get_remote_state ();
+ struct btrace_target_info *tinfo = NULL;
+ char *buf = rs->buf;
+ char *endbuf = rs->buf + get_remote_packet_size ();
+
+ if (packet->support != PACKET_ENABLE)
+ {
+ errno = ENOSYS;
+ return NULL;
+ }
+
+ buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
+ buf += xsnprintf (buf, endbuf - buf, ":on:");
+ buf = write_ptid (buf, endbuf, ptid);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ switch (packet_ok (rs->buf, packet))
+ {
+ case PACKET_OK:
+ tinfo = xzalloc (sizeof (*tinfo));
+ if (tinfo)
+ tinfo->ptid = ptid;
+ else
+ errno = ENOMEM;
+ break;
+ case PACKET_ERROR:
+ {
+ int pid = ptid_get_lwp (ptid);
+ if (!pid)
+ pid = ptid_get_pid (ptid);
+
+ error (_("Couldn't enable btrace for %d: %s"),
+ pid, rs->buf);
+ }
+ default:
+ errno = ENOSYS;
+ break;
+ }
+
+ return tinfo;
+}
+
+static int
+remote_disable_btrace (struct btrace_target_info *tinfo)
+{
+ struct packet_config *packet = &remote_protocol_packets[PACKET_Qbtrace];
+ struct remote_state *rs = get_remote_state ();
+ char *buf = rs->buf;
+ char *endbuf = rs->buf + get_remote_packet_size ();
+
+ if (!tinfo)
+ return EINVAL;
+
+ if (packet->support != PACKET_ENABLE)
+ return ENOSYS;
+
+ buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
+ buf += xsnprintf (buf, endbuf - buf, ":off:");
+ buf = write_ptid (buf, endbuf, tinfo->ptid);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ switch (packet_ok (rs->buf, packet))
+ {
+ case PACKET_OK:
+ xfree (tinfo);
+ return 0;
+
+ case PACKET_ERROR:
+ {
+ int pid = ptid_get_lwp (tinfo->ptid);
+ if (!pid)
+ pid = ptid_get_pid (tinfo->ptid);
+
+ error (_("Couldn't disable btrace for %d: %s"),
+ pid, rs->buf);
+ }
+ default:
+ return ENOSYS;
+ }
+}
+
+static int
+remote_btrace_has_changed (struct btrace_target_info *tinfo)
+{
+ struct packet_config *packet = &remote_protocol_packets[PACKET_qbtrace];
+ struct remote_state *rs = get_remote_state ();
+ char *buf = rs->buf;
+ char *endbuf = rs->buf + get_remote_packet_size ();
+
+ if (!tinfo)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+ if (packet->support != PACKET_ENABLE)
+ {
+ errno = ENOSYS;
+ return 0;
+ }
+
+ buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
+ buf += xsnprintf (buf, endbuf - buf, ":");
+ buf = write_ptid (buf, endbuf, tinfo->ptid);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ switch (packet_ok (rs->buf, packet))
+ {
+ case PACKET_OK:
+ return (strcmp (rs->buf, "yes") == 0);
+ case PACKET_ERROR:
+ error (_("%s"), rs->buf);
+ default:
+ errno = ENOSYS;
+ return 0;
+ }
+}
+
+static VEC (btrace_block_s) *
+remote_read_btrace (struct btrace_target_info *tinfo)
+{
+ struct packet_config *packet = &remote_protocol_packets[PACKET_qXfer_btrace];
+ struct remote_state *rs = get_remote_state ();
+ char *xml, annex[64], *pend;
+ VEC (btrace_block_s) *btrace = NULL;
+
+ if (!tinfo)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (packet->support != PACKET_ENABLE)
+ {
+ errno = ENOSYS;
+ return NULL;
+ }
+
+#if !defined(HAVE_LIBEXPAT)
+ errno = ENOSYS;
+ return NULL;
+#endif
+
+ memset (annex, 0, sizeof (annex));
+ pend = write_ptid (annex, annex + sizeof (annex), tinfo->ptid);
+
+ xml = target_read_stralloc (¤t_target,
+ TARGET_OBJECT_BTRACE, annex);
+ if (xml)
+ {
+ struct cleanup *cleanup = make_cleanup (xfree, xml);
+ btrace = parse_xml_btrace (xml);
+ do_cleanups (cleanup);
+ }
+
+ return btrace;
+}
+
static void
init_remote_ops (void)
{
@@ -11015,6 +11209,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_btrace_has_changed = remote_btrace_has_changed;
+ remote_ops.to_read_btrace = remote_read_btrace;
}
/* Set up the extended remote vector by making a copy of the standard
@@ -11537,6 +11736,15 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (&remote_protocol_packets[PACKET_QAgent],
"QAgent", "agent", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qbtrace],
+ "qbtrace", "query-btrace", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace],
+ "Qbtrace", "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
diff --git a/gdb/target.h b/gdb/target.h
index b54bbc1..8080a1d 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -283,7 +283,9 @@ enum target_object
/* Darwin dynamic linker info data. */
TARGET_OBJECT_DARWIN_DYLD_INFO,
/* OpenVMS Unwind Information Block. */
- TARGET_OBJECT_OPENVMS_UIB
+ TARGET_OBJECT_OPENVMS_UIB,
+ /* Branch trace data, in XML format. */
+ TARGET_OBJECT_BTRACE
/* Possible future objects: TARGET_OBJECT_FILE, ... */
};
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 03/16] source, disasm: optionally prefix source lines with filename
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (9 preceding siblings ...)
2012-05-10 15:17 ` [PATCH 14/16] remote, btrace: add branch trace remote ops markus.t.metzger
@ 2012-05-10 15:17 ` markus.t.metzger
2012-05-10 15:18 ` [PATCH 06/16] configure: add check for perf_event header markus.t.metzger
` (5 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:17 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add respective flags to print_source_lines () and gdb_disassembly () to prefix
the source line with its file name.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* disasm.h (DISASSEMBLY_FILENAME): New macro
* disasm.c (do_mixed_source_and_assembly): Pass filename flag on to
print_source_lines ().
* symtab.h (PRINT_SOURCE_LINES_FILENAME): New print source lines flag
* source.c (print_source_lines_base): Prefix source line with filename if
PRINT_SOURCE_LINES_FILENAME flag is set.
---
gdb/disasm.c | 12 ++++++++----
gdb/disasm.h | 1 +
gdb/source.c | 5 +++++
gdb/symtab.h | 3 ++-
4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/gdb/disasm.c b/gdb/disasm.c
index 4902d95..d0a0be4 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -204,10 +204,14 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
int out_of_order = 0;
int next_line = 0;
int num_displayed = 0;
+ int psl_flags = 0;
struct cleanup *ui_out_chain;
struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
+ if (flags & DISASSEMBLY_FILENAME)
+ psl_flags |= PRINT_SOURCE_LINES_FILENAME;
+
mle = (struct dis_line_entry *) alloca (nlines
* sizeof (struct dis_line_entry));
@@ -295,7 +299,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
ui_out_tuple_chain
= make_cleanup_ui_out_tuple_begin_end (uiout,
"src_and_asm_line");
- print_source_lines (symtab, next_line, mle[i].line + 1, 0);
+ print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
}
else
{
@@ -309,7 +313,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
= make_cleanup_ui_out_tuple_begin_end (uiout,
"src_and_asm_line");
print_source_lines (symtab, next_line, next_line + 1,
- 0);
+ psl_flags);
ui_out_list_chain_line
= make_cleanup_ui_out_list_begin_end (uiout,
"line_asm_insn");
@@ -321,7 +325,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
ui_out_tuple_chain
= make_cleanup_ui_out_tuple_begin_end (uiout,
"src_and_asm_line");
- print_source_lines (symtab, next_line, mle[i].line + 1, 0);
+ print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
}
}
else
@@ -329,7 +333,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
ui_out_tuple_chain
= make_cleanup_ui_out_tuple_begin_end (uiout,
"src_and_asm_line");
- print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
+ print_source_lines (symtab, mle[i].line, mle[i].line + 1, psl_flags);
}
next_line = mle[i].line + 1;
diff --git a/gdb/disasm.h b/gdb/disasm.h
index 5b459f4..5ae71c9 100644
--- a/gdb/disasm.h
+++ b/gdb/disasm.h
@@ -23,6 +23,7 @@
#define DISASSEMBLY_RAW_INSN (0x1 << 1)
#define DISASSEMBLY_OMIT_FNAME (0x1 << 2)
#define DISASSEMBLY_PRECISE_INSN (0x1 << 3)
+#define DISASSEMBLY_FILENAME (0x1 << 4)
struct ui_out;
struct ui_file;
diff --git a/gdb/source.c b/gdb/source.c
index 4dd7ed2..a1ca6d3 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -1315,6 +1315,11 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int flags)
if (c == EOF)
break;
last_line_listed = current_source_line;
+ if (flags & PRINT_SOURCE_LINES_FILENAME)
+ {
+ ui_out_text (uiout, s->filename);
+ ui_out_text (uiout, ":");
+ }
sprintf (buf, "%d\t", current_source_line++);
ui_out_text (uiout, buf);
do
diff --git a/gdb/symtab.h b/gdb/symtab.h
index b252725..62a6a7b 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1128,7 +1128,8 @@ extern int identify_source_line (struct symtab *, int, int, CORE_ADDR);
/* Flags passed as 4th argument to print_source_lines. */
enum print_source_lines_flags {
- PRINT_SOURCE_LINES_NOERROR = (0x1 << 0)
+ PRINT_SOURCE_LINES_NOERROR = (0x1 << 0),
+ PRINT_SOURCE_LINES_FILENAME = (0x1 << 1)
};
extern void print_source_lines (struct symtab *, int, int, int);
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 06/16] configure: add check for perf_event header
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (10 preceding siblings ...)
2012-05-10 15:17 ` [PATCH 03/16] source, disasm: optionally prefix source lines with filename markus.t.metzger
@ 2012-05-10 15:18 ` markus.t.metzger
2012-05-10 15:18 ` [PATCH 12/16] test, btrace: more branch tracing tests markus.t.metzger
` (4 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:18 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* configure.ac: check for linux/perf_event.h
gdb/gdbserver/
* configure.ac: check for linux/perf_event.h
---
gdb/configure.ac | 2 ++
gdb/gdbserver/configure.ac | 2 +-
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/gdb/configure.ac b/gdb/configure.ac
index ce7515b..b9c0abf 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1044,6 +1044,8 @@ AC_CHECK_HEADERS(term.h, [], [],
#endif
])
+AC_CHECK_HEADERS(linux/perf_event.h)
+
# ------------------------- #
# Checks for declarations. #
# ------------------------- #
diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac
index 7013a21..f6748af 100644
--- a/gdb/gdbserver/configure.ac
+++ b/gdb/gdbserver/configure.ac
@@ -55,7 +55,7 @@ AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h string.h dnl
stdlib.h unistd.h dnl
errno.h fcntl.h signal.h sys/file.h malloc.h dnl
sys/ioctl.h netinet/in.h sys/socket.h netdb.h dnl
- netinet/tcp.h arpa/inet.h sys/wait.h sys/un.h)
+ netinet/tcp.h arpa/inet.h sys/wait.h sys/un.h linux/perf_event.h)
AC_CHECK_FUNCS(pread pwrite pread64 readlink)
AC_REPLACE_FUNCS(vasprintf vsnprintf)
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 12/16] test, btrace: more branch tracing tests
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (11 preceding siblings ...)
2012-05-10 15:18 ` [PATCH 06/16] configure: add check for perf_event header markus.t.metzger
@ 2012-05-10 15:18 ` markus.t.metzger
2012-05-10 15:18 ` [PATCH 09/16] btrace, linux: add linux native btrace target ops markus.t.metzger
` (3 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:18 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Barkha Ahuja
From: Barkha Ahuja <barkha.ahuja@intel.com>
Non-stop tests are failing with gdbserver.
2012-05-10 Barkha Ahuja <barkha.ahuja@intel.com>
gdb/testsuite/gdb.btrace/
* a.s: New file
* allthreads_trace.exp: New file
* b.s: New file
* decrement.exp: New file
* decrement.s: New file
* disable_all.exp: New file
* enable_all.exp: New file
* enable_range.exp: New file
* list_options.exp: New file
* main.s: New file
* main_asm.exp: New file
* main_segv.exp: New file
* main_segv.s: New file
* sanity_crash.exp: New file
* sanity_crash.s: New file
* thr_callback_32.s: New file
* thr_callback_64.s: New file
* threads.c: New file
* threads_asm.c: New file
* threads_auto.exp: New file
* threads_independent.exp: New file
* threads_nonstop.exp: New file
* trace_iteration.exp: New file
---
gdb/testsuite/gdb.btrace/a.s | 24 ++
gdb/testsuite/gdb.btrace/allthreads_trace.exp | 270 ++++++++++++++++++++++
gdb/testsuite/gdb.btrace/b.s | 23 ++
gdb/testsuite/gdb.btrace/decrement.exp | 140 +++++++++++
gdb/testsuite/gdb.btrace/decrement.s | 32 +++
gdb/testsuite/gdb.btrace/disable_all.exp | 198 ++++++++++++++++
gdb/testsuite/gdb.btrace/enable_all.exp | 201 ++++++++++++++++
gdb/testsuite/gdb.btrace/enable_range.exp | 198 ++++++++++++++++
gdb/testsuite/gdb.btrace/list_options.exp | 107 +++++++++
gdb/testsuite/gdb.btrace/main.s | 32 +++
gdb/testsuite/gdb.btrace/main_asm.exp | 113 +++++++++
gdb/testsuite/gdb.btrace/main_segv.exp | 84 +++++++
gdb/testsuite/gdb.btrace/main_segv.s | 28 +++
gdb/testsuite/gdb.btrace/sanity_crash.exp | 69 ++++++
gdb/testsuite/gdb.btrace/sanity_crash.s | 52 ++++
gdb/testsuite/gdb.btrace/thr_callback_32.s | 116 +++++++++
gdb/testsuite/gdb.btrace/thr_callback_64.s | 116 +++++++++
gdb/testsuite/gdb.btrace/threads.c | 96 ++++++++
gdb/testsuite/gdb.btrace/threads_asm.c | 78 +++++++
gdb/testsuite/gdb.btrace/threads_auto.exp | 113 +++++++++
gdb/testsuite/gdb.btrace/threads_independent.exp | 119 ++++++++++
gdb/testsuite/gdb.btrace/threads_nonstop.exp | 182 +++++++++++++++
gdb/testsuite/gdb.btrace/trace_iteration.exp | 264 +++++++++++++++++++++
23 files changed, 2655 insertions(+), 0 deletions(-)
create mode 100755 gdb/testsuite/gdb.btrace/a.s
create mode 100755 gdb/testsuite/gdb.btrace/allthreads_trace.exp
create mode 100755 gdb/testsuite/gdb.btrace/b.s
create mode 100755 gdb/testsuite/gdb.btrace/decrement.exp
create mode 100755 gdb/testsuite/gdb.btrace/decrement.s
create mode 100755 gdb/testsuite/gdb.btrace/disable_all.exp
create mode 100755 gdb/testsuite/gdb.btrace/enable_all.exp
create mode 100755 gdb/testsuite/gdb.btrace/enable_range.exp
create mode 100755 gdb/testsuite/gdb.btrace/list_options.exp
create mode 100755 gdb/testsuite/gdb.btrace/main.s
create mode 100755 gdb/testsuite/gdb.btrace/main_asm.exp
create mode 100755 gdb/testsuite/gdb.btrace/main_segv.exp
create mode 100755 gdb/testsuite/gdb.btrace/main_segv.s
create mode 100755 gdb/testsuite/gdb.btrace/sanity_crash.exp
create mode 100755 gdb/testsuite/gdb.btrace/sanity_crash.s
create mode 100755 gdb/testsuite/gdb.btrace/thr_callback_32.s
create mode 100755 gdb/testsuite/gdb.btrace/thr_callback_64.s
create mode 100755 gdb/testsuite/gdb.btrace/threads.c
create mode 100755 gdb/testsuite/gdb.btrace/threads_asm.c
create mode 100755 gdb/testsuite/gdb.btrace/threads_auto.exp
create mode 100755 gdb/testsuite/gdb.btrace/threads_independent.exp
create mode 100755 gdb/testsuite/gdb.btrace/threads_nonstop.exp
create mode 100755 gdb/testsuite/gdb.btrace/trace_iteration.exp
diff --git a/gdb/testsuite/gdb.btrace/a.s b/gdb/testsuite/gdb.btrace/a.s
new file mode 100755
index 0000000..75e7ba3
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/a.s
@@ -0,0 +1,24 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+ .text
+ .globl callA
+ .type callA, @function
+callA:
+ nop
+ ret
+
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.btrace/allthreads_trace.exp b/gdb/testsuite/gdb.btrace/allthreads_trace.exp
new file mode 100755
index 0000000..250e24d
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/allthreads_trace.exp
@@ -0,0 +1,270 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, Enable trace for all the threads by "btr enable auto" on primary thread and check the trace availability for all the threads
+# Sourcefiles : threads_asm.c, thr_callback_32.s, thr_callback_64.s
+# Compiled using '-g -lpthread' option.
+#executed as :
+# make check RUNTESTFLAGS="GDB=<path to gdb> gdb.trace/allthreads_trace.exp"
+###############
+
+load_lib btrace.exp
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/allthreads_trace.x
+set options "{debug}"
+
+#Load different callback files for 32 and 64 bit.
+# 32 bit platform
+if {[ishost "i?86-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/thr_callback_32.s
+} elseif {[ishost "x86_64-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/thr_callback_64.s
+} else {
+ warning "host platform not supported "
+ untested allthreads_trace.exp
+ return -1
+}
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} {
+ untested allthreads_trace.exp
+ return -1
+}
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} {
+ untested allthreads_trace.exp
+ return -1
+}
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested allthreads_trace.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+runto main
+# set breakpoint at line 67, at call to mybarrier() for primary thread.
+gdb_breakpoint "67" "Breakpoint 2 at.*: file.*threads_asm.c, line 67." " breakpoint at line 67, 1.1"
+
+# set a breakpoint at mybarrier() to halt all the new threads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 3, mybarrier \\(\\) at .*thr_callback_...s:114" "Breakpoint at my barrier for all the threads to stop, 1.2"
+
+# enable trace in primary thread, which automatically enables trace in all new threads crated.
+gdb_test "btr enable auto"
+send_gdb "continue\n"
+gdb_expect 8 {
+ -re "Breakpoint 3, mybarrier \\(\\) at.*thr_callback_...s:114.*"
+ {
+ pass "continuing"
+ }
+ }
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# We need to do a seperate listing from here, since the instr length is different
+# on different platforms.
+gdb_test "thread 2" ".*Switching to thread 2.*mybarrier.*" " switch to thread 2, 1.3"
+# 64 bit platform
+if {[ishost "x86_64-*-*"]} {
+
+# trace for thread 2
+gdb_test "btr list /a" "
+1 0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+2 0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+.*" "BTR listing for thread 2, 1.4"
+
+gdb_test "btr /m 1" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 2, 1.5"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_a\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_a\\+19>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 2, 1.6"
+
+# trace for thread 3
+gdb_test "thread 3" ".*Switching to thread 3.*mybarrier.*" " switch to thread 3, 1.7"
+
+gdb_test "btr list /la" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*thr_callback_64.s:112-114\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*thr_callback_64.s:44-45\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*thr_callback_64.s:85-89\r
+4 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*thr_callback_64.s:40-43\r
+.*" "BTR listing for thread 3, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 3, 1.9"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_b\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_b\\+19>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 3, 1.10"
+
+# trace for thread 4
+gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " switch to thread 4, 1.11"
+
+gdb_test "btr list /lf" "
+1 *in mybarrier \\(\\) at.*thr_callback_64.s:112-114\r
+2 *in th_c \\(\\) at.*thr_callback_64.s:56-57\r
+3 *in call_C \\(\\) at.*thr_callback_64.s:94-98\r
+4 *in th_c \\(\\) at.*thr_callback_64.s:52-55\r
+.*" "BTR listing for thread 4, 1.12"
+
+gdb_test "btr /m 1" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 4, 1.13"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_c\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_c\\+19>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 4, 1.14"
+
+# trace for thread 5
+gdb_test "thread 5" ".*Switching to thread 5.*mybarrier.*" " switch to thread 5, 1.15"
+
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in mybarrier \\(\\)\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_d \\(\\)\r
+.*" "BTR listing for thread 5, 1.16"
+
+gdb_test "btr " "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 5, 1.17"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_d\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_d\\+19>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 5, 1.18"
+
+ gdb_test "btr +" "
+ *0x\[a-f0-9\]* <call_D\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <call_D\\+1>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_D\\+4>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_D\\+9>:\[\[:blank:\]\]*leave.*\r
+ *0x\[a-f0-9\]* <call_D\\+10>:\[\[:blank:\]\]*ret.*\r" " BTR of 3 for thread 5, 1.19"
+
+} elseif {[ishost "i?86-*-*"]} {
+# 32 bit platform
+
+#trace for thread 2
+gdb_test "btr list /a" "
+1 0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+2 0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+.*" "BTR listing for thread 2, 1.4"
+
+gdb_test "btr /m 1" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 2, 1.5"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_a\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_a\\+18>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 2, 1.6"
+
+gdb_test "thread 3" ".*Switching to thread 3.*mybarrier.*" " switch to thread 3, 1.7"
+
+#trace for thread 3
+gdb_test "btr list /la" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*thr_callback_32.s:112-114\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*thr_callback_32.s:44-45\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*thr_callback_32.s:85-89\r
+4 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* at .*thr_callback_32.s:40-43\r
+.*" "BTR listing for thread 3, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 3, 1.9"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_b\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_b\\+18>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 3, 1.10"
+
+gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " switch to thread 4, 1.11"
+
+#trace for thread 4
+gdb_test "btr list /lf" "
+1 *in mybarrier \\(\\) at.*thr_callback_32.s:112-114\r
+2 *in th_c \\(\\) at.*thr_callback_32.s:56-57\r
+3 *in call_C \\(\\) at.*thr_callback_32.s:94-98\r
+4 *in th_c \\(\\) at.*thr_callback_32.s:52-55\r
+.*" "BTR listing for thread 4, 1.12"
+
+gdb_test "btr /m 1" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 4, 1.13"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_c\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_c\\+18>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 4, 1.14"
+
+gdb_test "thread 5" ".*Switching to thread 5.*mybarrier.*" " switch to thread 5, 1.15"
+
+#trace for thread 5
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in mybarrier \\(\\)\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_d \\(\\)\r
+.*" "BTR listing for thread 5, 1.16"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> *0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" " BTR of 1 for thread 5, 1.17"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_d\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_d\\+18>:\[\[:blank:\]\]*call.*" " BTR of 2 for thread 5, 1.18"
+
+ gdb_test "btr +" "
+ *0x\[a-f0-9\]* <call_D\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <call_D\\+1>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_D\\+3>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_D\\+8>:\[\[:blank:\]\]*leave.*\r
+ *0x\[a-f0-9\]* <call_D\\+9>:\[\[:blank:\]\]*ret.*\r" " BTR of 3 for thread 5, 1.19"
+
+} else {
+ note "Platform not supported"
+ untested allthreads_trace.exp
+}
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.btrace/b.s b/gdb/testsuite/gdb.btrace/b.s
new file mode 100755
index 0000000..271091f
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/b.s
@@ -0,0 +1,23 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+ .text
+ .globl callB
+ .type callB, @function
+callB:
+ nop
+ ret
diff --git a/gdb/testsuite/gdb.btrace/decrement.exp b/gdb/testsuite/gdb.btrace/decrement.exp
new file mode 100755
index 0000000..11f3900
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/decrement.exp
@@ -0,0 +1,140 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+
+###############
+#Test Purpose: Fix a location while linking, where teh debuggee will be loaded and then
+# see that trace gives the correct addresses.
+# Source file: decrement.s
+###############
+
+load_lib btrace.exp
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+set srcfile ${srcdir}/${subdir}/decrement.s
+set objfile ${objdir}/${subdir}/decrement.o
+set binfile ${objdir}/${subdir}/decrement.x
+set options "{debug}"
+#compile
+if {[target_assemble ${srcfile} ${objfile} ""] != ""} { return "" }
+#link
+if {[target_link ${objfile} ${binfile} " -Ttext 0x400400 "] != ""} {
+ untested decrement.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+
+# Make sure we don't die when enabling trace for a newly created thread.
+runto L1
+
+# Enable branch trace to trace the startup.
+gdb_test_no_output "btr enable"
+
+# Reset branch trace so we get predictable output.
+btrace_reset_trace
+
+gdb_test "next" "0x0*40041a in L1.*" ""
+
+gdb_test "btr list /lfa" "
+1 *0x0*40041a - 0x0*40041a in L1 \\(\\)" "list L1, 1.1"
+
+gdb_continue_to_breakpoint "L1"
+
+if {[ishost "x86_64-*-*"]} {
+#We enter the loop for 5 times from here.
+gdb_test "btr list /lfa" "
+1 *0x0*40041a - 0x0*40041a in L1 \\(\\)\r
+2 *0x0*40041a - 0x0*400421 in L1 \\(\\)" "list L1 again , 1.2"
+} elseif {[ishost "i?86-*-*"]} {
+#We enter the loop for 5 times from here.
+gdb_test "btr list /lfa" "
+1 *0x0*40041a - 0x0*40041a in L1 \\(\\)\r
+2 *0x0*40041a - 0x0*400420 in L1 \\(\\)" "list L1 again, 1.2"
+}
+
+#Delete all Breakpoints
+delete_breakpoints
+
+#Set a Breakpoint at L2
+gdb_breakpoint "L2"
+
+#Continue to L2
+gdb_continue_to_breakpoint "L2"
+
+if {[ishost "x86_64-*-*"]} {
+# BTR listing in method L2, when the loop exits
+gdb_test "btr list /lfa" "
+1 *0x0*400423 - 0x0*400423 in L2 \\(\\)\r
+2 *0x0*40041a - 0x0*40041d in L1 \\(\\)\r
+3 *0x0*40041a - 0x0*400421 in L1 \\(\\)\r
+4 *0x0*40041a - 0x0*400421 in L1 \\(\\)\r
+5 *0x0*40041a - 0x0*400421 in L1 \\(\\)\r
+6 *0x0*40041a - 0x0*400421 in L1 \\(\\)\r" "BTR listing at L2, 1.3"
+
+# Exit the loop
+gdb_test "btr /m 1" "
+=> 0x0*400423 *<L2\\+0>:\[\[:blank:\]\]*ret.*\r" "BTR at block 1, 1.4"
+
+# Comparison, if we are exiting the loop
+gdb_test "btr /m 2" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 *<L2>" "BTR at block 2, 1.5"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at block 3, 1.6"
+
+} elseif {[ishost "i?86-*-*"]} {
+# BTR listing in method L2, when the loop exits
+gdb_test "btr list /lfa" "
+1 *0x0*400422 - 0x0*400422 in L2 \\(\\)\r
+2 *0x0*40041a - 0x0*40041d in L1 \\(\\)\r
+3 *0x0*40041a - 0x0*400420 in L1 \\(\\)\r
+4 *0x0*40041a - 0x0*400420 in L1 \\(\\)\r
+5 *0x0*40041a - 0x0*400420 in L1 \\(\\)\r
+6 *0x0*40041a - 0x0*400420 in L1 \\(\\)\r" "BTR listing at L2, 1.3"
+
+# Exit the loop
+gdb_test "btr /m 1" "
+=> 0x0*400422 *<L2\\+0>:\[\[:blank:\]\]*ret.*\r" "BTR at block 1, 1.4"
+
+# Comparison, if we are exiting the loop
+gdb_test "btr /m 2" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 *<L2>" "BTR at block 2, 1.5"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at block 3, 1.6"
+
+} else {
+ warning "host platform not supported "
+ return -1
+}
+
diff --git a/gdb/testsuite/gdb.btrace/decrement.s b/gdb/testsuite/gdb.btrace/decrement.s
new file mode 100755
index 0000000..c94a98a
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/decrement.s
@@ -0,0 +1,32 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+#
+#Decrements the number 5 by 1 untill it is 0. The
+ .text
+ .globl _start
+_start:
+ .align 0x10 # 0x400010
+ movl $5, %eax
+ .align 0x10 # 0x400010
+ movl $1, %ebx
+ call L1
+
+L1: cmpl $0, %eax #compare 0 with value in eax
+ je L2 #jump to L2 if 0==eax (je - jump if equal)
+ decl %eax #decrement eax
+ jmp L1 # unconditional jump to L1
+L2: ret
diff --git a/gdb/testsuite/gdb.btrace/disable_all.exp b/gdb/testsuite/gdb.btrace/disable_all.exp
new file mode 100755
index 0000000..7f67503
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/disable_all.exp
@@ -0,0 +1,198 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, Enable trace for all the threads by "btr enable auto" on primary thread and check the trace availability for all the threads
+# Sourcefiles : threads_asm.c, thr_callback_32.s, thr_callback_64.s
+# Compiled using '-g -lpthread' option.
+#executed on 32 bit as :
+# make check RUNTESTFLAGS="GDB=/users/bahuja/work_gdb/gdb_32/gdb --host i686-linux-gnu --target i686-linux-gnu gdb.trace/thread_auto.exp"
+#executed on 64 bit as :
+# make check RUNTESTFLAGS="GDB=/users/bahuja/work_gdb/gdb_32/gdb --host x86_64-linux-gnu --target x86_64-linux-gnu gdb.trace/thread_auto.exp"
+###############
+
+load_lib btrace.exp
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/disable_all.x
+set options "{debug}"
+
+#Load different callback files for 32 and 64 bit.
+# 32 bit platform
+if {[ishost "i?86-*-*"]} {
+ note "This is 32 bit host."
+ set srccallback ${srcdir}/${subdir}/thr_callback_32.s
+} elseif {[ishost "x86_64-*-*"]} {
+ note "This is 64 bit host."
+ set srccallback ${srcdir}/${subdir}/thr_callback_64.s
+} else {
+ warning "host platform not supported "
+ untested disable_all.exp
+ return -1
+}
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} {
+ untested disable_all.exp
+ return -1
+}
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} {
+ untested disable_all.exp
+ return -1
+}
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested disable_all.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+runto main
+# set breakpoint at line 67, at call to mybarrier() for primary thread.
+gdb_breakpoint "67" "Breakpoint 2 at.*: file.*threads_asm.c, line 67." " breakpoint at line 67, 1.1"
+
+# set a breakpoint at mybarrier() to halt all the new threads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 3, mybarrier \\(\\) at .*thr_callback_...s:114" "Breakpoint at my barrier for all the threads to stop, 1.2"
+
+gdb_breakpoint "${srccallback}:35" "Breakpoint 4 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 35." "Breakpoint after the barrier for thread 2, 1.3"
+
+gdb_breakpoint "${srccallback}:47" "Breakpoint 5 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 47." "Breakpoint after the barrier for thread 3, 1.4"
+gdb_breakpoint "${srccallback}:59" "Breakpoint 6 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 59." "Breakpoint after the barrier for thread 4, 1.5"
+gdb_breakpoint "${srccallback}:71" "Breakpoint 7 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 71." "Breakpoint after the barrier for thread 5, 1.6"
+
+# enable trace in primary thread, which automatically enables trace in all new threads crated.
+gdb_test "btr enable auto"
+send_gdb "continue\n"
+gdb_expect 8 {
+ -re "Breakpoint 3, mybarrier \\(\\) at.*thr_callback_...s:114.*"
+ {
+ pass "continuing"
+ }
+ }
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# Enable btrace on all threads
+gdb_test "btr disable all"
+
+# We need to do a seperate listing from here, since the instr length is different
+# on different platforms.
+gdb_test "thread 2" ".*Switching to thread 2.*mybarrier.*" " switch to thread 2, 1.7"
+# 64 bit platform
+if {[ishost "x86_64-*-*"]} {
+note "64 bit platform"
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr_callback_...s:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+No trace." " BTR of thread 2, 1.9"
+
+# trace for thread 3
+gdb_test "thread 3" ".*Switching to thread 3.*mybarrier.*" " switch to thread 3, 1.10"
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr_callback_...s:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+No trace." " BTR of thread 3, 1.12"
+
+# trace for thread 4
+gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " switch to thread 4, 1.13"
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr_callback_...s:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+No trace." " BTR of thread 4, 1.15"
+
+# trace for thread 5
+gdb_test "thread 5" ".*Switching to thread 5.*mybarrier.*" " switch to thread 5, 1.16"
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr_callback_...s:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+No trace." " BTR of thread 5, 1.18"
+
+} elseif {[ishost "i?86-*-*"]} {
+# 32 bit platform
+note "32 bit platform"
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr_callback_...s:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+No trace." " BTR of thread 2, 1.9"
+
+# trace for thread 3
+gdb_test "thread 3" ".*Switching to thread 3.*mybarrier.*" " switch to thread 3, 1.10"
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr_callback_...s:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+No trace." " BTR of thread 3, 1.12"
+
+# trace for thread 4
+gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " switch to thread 4, 1.13"
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr_callback_...s:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+No trace." " BTR of thread 4, 1.15"
+
+# trace for thread 5
+gdb_test "thread 5" ".*Switching to thread 5.*mybarrier.*" " switch to thread 5, 1.16"
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr_callback_...s:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+No trace." " BTR of thread 5, 1.18"
+
+} else {
+ note "Platform not supported"
+}
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.btrace/enable_all.exp b/gdb/testsuite/gdb.btrace/enable_all.exp
new file mode 100755
index 0000000..2ccd02c
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/enable_all.exp
@@ -0,0 +1,201 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, Enable trace for all the threads by "btr enable auto" on primary thread and check the trace availability for all the threads
+# Sourcefiles : threads_asm.c, thr_callback_32.s, thr_callback_64.s
+# Compiled using '-g -lpthread' option.
+#executed on 32 bit as :
+# make check RUNTESTFLAGS="GDB=<path to gdb> gdb.trace/enable_all.exp"
+###############
+
+load_lib btrace.exp
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/enable_all.x
+set options "{debug}"
+
+#Load different callback files for 32 and 64 bit.
+# 32 bit platform
+if {[ishost "i?86-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/thr_callback_32.s
+} elseif {[ishost "x86_64-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/thr_callback_64.s
+} else {
+ warning "host platform not supported "
+ untested enable_all.exp
+ return -1
+}
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} {
+ untested enable_all.exp
+ return -1
+}
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} {
+ untested enable_all.exp
+ return -1
+}
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested enable_all.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+runto main
+# set breakpoint at line 67, at call to mybarrier() for primary thread.
+gdb_breakpoint "67" "Breakpoint 2 at.*: file.*threads_asm.c, line 67." " breakpoint at line 67, 1.1"
+
+# set a breakpoint at mybarrier() to halt all the new threads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 3, mybarrier \\(\\) at .*thr_callback_...s:114" "Breakpoint at my barrier for all the threads to stop, 1.2"
+
+gdb_breakpoint "${srccallback}:35" "Breakpoint 4 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 35." "Breakpoint after the barrier for thread 2, 1.3"
+
+gdb_breakpoint "${srccallback}:47" "Breakpoint 5 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 47." "Breakpoint after the barrier for thread 3, 1.4"
+gdb_breakpoint "${srccallback}:59" "Breakpoint 6 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 59." "Breakpoint after the barrier for thread 4, 1.5"
+gdb_breakpoint "${srccallback}:71" "Breakpoint 7 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 71." "Breakpoint after the barrier for thread 5, 1.6"
+
+# enable trace in primary thread, which automatically enables trace in all new threads crated.
+#gdb_test "btr enable all"
+send_gdb "continue\n"
+gdb_expect 8 {
+ -re "Breakpoint 3, mybarrier \\(\\) at.*thr_callback_...s:114.*"
+ {
+ pass "continuing"
+ }
+ }
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# Enable btrace on all threads
+gdb_test "btr enable all"
+
+# We need to do a seperate listing from here, since the instr length is different
+# on different platforms.
+gdb_test "thread 2" ".*Switching to thread 2.*mybarrier.*" " switch to thread 2, 1.7"
+# 64 bit platform
+if {[ishost "x86_64-*-*"]} {
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr_callback_...s:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_a\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_a\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 2, 1.9"
+
+# trace for thread 3
+gdb_test "thread 3" ".*Switching to thread 3.*mybarrier.*" " switch to thread 3, 1.10"
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr_callback_...s:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_b\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_b\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 3, 1.12"
+
+# trace for thread 4
+gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " switch to thread 4, 1.13"
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr_callback_...s:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_c\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_c\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 4, 1.15"
+
+# trace for thread 5
+gdb_test "thread 5" ".*Switching to thread 5.*mybarrier.*" " switch to thread 5, 1.16"
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr_callback_...s:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_d\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_d\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 5, 1.18"
+
+} elseif {[ishost "i?86-*-*"]} {
+# 32 bit platform
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr_callback_...s:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_a\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_a\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 2, 1.9"
+
+# trace for thread 3
+gdb_test "thread 3" ".*Switching to thread 3.*mybarrier.*" " switch to thread 3, 1.10"
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr_callback_...s:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_b\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_b\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 3, 1.12"
+
+# trace for thread 4
+gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " switch to thread 4, 1.13"
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr_callback_...s:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_c\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_c\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 4, 1.15"
+
+# trace for thread 5
+gdb_test "thread 5" ".*Switching to thread 5.*mybarrier.*" " switch to thread 5, 1.16"
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr_callback_...s:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_d\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_d\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 5, 1.18"
+
+} else {
+ note "Platform not supported"
+ untested enable_all.exp
+}
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.btrace/enable_range.exp b/gdb/testsuite/gdb.btrace/enable_range.exp
new file mode 100755
index 0000000..509f93c
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/enable_range.exp
@@ -0,0 +1,198 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, Enable trace for a range of threads on primary thread and check the trace availability for all the threads
+# Sourcefiles : threads_asm.c, thr_callback_32.s, thr_callback_64.s
+# Compiled using '-g -lpthread' option.
+#executed on 32 bit as :
+# make check RUNTESTFLAGS="GDB=<path to gdb> gdb.trace/enable_range.exp"
+###############
+
+load_lib btrace.exp
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/enable_range.x
+set options "{debug}"
+
+#Load different callback files for 32 and 64 bit.
+# 32 bit platform
+if {[ishost "i?86-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/thr_callback_32.s
+} elseif {[ishost "x86_64-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/thr_callback_64.s
+} else {
+ warning "host platform not supported "
+ untested enable_range.exp
+ return -1
+}
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} {
+ untested enable_range.exp
+ return -1
+}
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} {
+ untested enable_range.exp
+ return -1
+}
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested enable_range.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+runto main
+# set breakpoint at line 67, at call to mybarrier() for primary thread.
+gdb_breakpoint "67" "Breakpoint 2 at.*: file.*threads_asm.c, line 67." " breakpoint at line 67, 1.1"
+
+# set a breakpoint at mybarrier() to halt all the new threads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 3, mybarrier \\(\\) at .*thr_callback_...s:114" "Breakpoint at my barrier for all the threads to stop, 1.2"
+
+gdb_breakpoint "${srccallback}:35" "Breakpoint 4 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 35." "Breakpoint after the barrier for thread 2, 1.3"
+
+gdb_breakpoint "${srccallback}:47" "Breakpoint 5 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 47." "Breakpoint after the barrier for thread 3, 1.4"
+gdb_breakpoint "${srccallback}:59" "Breakpoint 6 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 59." "Breakpoint after the barrier for thread 4, 1.5"
+gdb_breakpoint "${srccallback}:71" "Breakpoint 7 at 0x\[a-f0-9\]*: file .*thr_callback_...s, line 71." "Breakpoint after the barrier for thread 5, 1.6"
+
+# enable trace in primary thread, which automatically enables trace in all new threads crated.
+#gdb_test "btr enable all"
+send_gdb "continue\n"
+gdb_expect 8 {
+ -re "Breakpoint 3, mybarrier \\(\\) at.*thr_callback_...s:114.*"
+ {
+ pass "continuing"
+ }
+ }
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing.
+gdb_test "" ""
+
+# Enable btrace on all threads
+gdb_test "btr enable 2-3"
+
+# We need to do a seperate listing from here, since the instr length is different
+# on different platforms.
+gdb_test "thread 2" ".*Switching to thread 2.*mybarrier.*" " switch to thread 2, 1.7"
+# 64 bit platform
+if {[ishost "x86_64-*-*"]} {
+
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr_callback_...s:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_a\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_a\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 2, 1.9"
+
+# trace for thread 3
+gdb_test "thread 3" ".*Switching to thread 3.*mybarrier.*" " switch to thread 3, 1.10"
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr_callback_...s:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_b\\+24>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_b\\+25>:\[\[:blank:\]\]*ret.*" " BTR of thread 3, 1.12"
+
+# trace for thread 4
+gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " switch to thread 4, 1.13"
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr_callback_...s:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+No trace." " BTR of thread 4, 1.15"
+
+# trace for thread 5
+gdb_test "thread 5" ".*Switching to thread 5.*mybarrier.*" " switch to thread 5, 1.16"
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr_callback_...s:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+No trace." " BTR of thread 5, 1.18"
+
+} elseif {[ishost "i?86-*-*"]} {
+# 32 bit platform
+
+# trace for thread 2
+gdb_test "continue" ".*
+Breakpoint 4, th_a \\(\\) at .*thr_callback_...s:35.*" "BTR listing for thread 2, 1.8"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_a\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_a\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 2, 1.9"
+
+# trace for thread 3
+gdb_test "thread 3" ".*Switching to thread 3.*mybarrier.*" " switch to thread 3, 1.10"
+
+gdb_test "continue" ".*
+Breakpoint 5, th_b \\(\\) at .*thr_callback_...s:47.*" "BTR listing for thread 3, 1.11"
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <th_b\\+23>:\[\[:blank:\]\]*leave.*\r
+=> *0x\[a-f0-9\]* <th_b\\+24>:\[\[:blank:\]\]*ret.*" " BTR of thread 3, 1.12"
+
+# trace for thread 4
+gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " switch to thread 4, 1.13"
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c \\(\\) at .*thr_callback_...s:59.*" "BTR listing for thread 4, 1.14"
+
+gdb_test "btr" "
+No trace." " BTR of thread 4, 1.15"
+
+# trace for thread 5
+gdb_test "thread 5" ".*Switching to thread 5.*mybarrier.*" " switch to thread 5, 1.16"
+
+gdb_test "continue" ".*
+Breakpoint 7, th_d \\(\\) at .*thr_callback_...s:71.*" "BTR listing for thread 5, 1.17"
+
+gdb_test "btr" "
+No trace." " BTR of thread 5, 1.18"
+
+} else {
+ note "Platform not supported"
+ untested enable_range.exp
+}
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.btrace/list_options.exp b/gdb/testsuite/gdb.btrace/list_options.exp
new file mode 100755
index 0000000..103f22a
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/list_options.exp
@@ -0,0 +1,107 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+
+###############
+#Test Purpose: Testing the other options of btrace list like /t, /af
+#Also tests the other commands like giving a range to btr list "btr list n1-n2"
+# Sourcefiles : main.s, a.s, b.s
+# Compiled using '-g' option.
+###############
+
+load_lib btrace.exp
+
+set testfile "main"
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/main.s
+set srcfilea ${srcdir}/${subdir}/a.s
+set srcfileb ${srcdir}/${subdir}/b.s
+set objfilemain ${objdir}/${subdir}/main_asm.o
+set objfilea ${objdir}/${subdir}/a.o
+set objfileb ${objdir}/${subdir}/b.o
+set binfile ${objdir}/${subdir}/list_options.x
+set options " -g "
+#compile
+if {[target_assemble ${srcfilemain} ${objfilemain} ${options}] != ""} { return "" }
+if {[target_assemble ${srcfilea} ${objfilea} ${options}]!= ""} { return "" }
+if {[target_assemble ${srcfileb} ${objfileb} ${options}]!= ""} { return "" }
+
+set objfiles "${objfilemain} ${objfilea} ${objfileb}"
+#link
+if {[target_link ${objfiles} ${binfile} " "] != ""} {
+ untested list_options.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_breakpoint "25" "Breakpoint 1 at .*:.*main.s, line 25." "Breakpoint at line 25, 1.1"
+gdb_breakpoint "30" "Breakpoint 4 at .*:.*main.s, line 30." "Breakpoint at line 30, 1.2"
+
+gdb_test "r" ".*Breakpoint 1, _start .* at.*main.s:25\r
+25.*" "Run to Breakpoint at line 25, 1.3"
+
+# Enable branch trace to trace the startup.
+gdb_test_no_output "btr enable"
+
+gdb_test "c"
+
+gdb_test "btr list /t" "total: 4" "total number of btrace blocks, 1.4"
+
+#Get the trace listing after it returns from callB
+gdb_test "btr list /af" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in _start \\(\\)\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in callB \\(\\)\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in _start \\(\\)\r
+4 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in callA \\(\\)\r" "Listing at return, 1.5"
+
+#Get the trace listing for only 1-3
+gdb_test "btr list /lf 1-3" "
+1 *in _start \\(\\) at .*main.s:29-30\r
+2 *in callB \\(\\) at .*b.s:22-23\r
+3 *in _start \\(\\) at .*main.s:27-28\r" "Listing at return, 1.6"
+
+#Get the trace listing for only 2-3
+gdb_test "btr list /lf 2-4" "
+2 *in callB \\(\\) at .*b.s:22-23\r
+3 *in _start \\(\\) at .*main.s:27-28\r
+4 *in callA \\(\\) at .*a.s:22-23\r" "Listing at return, 1.7"
+
+gdb_test "btrace /m 3" "
+.*main.s:27\[\[:blank:\]\]*movl *.0, %eax\r
+ *0x\[a-f0-9\]* <_start\\+10>:\[\[:blank:\]\]*mov *.0x0,%eax\r
+\r
+.*main.s:28\[\[:blank:\]\]*call\[\[:blank:\]\]*callB\r
+ *0x\[a-f0-9\]* <_start\\+15>:\[\[:blank:\]\]*call. *0x\[a-f0-9\]* *<callB>" "btrace for 1 to 3, 1.8"
+
+gdb_test "btrace /r 3" "
+ *0x\[a-f0-9\]* <_start\\+10>:.*mov *.0x0,%eax\r
+ *0x\[a-f0-9\]* <_start\\+15>:.*call. *0x\[a-f0-9\]* <callB>" "btrace with /r options at 3, 1.9"
+
+
+gdb_test "btrace /r -" "
+ *0x\[a-f0-9\]* <callB\\+0>:\[\[:blank:\]\]*90\[\[:blank:\]\]*nop *\r
+ *0x\[a-f0-9\]* <callB\\+1>:\[\[:blank:\]\]*c3\[\[:blank:\]\]*ret. *" " btrace with /r option at 2, 1.10"
diff --git a/gdb/testsuite/gdb.btrace/main.s b/gdb/testsuite/gdb.btrace/main.s
new file mode 100755
index 0000000..b314ada
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/main.s
@@ -0,0 +1,32 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+###################
+# main.s, uses a.s and b.s
+###################
+
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ movl $0, %eax
+ call callA
+ movl $0, %eax
+ call callB
+ movl $0, %eax
+ leave
+ ret
+
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.btrace/main_asm.exp b/gdb/testsuite/gdb.btrace/main_asm.exp
new file mode 100755
index 0000000..0e7363d
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/main_asm.exp
@@ -0,0 +1,113 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+
+###############
+#Test Purpose: The trace works when we step into multiple source files in '.s' format
+# Sourcefiles : main.s, a.s, b.s
+# Compiled using '-g' option.
+###############
+
+load_lib btrace.exp
+
+set testfile "main"
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/main.s
+set srcfilea ${srcdir}/${subdir}/a.s
+set srcfileb ${srcdir}/${subdir}/b.s
+set objfilemain ${objdir}/${subdir}/main_asm.o
+set objfilea ${objdir}/${subdir}/a.o
+set objfileb ${objdir}/${subdir}/b.o
+set binfile ${objdir}/${subdir}/main_asm.x
+set options " -g "
+#compile
+if {[target_assemble ${srcfilemain} ${objfilemain} ${options}] != ""} { return "" }
+if {[target_assemble ${srcfilea} ${objfilea} ${options}]!= ""} { return "" }
+if {[target_assemble ${srcfileb} ${objfileb} ${options}]!= ""} { return "" }
+
+set objfiles "${objfilemain} ${objfilea} ${objfileb}"
+#link
+if {[target_link ${objfiles} ${binfile} " "] != ""} {
+ untested main_asm.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_breakpoint "25" "Breakpoint 1 at .*:.*main.s, line 25." "Breakpoint at line 25, 1.1"
+gdb_breakpoint "26" "Breakpoint 2 at .*:.*main.s, line 26." "Breakpoint at line 26, 1.2"
+gdb_breakpoint "28" "Breakpoint 3 at .*:.*main.s, line 28." "Breakpoint at line 28, 1.3"
+gdb_breakpoint "30" "Breakpoint 4 at .*:.*main.s, line 30." "Breakpoint at line 30, 1.4"
+
+gdb_test "r" ".*Breakpoint 1, _start .* at.*main.s:25\r
+25.*" "Run to Breakpoint at line 25, 1.5"
+
+# Enable branch trace to trace the startup.
+gdb_test_no_output "btr enable"
+
+gdb_test "c" ".*Breakpoint 2, _start .* at.*main.s:26\r
+26.*call.*callA" "Run to Breakpoint at line 26, 1.6"
+
+# run to callB
+gdb_test "c" ".*Breakpoint 3, _start .* at.*main.s:28\r
+28.*call.*callB" "Run to Breakpoint at line 28, 1.7"
+
+#get BTR listing in CallB
+gdb_test "btr list /lfa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in _start \\(\\) at .*main.s:27-28\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in callA \\(\\) at .*a.s:22-23" "BTR listing at line 28, 1.8"
+
+#return to main
+gdb_test "c" ".*Breakpoint 4, _start .* at.*main.s:30\r
+30.*leave" "Run to Breakpoint at line 30, 1.9"
+
+# we do get trace for main, callB, main, callA here
+gdb_test "btr list /lfa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in _start \\(\\) at .*main.s:29-30\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in callB \\(\\) at .*b.s:22-23\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in _start \\(\\) at .*main.s:27-28\r
+4 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in callA \\(\\) at .*a.s:22-23" "BTR listing at line 30, 1.10"
+
+
+gdb_test "btr /m 1" "
+.*main.s:29\[\[:blank:\]\]*movl *.0, %eax\r
+ *0x\[a-f0-9\]* <_start\\+20>:\[\[:blank:\]\]*mov *.0x0,%eax\r
+\r
+.*main.s:30\[\[:blank:\]\]*leave\r
+=> *0x\[a-f0-9\]* <_start\\+25>: leave.*" "BTR of 1, 1.11"
+
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <callB\\+0>:\[\[:blank:\]\]*nop\r
+ *0x\[a-f0-9\]* <callB\\+1>:\[\[:blank:\]\]*ret.*" "BTR of 2, 1.12"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <_start\\+10>:\[\[:blank:\]\]*mov *.0x0,%eax\r
+ *0x\[a-f0-9\]* <_start\\+15>:\[\[:blank:\]\]*call.*<callB>." "BTR of 3, 1.13"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <callA\\+0>:\[\[:blank:\]\]*nop\r
+ *0x\[a-f0-9\]* <callA\\+1>:\[\[:blank:\]\]*ret.*" "BTR of 4, 1.14"
diff --git a/gdb/testsuite/gdb.btrace/main_segv.exp b/gdb/testsuite/gdb.btrace/main_segv.exp
new file mode 100755
index 0000000..402d6d0
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/main_segv.exp
@@ -0,0 +1,84 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+
+###############
+#Test Purpose: The trace shows up when the debugge crashes with SIGSEGV
+# Sourcefiles : main_segv.s, b.s,
+# Compiled using '-g' option.
+###############
+
+load_lib btrace.exp
+
+set testfile "main"
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/main_segv.s
+set srcfileb ${srcdir}/${subdir}/b.s
+set objfilemain ${objdir}/${subdir}/main_segv.o
+set objfileb ${objdir}/${subdir}/b.o
+set binfile ${objdir}/${subdir}/main_segv.x
+set options " -g "
+#compile
+if {[target_assemble ${srcfilemain} ${objfilemain} ${options}] != ""} { return "" }
+if {[target_assemble ${srcfileb} ${objfileb} ${options}]!= ""} { return "" }
+
+set objfiles "${objfilemain} ${objfileb}"
+#link
+if {[target_link ${objfiles} ${binfile} " "] != ""} { return "" }
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_breakpoint "25" "Breakpoint 1 at .*:.*main_segv.s, line 25." "Breakpoint at line 25, 1.1"
+gdb_breakpoint "28" "Breakpoint 2 at .*:.*main_segv.s, line 28." "Breakpoint at line 28, 1.2"
+
+gdb_test "r" ".*Breakpoint 1, _start .* at.*main_segv.s:25\r
+25.*" "Run to Breakpoint at line 25, 1.3"
+
+# Enable branch trace to trace the startup.
+gdb_test_no_output "btr enable"
+
+gdb_test "stepi" ".*22.*" "Stepping into callB, 1.4"
+
+gdb_test "btr list /lfa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in callB \\(\\) at .*b.s.*" "BTR listing in b.s, 1.5"
+
+#check that we got SEGV
+gdb_test "c" ".*Program received signal SIGSEGV, Segmentation fault.\r
+_start.*at.*main_segv.s:27.*" "Program received SEGV at line 27, 1.6"
+
+#Check that we do get trace after SEGV too.
+gdb_test "btr list /a" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]*\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]*" "BTR listing at line 29, 1.7"
+
+#Check where we got SEGV
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <_start\\+5>:\[\[:blank:\]\]*mov *.0x0,%eax\r
+=> 0x\[a-f0-9\]* <_start\\+10>:\[\[:blank:\]\]*leave.*" "BTR of 1, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <callB\\+0>:\[\[:blank:\]\]*nop\r
+ *0x\[a-f0-9\]* <callB\\+1>:\[\[:blank:\]\]*ret.*" "BTR of 2, 1.9"
diff --git a/gdb/testsuite/gdb.btrace/main_segv.s b/gdb/testsuite/gdb.btrace/main_segv.s
new file mode 100755
index 0000000..f1ca686
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/main_segv.s
@@ -0,0 +1,28 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+###################
+# main.s, uses callB from b.s
+###################
+
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ call callB
+ movl $0, %eax
+ leave
+ ret
diff --git a/gdb/testsuite/gdb.btrace/sanity_crash.exp b/gdb/testsuite/gdb.btrace/sanity_crash.exp
new file mode 100755
index 0000000..2eaf96f
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/sanity_crash.exp
@@ -0,0 +1,69 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+#Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+###############
+#Test Purpose: Check that we get SEGV trace, in single source file.
+# see that trace gives the correct addresses.
+# Source file: sanity_crash.s
+###############
+load_lib btrace.exp
+
+set testfile "sanity_crash"
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfile ${srcdir}/${subdir}/sanity_crash.s
+set objfile ${objdir}/${subdir}/sanity_crash.o
+set binfile ${objdir}/${subdir}/sanity_crash.x
+set options " -g "
+#compile
+if {[target_assemble ${srcfile} ${objfile} ${options}] != ""} { return "" }
+#link
+if {[target_link ${objfile} ${binfile} " "] != ""} { return "" }
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# At breakpoint on line 20, we reset the trace.
+gdb_breakpoint "40" "Breakpoint 1 at .*:.*sanity_crash.s, line 40." "Breakpoint at line 40, 1.1"
+gdb_breakpoint "47" "Breakpoint 2 at .*:.*sanity_crash.s, line 47." "Breakpoint at line 47, 1.2"
+
+#Reach line 20 and enable trace
+gdb_test "run"
+# Enable branch trace to trace the startup.
+gdb_test_no_output "btr enable"
+
+# we get Segv in between line 24 and 27.
+gdb_test "continue" ".*Program received signal SIGSEGV, Segmentation fault.\r
+_start .* at .*sanity_crash.s:44.*" "Continue, Program received SIGSEGV, 1.3"
+
+# check, we do get Segv for single trace too
+gdb_test "btr list /lf" "
+1 *in _start \\(\\) at.*sanity_crash.s:42-44\r
+2 *in somethingToDo \\(\\) at.*sanity_crash.s:28-36" "BTR listing, 1.4"
+
+#Check where we got SEGV
+gdb_test "btr /m 1" "
+ *0x\[a-f0-9\]* *<_start\\+14>:\[\[:blank:\]\]movl *.0x2,0x20000f.%rip.*\r
+ *0x\[a-f0-9\]* *<_start\\+24>:\[\[:blank:\]\]mov *.0x0,%eax.*\r
+=> 0x\[a-f0-9\]* *<_start\\+29>:\[\[:blank:\]\]movb *.0x0,.%rax." "BTR at 1, 1.5"
diff --git a/gdb/testsuite/gdb.btrace/sanity_crash.s b/gdb/testsuite/gdb.btrace/sanity_crash.s
new file mode 100755
index 0000000..bbfc303
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/sanity_crash.s
@@ -0,0 +1,52 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+###################
+# sanity_crash.s
+# Gives segv after calling somethingToDo in _start
+###################
+ .file "sanity_crash.c"
+ .text
+ .globl _start
+ .type _start, @function
+ .globl somethingToDo
+ .type somethingToDo, @function
+somethingToDo:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl x.2043(%rip), %eax
+ movl %eax, %edx
+ addl $1, %eax
+ movl %eax, x.2043(%rip)
+ movl %edx, %eax
+ popq %rbp
+ ret
+_start:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ call somethingToDo
+ movl $2, jvar.2046(%rip)
+ movl $0, %eax
+ movb $0, (%rax)
+ movl $0, %eax
+ popq %rbp
+ ret
+.LFE1:
+ .local jvar.2046
+ .comm jvar.2046,4,4
+ .local x.2043
+ .comm x.2043,4,4
diff --git a/gdb/testsuite/gdb.btrace/thr_callback_32.s b/gdb/testsuite/gdb.btrace/thr_callback_32.s
new file mode 100755
index 0000000..c94285b
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/thr_callback_32.s
@@ -0,0 +1,116 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+#
+#
+###############
+# threads.c calls th_a(), th_b(),th_c() and th_d() as callback methods
+# for 4 threads being created.
+###############
+
+
+ .globl th_a
+ .type th_a, @function
+th_a:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ call call_A
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_b
+ .type th_b @function
+th_b:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ call call_B
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_c
+ .type th_c @function
+th_c:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ call call_C
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_d
+ .type th_d @function
+th_d:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ call call_D
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl call_A
+ .type call_A, @function
+call_A:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_B
+ .type call_B @function
+call_B:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_C
+ .type call_C @function
+call_C:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_D
+ .type call_D @function
+call_D:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl mybarrier
+ .type mybarrier @function
+mybarrier:
+ pushl %ebp
+ movl %esp, %ebp
+ movl $0, %eax
+ leave
+ ret
diff --git a/gdb/testsuite/gdb.btrace/thr_callback_64.s b/gdb/testsuite/gdb.btrace/thr_callback_64.s
new file mode 100755
index 0000000..6d4c0bd
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/thr_callback_64.s
@@ -0,0 +1,116 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+#
+#
+###############
+# threads.c calls th_a(), th_b(),th_c() and th_d() as callback methods
+# for 4 threads being created.
+###############
+
+
+ .globl th_a
+ .type th_a, @function
+th_a:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ call call_A
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_b
+ .type th_b @function
+th_b:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ call call_B
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_c
+ .type th_c @function
+th_c:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ call call_C
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl th_d
+ .type th_d @function
+th_d:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ call call_D
+ movl $0, %eax
+ call mybarrier
+ leave
+ ret
+
+ .globl call_A
+ .type call_A, @function
+call_A:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_B
+ .type call_B @function
+call_B:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_C
+ .type call_C @function
+call_C:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl call_D
+ .type call_D @function
+call_D:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
+
+ .globl mybarrier
+ .type mybarrier @function
+mybarrier:
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0, %eax
+ leave
+ ret
diff --git a/gdb/testsuite/gdb.btrace/threads.c b/gdb/testsuite/gdb.btrace/threads.c
new file mode 100755
index 0000000..2d81715
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads.c
@@ -0,0 +1,96 @@
+/*
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+
+###############
+#This program spawns 4 threads and each thread has a seperate callback function and
+# a diffierent function call from callback function.
+# Purpose: To check the trace functionality of gdb, ("btr auto on" and "btr enable" for individual threads)
+###############
+*/
+#include <pthread.h>
+#include <stdio.h>
+
+
+//function being called by Thread[0],
+int call_A(){ return 0;}
+//function being called by Thread[1]
+int call_B(){ return 0;}
+//function being called by Thread[2]
+int call_C(){ return 0;}
+//function being called by Thread[3]
+int call_D(){ return 0;}
+
+//Callback function for thread[0]
+void* th_a(void* arg){
+ int number = *((int*) arg);
+ call_A();
+ return arg;
+}
+//Callback function for thread[1]
+void* th_b(void* arg){
+ int number = *((int*) arg);
+ call_B();
+ return arg;
+}
+//Callback function for thread[2]
+void* th_c(void* arg){
+ int number = *((int*) arg);
+ call_C();
+ return arg;
+}
+//Callback function for thread[3]
+void* th_d(void* arg){
+ int number = *((int*) arg);
+ call_D();
+ return arg;
+}
+// Terminate the already created thread
+int join_thread(pthread_t *thr)
+{
+ int* resultp;
+ if (pthread_join(*thr, (void**) &resultp))
+ {
+ printf("ERROR: pthread_join failed, aborting!\n");
+ return(1);
+ }
+ return(0);
+}
+
+int main(){
+ const int THREADS = 4;
+ pthread_t thread[THREADS];
+ int args[THREADS];
+ args[0]=0;
+ args[1]=1;
+ args[2]=2;
+ args[3]=3;
+
+ // To be deterministic, we have to first terminate the
+ // created thread before creating a new one.
+ pthread_create(&thread[0], 0, th_a ,&args[0]);
+ join_thread(&thread[0]);
+ pthread_create(&thread[1], 0, th_b ,&args[1]);
+ join_thread(&thread[1]);
+ pthread_create(&thread[2], 0, th_c ,&args[2]);
+ join_thread(&thread[2]);
+ pthread_create(&thread[3], 0, th_d ,&args[3]);
+ join_thread(&thread[3]);
+
+ return 1;
+}
diff --git a/gdb/testsuite/gdb.btrace/threads_asm.c b/gdb/testsuite/gdb.btrace/threads_asm.c
new file mode 100755
index 0000000..eb58ecf
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads_asm.c
@@ -0,0 +1,78 @@
+/*
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+
+###############
+#This program spawns 4 threads and each thread has a seperate callback function and
+# a different function call from callback function.
+# th_a(), th_b(), th_c() and th_d are called from file th_callback.s
+#
+# Purpose: To check the trace functionality of gdb, ("btr auto on" and "btr enable" for individual threads and "btr enable" in GDb non-stop mode)
+###############
+*/
+#include <pthread.h>
+#include <stdio.h>
+
+pthread_barrier_t bar;
+
+void* th_a(void* arg);
+void* th_b(void* arg);
+void* th_c(void* arg);
+void* th_d(void* arg);
+
+// Terminate the already created thread
+int join_thread(pthread_t *thr)
+{
+ int* resultp;
+ if (pthread_join(*thr, (void**) &resultp))
+ {
+ printf("ERROR: pthread_join failed, aborting!\n");
+ return(1);
+ }
+ return(-1);
+}
+
+int main(){
+ const int THREADS = 4;
+ pthread_t thread[THREADS];
+ int args[THREADS];
+ int i;
+ args[0]=0;
+ args[1]=1;
+ args[2]=2;
+ args[3]=3;
+ pthread_barrier_init(&bar, NULL, 5);
+
+ //create 4 threads having different callback fucntions.
+ pthread_create(&thread[0], 0, th_a ,&args[0]);
+ pthread_create(&thread[1], 0, th_b ,&args[1]);
+ pthread_create(&thread[2], 0, th_c ,&args[2]);
+ pthread_create(&thread[3], 0, th_d ,&args[3]);
+ mybarrier();
+ printf(" All the threads are created by now ");
+ //wait for all the threads to terminate
+
+ for(i=0;i<4;i++) {
+ join_thread(&thread[i]);
+ }
+ //destroy barrier
+ pthread_barrier_destroy(&bar);
+
+ return 1;
+}
+
diff --git a/gdb/testsuite/gdb.btrace/threads_auto.exp b/gdb/testsuite/gdb.btrace/threads_auto.exp
new file mode 100755
index 0000000..d9e85a6
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads_auto.exp
@@ -0,0 +1,113 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+
+###############
+#Test Purpose: The trace works for multi-threaded application and the trace is automatically enabled for all the threads created, if we execute the GDB command "btr enable auto".
+# Sourcefiles : threads.c
+# Compiled using '-g -lpthread' option.
+#executed as :
+# make check RUNTESTFLAGS="GDB=<path to gdb> gdb.trace/threads_auto.exp"
+###############
+
+
+
+load_lib btrace.exp
+
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads.c
+set objfilemain ${objdir}/${subdir}/threads.o
+set binfile ${objdir}/${subdir}/threads_auto.x
+set options "{debug}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objfilemain} "object" ${options}] != ""} {
+ untested threads_auto.exp
+ return -1
+}
+if {[gdb_compile_pthreads ${objfilemain} ${binfile} "executable" ""] != ""} {
+ untested threads_auto.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# Make sure we don't die when enabling trace for a newly created thread.
+runto main
+#set a breakpoint at the end of each callback function of each thread
+gdb_breakpoint "43" "Breakpoint 2 at .*:.*, line 43." "Breakpoint at line 42, 1.1"
+
+gdb_breakpoint "49" "Breakpoint 3 at .*:.*, line 49." "Breakpoint at line 48, 1.2"
+
+gdb_breakpoint "55" "Breakpoint 4 at .*:.*, line 55." "Breakpoint at line 54, 1.3"
+
+gdb_breakpoint "61" "Breakpoint 5 at .*:.*, line 61." "Breakpoint at line 60, 1.4"
+
+# Reset branch trace on all new threads automatically
+gdb_test_no_output "btr enable auto"
+
+gdb_test "continue" ".*
+Breakpoint 2, th_a.*threads\.c:43\r
+43\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 2, line 43, 1.5"
+
+#Get the trace listing after it returns from call_A, while ignoring the trace listing of trace pthread libs.
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_a \\(\\)\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_A \\(\\)\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_a \\(\\)\r
+.*\r" "listing is not correct thread\[0\], 1.6"
+
+
+gdb_test "continue" ".*
+Breakpoint 3, th_b.*threads\.c:49\r
+49\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 32, line 49, 1.7"
+
+#Get the trace listing after it returns from call_B
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_b \\(\\)\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_B \\(\\)\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_b \\(\\)\r
+.*\r" "listing is not correct thread\[1\], 1.8"
+
+gdb_test "continue" ".*
+Breakpoint 4, th_c.*threads\.c:55\r
+55\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 4, line 55, 1.9"
+
+#Get the trace listing after it returns from call_C
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_c \\(\\)\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_C \\(\\)\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_c \\(\\)\r
+.*\r" "listing is not correct thread\[2\], 1.10"
+
+gdb_test "continue" ".*
+Breakpoint 5, th_d.*threads\.c:61\r
+61\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 52, line 61, 1.11"
+
+#Get the trace listing after it returns from call_D
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_d \\(\\)\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_D \\(\\)\r
+3 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_d \\(\\)\r
+.*\r" "listing is not correct for thread\[3\], 1.12"
diff --git a/gdb/testsuite/gdb.btrace/threads_independent.exp b/gdb/testsuite/gdb.btrace/threads_independent.exp
new file mode 100755
index 0000000..a37be7f
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads_independent.exp
@@ -0,0 +1,119 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+
+###############
+#Test Purpose: The trace works for multi-threaded application and the trace is enabled for only the current thread.
+# Sourcefiles : threads.c
+# Compiled using '-g -lpthread' option.
+#executed as :
+# make check RUNTESTFLAGS="GDB=/users/bahuja/work_gdb/gdb_32/gdb --host i686-linux-gnu --target i686-linux-gnu gdb.trace/threads_independent.exp"
+###############
+
+
+load_lib btrace.exp
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads.c
+set objfilemain ${objdir}/${subdir}/threads.o
+set binfile ${objdir}/${subdir}/threads_independent.x
+set options "{debug}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${binfile} "executable" ${options}] != ""} {
+ untested threads_independent.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+# Make sure we don't die when enabling trace for a newly created thread.
+runto main
+#set a breakpoint at the end of each callback function of each thread
+gdb_breakpoint "th_a" "Breakpoint 2 at .*:.*, line 41." "Breakpoint at th_a, 1.1"
+
+gdb_breakpoint "th_c" "Breakpoint 4 at .*:.*, line 53." "Breakpoint at th_c, 1.2"
+
+#set a breakpoint at the end of each callback function of each thread
+gdb_breakpoint "43" "Breakpoint 6 at .*:.*, line 43." "Breakpoint at line 43, 1.3"
+
+gdb_breakpoint "49" "Breakpoint 7 at .*:.*, line 49." "Breakpoint at line 49, 1.4"
+
+gdb_breakpoint "55" "Breakpoint 8 at .*:.*, line 55." "Breakpoint at line 55, 1.5"
+
+gdb_breakpoint "61" "Breakpoint 9 at .*:.*, line 61." "Breakpoint at line 61, 1.6"
+
+# move to th_a for thread[0]and enable trace
+gdb_test "continue" ".*
+Breakpoint 2, th_a.*threads\.c:41\r.*" "Stopping at breakpoint 2, th_a, 1.7"
+
+# Reset branch trace
+gdb_test_no_output "btrace enable"
+
+gdb_test "continue" ".*
+Breakpoint 4, th_a.*threads\.c:43\r
+43\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 4, line 43, 1.8"
+
+#Get the trace listing after it returns from call_A
+gdb_test "btrace list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_a \\(\\)\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_A \\(\\)" "listing of thread\[0\], 1.9"
+
+
+# move to th_b for thread[1]and do not enable trace
+gdb_test "continue" ".*
+Breakpoint 5, th_b.*threads\.c:49\r
+49\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 5, line 49, 1.10"
+
+#Get the trace listing after it returns from call_B
+gdb_test "btr list" "No trace." "No trace for thread\[1\], 1.11"
+
+
+# move to th_c and enable trace
+gdb_test "continue" ".*
+Breakpoint 3, th_c.*threads\.c:53\r
+53.*" "Stopping at breakpoint 3, th_c, 1.12"
+
+
+# Reset branch trace for thread[2]
+gdb_test_no_output "btrace enable"
+
+gdb_test "continue" ".*
+Breakpoint 6, th_c.*threads\.c:55\r
+55\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 6, line 55, 1.13"
+
+#Get the trace listing after it returns from call_C
+gdb_test "btr list /fa" "
+1 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_c \\(\\)\r
+2 *0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_C \\(\\)" "listing of thread\[2\], 1.14"
+
+
+# move to th_d and do not enable trace
+gdb_test "continue" ".*
+Breakpoint 7, th_d.*threads\.c:61\r
+61\[\[:blank:\]\]*return arg.*" "Stopping at breakpoint 7, line 61, 1.15"
+
+#Get the trace listing after it returns from call_D
+gdb_test "btr list" "No trace." "No trace for thread\[3\], 1.16"
diff --git a/gdb/testsuite/gdb.btrace/threads_nonstop.exp b/gdb/testsuite/gdb.btrace/threads_nonstop.exp
new file mode 100755
index 0000000..f22e8f9
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/threads_nonstop.exp
@@ -0,0 +1,182 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+###############
+#Test Purpose: In GDB non-stop mode, when btrace is enabled for only one thread (created by pthread_create()), then trace is also generated for only that thread and not for all threads
+# Sourcefiles : threads_asm.c
+# Compiled using '-g -lpthread' option.
+#executed as :
+# make check RUNTESTFLAGS="GDB=/users/bahuja/work_gdb/gdb_32/gdb --host i686-linux-gnu --target i686-linux-gnu gdb.trace/threads_nonstop.exp"
+###############
+
+load_lib btrace.exp
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+global srcdir
+global objdir
+global subdir
+
+set srcfilemain ${srcdir}/${subdir}/threads_asm.c
+set objcallback ${objdir}/${subdir}/thr_callback.o
+set objmain ${objdir}/${subdir}/threads_asm.o
+set binfile ${objdir}/${subdir}/threads_nonstop.x
+set options "{debug}"
+
+# We need to do a seperate listing from here, since the instr lenght is different
+# on different platforms.
+# 32 bit platform
+if {[ishost "i?86-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/thr_callback_32.s
+} elseif {[ishost "x86_64-*-*"]} {
+ set srccallback ${srcdir}/${subdir}/thr_callback_64.s
+} else {
+ warning "host platform not supported "
+ return -1
+}
+
+set objfiles "${objmain} ${objcallback}"
+
+#compile
+if {[gdb_compile_pthreads ${srcfilemain} ${objmain} "object" ${options}] != ""} { return "" }
+if {[gdb_compile ${srccallback} ${objcallback} "object" ${options}] != ""} { return "" }
+
+if {[gdb_compile_pthreads ${objfiles} ${binfile} "executable" ${options}] != ""} {
+ untested threads_nonstop.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+gdb_test_no_output "set pagination off"
+gdb_test_no_output "set target-async 1"
+gdb_test_no_output "set non-stop 1"
+
+runto main
+
+#set breakpoint at mybarrier to prevent all the pthreads from exiting.
+gdb_breakpoint "mybarrier" "Breakpoint 2 at .*:thr_callback_\[32|64\].s, line .*." "Breakpoint in reach barrier, 1.1"
+
+#set a breakpoint in callback of thread 3, where we enable trace for only thread 3
+gdb_breakpoint "th_b" "Breakpoint 3 at .*:thr_callback_\[32|64\].s.*" "Breakpoint in reach barrier, 1.2"
+
+send_gdb "continue\n"
+gdb_expect 8 {
+ -re "Breakpoint 2.*"
+ {
+ pass "continuing"
+ }
+ }
+# This "info threads" is needed to get a $gdb_prompt, since gdb seems to get hanged at this particular location.
+set test "info for threads"
+gdb_test_multiple "info threads" $test {
+ -re ".*\n" {
+ pass $test
+ }
+}
+
+# this is added to get the prompt, which is missing after creating new threads in non-stop mode.
+gdb_test "" ""
+
+# thread 3 reaches its callback th_b(), while all threads wait at mybarrier()
+gdb_test "info threads" " Id Target Id Frame \r
+ 5 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr_callback_...s:114\r
+ 4 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr_callback_...s:114\r
+ 3 Thread 0x\[a-f0-9\]*.*th_b \\(\\) at.*thr_callback_...s:42\r
+ 2 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr_callback_...s:114\r
+.* 1 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr_callback_...s:114" "info threads before thread 3 reaches mybarrier(), 1.3"
+
+gdb_test "thread 3" ".*Switching to thread 3.*th_b.*" " Thread 3 is still waiting at th_b(), 1.4"
+#enable trace for only thread 3
+
+gdb_test "btr enable"
+# thread 3 also continues to mybarrier()
+
+gdb_test "continue" ".*Breakpoint 2, mybarrier \\(\\) at .*thr_callback_...s:114.*" " thread 3 also reached at breakpoint 1 at line 53, 1.5"
+# back trace for thread 3.
+
+gdb_test "btr list /lfa" "
+1 0x\[a-f0-9\]* - 0x\[a-f0-9\]* in mybarrier \\(\\) at.*thr_callback_...s:112-114\r
+2 0x\[a-f0-9\]* - 0x\[a-f0-9\]* in th_b \\(\\) at.*thr_callback_...s:44-45\r
+3 0x\[a-f0-9\]* - 0x\[a-f0-9\]* in call_B \\(\\) at.*thr_callback_...s:85-89" "BTR listing at line mybarrier for thread 3, 1.6"
+
+# 32 bit host
+if {[ishost "i?86-*-*"]} {
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> 0x\[a-f0-9\]* <mybarrier\\+3>:\[\[:blank:\]\]*mov.*" "btr 0 for thread 3, 1.7"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_b\\+13>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_b\\+18>:\[\[:blank:\]\]*call.*<mybarrier>" "btr 1 for thread 3, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <call_B\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <call_B\\+1>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_B\\+3>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_B\\+8>:\[\[:blank:\]\]*leave.*\r
+ *0x\[a-f0-9\]* <call_B\\+9>:\[\[:blank:\]\]*ret.*\r" "btr 1 for thread 3, 1.9"
+
+} elseif {[ishost "x86_64-*-*"]} {
+# 64 bit host
+
+gdb_test "btr" "
+ *0x\[a-f0-9\]* <mybarrier\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <mybarrier\\+1>:\[\[:blank:\]\]*mov.*\r
+=> 0x\[a-f0-9\]* <mybarrier\\+4>:\[\[:blank:\]\]*mov.*" "btr 0 for thread 3, 1.7"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <th_b\\+14>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <th_b\\+19>:\[\[:blank:\]\]*call.*<mybarrier>" "btr 1 for thread 3, 1.8"
+
+gdb_test "btr +" "
+ *0x\[a-f0-9\]* <call_B\\+0>:\[\[:blank:\]\]*push.*\r
+ *0x\[a-f0-9\]* <call_B\\+1>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_B\\+4>:\[\[:blank:\]\]*mov.*\r
+ *0x\[a-f0-9\]* <call_B\\+9>:\[\[:blank:\]\]*leave.*\r
+ *0x\[a-f0-9\]* <call_B\\+10>:\[\[:blank:\]\]*ret.*\r" "btr 1 for thread 3, 1.9"
+
+}
+# All the threads are at mybarrier()
+gdb_test "info threads" " Id Target Id Frame \r
+ 5 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr_callback_...s:114\r
+ 4 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr_callback_...s:114\r
+.* 3 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr_callback_...s:114\r
+ 2 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr_callback_...s:114\r
+ 1 Thread 0x\[a-f0-9\]*.*mybarrier \\(\\) at.*thr_callback_...s:114" "Info threads, when all threads reached barrier, 1.10"
+
+# trace was enabled for only thread 3, and none other thread has trace
+gdb_test "thread 2" ".*Switching to thread 2.*mybarrier.*" " switch to thread 2, 1.11"
+
+gdb_test "btr list" "No trace" " no trace for thread 2, 1.12"
+
+gdb_test "thread 4" ".*Switching to thread 4.*mybarrier.*" " swtich to thread 4, 1.13"
+
+gdb_test "btr list" "No trace" " no trace for thread 4, 1.14"
+
+gdb_test "thread 5" ".*Switching to thread 5.*mybarrier.*" " swtich to thread 5, 1.15"
+
+gdb_test "btr list" "No trace" " no trace for thread 5, 1.16"
+
+
+
+
diff --git a/gdb/testsuite/gdb.btrace/trace_iteration.exp b/gdb/testsuite/gdb.btrace/trace_iteration.exp
new file mode 100755
index 0000000..1a63e11
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/trace_iteration.exp
@@ -0,0 +1,264 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# Contributed by Barkha Ahuja <barkha.ahuja@intel.com>
+#
+# 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/>.
+
+
+###############
+#Test Purpose: Fix a location while linking, where the debuggee will be loaded and then
+# see that trace gives the correct addresses.
+# Iterate over the btrace using the commands "btr", "btr +", "btr -", and check that it gives the correct output.
+# Source file: decrement.s
+###############
+
+load_lib btrace.exp
+
+# start fresh - without an executable
+gdb_exit
+gdb_start
+
+set srcfile ${srcdir}/${subdir}/decrement.s
+set objfile ${objdir}/${subdir}/decrement.o
+set binfile ${objdir}/${subdir}/trace_iteration.x
+set options "{debug}"
+#compile
+if {[target_assemble ${srcfile} ${objfile} ""] != ""} { return -1 }
+#link
+if {[target_link ${objfile} ${binfile} " -Ttext 0x400400 "] != ""} {
+ untested trace_iteration.exp
+ return -1
+}
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load $binfile
+
+
+# Make sure we don't die when enabling trace for a newly created thread.
+runto L1
+
+# Enable branch trace to trace the startup.
+gdb_test_no_output "btr enable"
+
+# Reset branch trace so we get predictable output.
+btrace_reset_trace
+
+gdb_test "next" "0x0*40041a in L1.*" ""
+
+gdb_test "btr list /lfa" "
+1 *0x0*40041a - 0x0*40041a in L1 \\(\\)" "list L1, 1.1"
+
+gdb_continue_to_breakpoint "L1, 1.2"
+
+if {[ishost "x86_64-*-*"]} {
+#64 bit host
+
+#We enter the loop for 5 times from here.
+gdb_test "btr list /af" "
+1 *0x0*40041a - 0x0*40041a in L1 \\(\\)\r
+2 *0x0*40041a - 0x0*400421 in L1 \\(\\)" "list L1 again, 1.3"
+
+#Delete all Breakpoints
+delete_breakpoints
+
+#Set a Breakpoint at L2
+gdb_breakpoint "L2"
+
+#Continue to L2
+gdb_continue_to_breakpoint "L2"
+
+# BTR listing in method L2, when the loop exits
+gdb_test "btr list /a" "
+1 *0x0*400423 - 0x0*400423\r
+2 *0x0*40041a - 0x0*40041d\r
+3 *0x0*40041a - 0x0*400421\r
+4 *0x0*40041a - 0x0*400421\r
+5 *0x0*40041a - 0x0*400421\r.*" "BTR listing at L2, 1.4"
+
+# Exit the loop
+gdb_test "btr " "
+=> 0x0*400423 *<L2\\+0>:\[\[:blank:\]\]*retq *" "BTR of 0, 1.5"
+
+#BTR of non existing trace
+gdb_test "btr -" "
+No trace." "BTR of non-existing trace, 1.6"
+
+# Comparison, if we are exiting the loop
+gdb_test "btr -" "
+No trace." "BTR of non-existing trace, 1.7"
+
+gdb_test "btr " "
+=> 0x0*400423 *<L2\\+0>:\[\[:blank:\]\]*retq *" "BTR of 1, 1.8"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r" "BTR at 2, 1.9"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3, 1.10"
+
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r" "BTR at 2 second time, 1.11"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3 second time, 1.12"
+
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r" "BTR at 2 third time, 1.13"
+
+#in the loop
+gdb_test "btr -" "
+=> 0x0*400423 *<L2\\+0>:\[\[:blank:\]\]*retq *" "BTR at 1 Again, 1.14"
+
+gdb_test "btr 6" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 6, 1.15"
+
+gdb_test "btr +" "
+No trace." "BTR of non existing at end, 1.16"
+
+gdb_test "btr" "
+No trace." "BTR still at 6 , 1.17"
+
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400423 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400421 *<L1\\+7>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 6, 1.18"
+
+} elseif {[ishost "i?86-*-*"]} {
+#32 bit host
+
+#We enter the loop for 5 times from here.
+gdb_test "btr list /af" "
+1 *0x0*40041a - 0x0*40041a in L1 \\(\\)\r
+2 *0x0*40041a - 0x0*400420 in L1 \\(\\)" "list L1 again, 1.3"
+
+#Delete all Breakpoints
+delete_breakpoints
+
+#Set a Breakpoint at L2
+gdb_breakpoint "L2"
+
+#Continue to L2
+gdb_continue_to_breakpoint "L2"
+
+# BTR listing in method L2, when the loop exits
+gdb_test "btr list /a" "
+1 *0x0*400422 - 0x0*400422\r
+2 *0x0*40041a - 0x0*40041d\r
+3 *0x0*40041a - 0x0*400420\r
+4 *0x0*40041a - 0x0*400420\r
+5 *0x0*40041a - 0x0*400420\r
+6 *0x0*40041a - 0x0*400420\r" "BTR listing at L2, 1.4"
+
+# Exit the loop
+gdb_test "btr " "
+=> 0x0*400422 *<L2\\+0>:\[\[:blank:\]\]*ret *" "BTR of 1, 1.5"
+
+#BTR of non existing trace
+gdb_test "btr -" "
+No trace." "BTR of non-existing trace, 1.6"
+
+#BTR of non existing trace
+gdb_test "btr -" "
+No trace." "BTR of non-existing trace, 1.7"
+
+#BTR of non existing trace
+gdb_test "btr " "
+=> 0x0*400422 *<L2\\+0>:\[\[:blank:\]\]*ret *" "BTR of 1, 1.8"
+
+# Comparison, if we are exiting the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 *<L2>" "BTR at 2, 1.9"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3, 1.10"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3, 1.11"
+
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 2 second time, 1.12"
+
+#in the loop
+gdb_test "btr +" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 3 second time, 1.13"
+
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 2nd third time, 1.14"
+#in the loop
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 *<L2>" "BTR at 1 Again, 1.15"
+
+gdb_test "btr 6" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR at 6, 1.16"
+
+gdb_test "btr +" "" "BTR of non existing at end, 1.17"
+
+gdb_test "btr" "" "BTR still at 6 , 1.18"
+
+gdb_test "btr -" "
+ *0x0*40041a *<L1\\+0>:\[\[:blank:\]\]*cmp *.0x0,%eax\r
+ *0x0*40041d *<L1\\+3>:\[\[:blank:\]\]*je *0x400422 <L2>\r
+ *0x0*40041f *<L1\\+5>:\[\[:blank:\]\]*dec *%eax\r
+ *0x0*400420 *<L1\\+6>:\[\[:blank:\]\]*jmp *0x40041a <L1>" "BTR still at 6 , 1.19"
+
+ } else {
+ warning "host platform not supported "
+}
+
+#reset the trace
+btrace_reset_trace
+
+gdb_test "btr list" "No trace." "No trace should be available now"
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 09/16] btrace, linux: add linux native btrace target ops
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (12 preceding siblings ...)
2012-05-10 15:18 ` [PATCH 12/16] test, btrace: more branch tracing tests markus.t.metzger
@ 2012-05-10 15:18 ` markus.t.metzger
2012-05-10 15:18 ` [PATCH 13/16] xml, btrace: define btrace xml document style markus.t.metzger
` (2 subsequent siblings)
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:18 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Implement btrace target ops for linux native based on the common linux btrace
support.
We use a separate file for this to allow sharing between multiple targets
(i.e. i386 and x86_64) and to avoid having to guard this for targets that do not
support branch tracing.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* linux-nat-btrace.h: New file
* linux-nat-btrace.c: New file
---
gdb/linux-nat-btrace.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++
gdb/linux-nat-btrace.h | 28 +++++++++++++++
2 files changed, 114 insertions(+), 0 deletions(-)
create mode 100644 gdb/linux-nat-btrace.c
create mode 100644 gdb/linux-nat-btrace.h
diff --git a/gdb/linux-nat-btrace.c b/gdb/linux-nat-btrace.c
new file mode 100644
index 0000000..f69fc6f
--- /dev/null
+++ b/gdb/linux-nat-btrace.c
@@ -0,0 +1,86 @@
+/* Branch trace support for GDB, the GNU debugger.
+
+ Copyright (C) 2012 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 "linux-nat-btrace.h"
+#include "linux-btrace.h"
+#include "btrace.h"
+#include "target.h"
+#include "gdbarch.h"
+#include "arch-utils.h"
+#include <errno.h>
+
+static int
+linux_nat_push_btrace_record (struct linux_btrace_block *raw, void *arg)
+{
+ VEC (btrace_block_s) **btrace = arg;
+ struct btrace_block *block;
+
+ if (!raw)
+ return EINVAL;
+
+ if (!btrace)
+ return EINVAL;
+
+ block = VEC_safe_push (btrace_block_s, *btrace, NULL);
+ if (!block)
+ return ENOMEM;
+
+ block->begin = raw->begin;
+ block->end = raw->end;
+
+ return 0;
+}
+
+static VEC (btrace_block_s) *
+linux_nat_read_btrace (struct btrace_target_info *tinfo)
+{
+ VEC (btrace_block_s) *btrace = NULL;
+ int errcode;
+
+ if (!tinfo)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (!tinfo->ptr_bits)
+ {
+ struct gdbarch *gdbarch = get_current_arch ();
+ if (gdbarch)
+ tinfo->ptr_bits = gdbarch_ptr_bit (gdbarch);
+ }
+
+ errcode = linux_read_btrace (tinfo, linux_nat_push_btrace_record, &btrace);
+ if (errcode)
+ warning (_("error while reading branch trace data: %s. "
+ "trace might be incomplete."), safe_strerror (errcode));
+
+ return btrace;
+}
+
+void
+linux_nat_add_btrace_ops (struct target_ops *t)
+{
+ t->to_supports_btrace = linux_supports_btrace;
+ t->to_enable_btrace = linux_enable_btrace;
+ t->to_disable_btrace = linux_disable_btrace;
+ t->to_btrace_has_changed = linux_btrace_has_changed;
+ t->to_read_btrace = linux_nat_read_btrace;
+}
diff --git a/gdb/linux-nat-btrace.h b/gdb/linux-nat-btrace.h
new file mode 100644
index 0000000..cbe9c89
--- /dev/null
+++ b/gdb/linux-nat-btrace.h
@@ -0,0 +1,28 @@
+/* Branch trace support for GDB, the GNU debugger.
+
+ Copyright (C) 2012 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/>. */
+
+#ifndef LINUX_NAT_BTRACE_H
+#define LINUX_NAT_BTRACE_H
+
+struct target_ops;
+extern void linux_nat_add_btrace_ops (struct target_ops *);
+
+#endif /* LINUX_NAT_BTRACE_H */
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 13/16] xml, btrace: define btrace xml document style
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (13 preceding siblings ...)
2012-05-10 15:18 ` [PATCH 09/16] btrace, linux: add linux native btrace target ops markus.t.metzger
@ 2012-05-10 15:18 ` markus.t.metzger
2012-05-10 15:18 ` [PATCH 15/16] gdbserver, btrace: add generic btrace support markus.t.metzger
2012-05-11 0:25 ` [PATCH 00/16] branch tracing support Hui Zhu
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:18 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Define the xml document style for transferring branch trace data.
Add a function to parse a btrace xml document into a vector of branch trace
blocks.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/features/
* btrace.dtd: New file
gdb/
* Makefile.in (XMLFILES): Add btrace.dtd
* btrace.h (parse_xml_btrace): New declaration
* btrace.c (parse_xml_btrace): New function
(parse_xml_btrace_block): New function
(block_attributes): New struct
(btrace_attributes): New struct
(btrace_children): New struct
(btrace_elements): New struct
---
gdb/Makefile.in | 3 +-
gdb/btrace.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++
gdb/btrace.h | 3 ++
gdb/features/btrace.dtd | 12 +++++++
4 files changed, 98 insertions(+), 1 deletions(-)
create mode 100644 gdb/features/btrace.dtd
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index b3fdd4f..5c31ecd 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -489,7 +489,8 @@ RUNTESTFLAGS=
XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd \
$(srcdir)/features/library-list.dtd \
$(srcdir)/features/library-list-svr4.dtd $(srcdir)/features/osdata.dtd \
- $(srcdir)/features/threads.dtd $(srcdir)/features/traceframe-info.dtd
+ $(srcdir)/features/threads.dtd $(srcdir)/features/traceframe-info.dtd \
+ $(srcdir)/features/btrace.dtd
# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
# interface to the serial port. Hopefully if get ported to OS/2, VMS,
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 2b57ca7..c2aef67 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -29,6 +29,7 @@
#include "cli/cli-utils.h"
#include "arch-utils.h"
#include "disasm.h"
+#include "xml-support.h"
#include <errno.h>
#include <ctype.h>
@@ -798,6 +799,86 @@ cmd_btrace (char *args, int from_tty)
do_btrace (trace, flags);
}
+#if defined(HAVE_LIBEXPAT)
+
+static void
+check_xml_btrace_version (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC (gdb_xml_value_s) *attributes)
+{
+ const char *version = xml_find_attribute (attributes, "version")->value;
+ if (strcmp (version, "1.0") != 0)
+ gdb_xml_error (parser, _("Unsupported btrace version: \"%s\""), version);
+}
+
+static void
+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 = user_data;
+ struct btrace_block *block = VEC_safe_push (btrace_block_s, *btrace, NULL);
+ ULONGEST *begin, *end;
+
+ begin = xml_find_attribute (attributes, "begin")->value;
+ end = xml_find_attribute (attributes, "end")->value;
+
+ block->begin = *begin;
+ block->end = *end;
+}
+
+const struct gdb_xml_attribute block_attributes[] = {
+ { "begin", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { "end", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_attribute btrace_attributes[] = {
+ { "version", GDB_XML_AF_NONE, NULL, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element btrace_children[] = {
+ { "block", block_attributes, NULL,
+ GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, parse_xml_btrace_block, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element btrace_elements[] = {
+ { "btrace", btrace_attributes, btrace_children, GDB_XML_EF_NONE,
+ check_xml_btrace_version, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+#endif /* defined(HAVE_LIBEXPAT) */
+
+VEC (btrace_block_s) *
+parse_xml_btrace (const char *buffer)
+{
+ VEC (btrace_block_s) *btrace = NULL;
+ struct cleanup *cleanup;
+ int errcode;
+
+#if defined(HAVE_LIBEXPAT)
+ cleanup = make_cleanup (xfree, btrace);
+ errcode = gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements,
+ buffer, &btrace);
+ if (errcode)
+ {
+ do_cleanups (cleanup);
+ errno = errcode;
+ return NULL;
+ }
+
+ /* Keep parse results. */
+ discard_cleanups (cleanup);
+#else /* defined(HAVE_LIBEXPAT) */
+ errno = ENOSYS;
+#endif /* defined(HAVE_LIBEXPAT) */
+
+ return btrace;
+}
+
void _initialize_btrace (void);
void
diff --git a/gdb/btrace.h b/gdb/btrace.h
index 97f0f52..12e70b9 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -86,4 +86,7 @@ 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 *);
+/* Parse a branch trace xml document into a block vector. */
+extern VEC (btrace_block_s) *parse_xml_btrace (const char*);
+
#endif /* BTRACE_H */
diff --git a/gdb/features/btrace.dtd b/gdb/features/btrace.dtd
new file mode 100644
index 0000000..7e6bfd0
--- /dev/null
+++ b/gdb/features/btrace.dtd
@@ -0,0 +1,12 @@
+<!-- Copyright (C) 2012 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!ELEMENT btrace (block)* >
+<!ATTLIST btrace version CDATA #REQUIRED>
+
+<!ELEMENT block EMPTY>
+<!ATTLIST block begin CDATA #REQUIRED
+ end CDATA #REQUIRED>
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* [PATCH 15/16] gdbserver, btrace: add generic btrace support
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (14 preceding siblings ...)
2012-05-10 15:18 ` [PATCH 13/16] xml, btrace: define btrace xml document style markus.t.metzger
@ 2012-05-10 15:18 ` markus.t.metzger
2012-05-11 0:25 ` [PATCH 00/16] branch tracing support Hui Zhu
16 siblings, 0 replies; 24+ messages in thread
From: markus.t.metzger @ 2012-05-10 15:18 UTC (permalink / raw)
To: gdb-patches; +Cc: markus.t.metzger, Markus Metzger
From: Markus Metzger <markus.t.metzger@intel.com>
Add support to gdbserver to understand branch trace related packages.
2012-05-10 Markus Metzger <markus.t.metzger@intel.com>
gdb/gdbserver/
* target.h (struct target_ops): Add btrace ops
(target_supports_btrace): New macro
(target_btrace_has_changed): 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 (handle_btrace_general_set): New function
(handle_general_set): Call handle_btrace_general_set
(handle_qxfer_btrace): New function
(struct qxfer qxfer_packets[]): Add btrace entry
(handle_btrace_query): New function
(handle_query): Add btrace to supported query, call handle_btrace_query
* inferiors.c (remove_thread): Disable btrace
---
gdb/gdbserver/gdbthread.h | 5 ++
gdb/gdbserver/inferiors.c | 3 +
gdb/gdbserver/server.c | 171 +++++++++++++++++++++++++++++++++++++++++++++
gdb/gdbserver/target.h | 38 ++++++++++
4 files changed, 217 insertions(+), 0 deletions(-)
diff --git a/gdb/gdbserver/gdbthread.h b/gdb/gdbserver/gdbthread.h
index d863ec0..b2b6f62 100644
--- a/gdb/gdbserver/gdbthread.h
+++ b/gdb/gdbserver/gdbthread.h
@@ -22,6 +22,8 @@
#include "server.h"
+struct btrace_target_info;
+
struct thread_info
{
struct inferior_list_entry entry;
@@ -58,6 +60,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;
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 76abaf5..76f5731 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -161,6 +161,9 @@ free_one_thread (struct inferior_list_entry *inf)
void
remove_thread (struct thread_info *thread)
{
+ if (thread->btrace)
+ target_disable_btrace (thread->btrace);
+
remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
free_one_thread (&thread->entry);
}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index b3d1b41..87613b9 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -446,6 +446,85 @@ write_qxfer_response (char *buf, const void *data, int len, int is_more)
/* Handle all of the extended 'Q' packets. */
+static int
+handle_btrace_general_set (char *own_buf)
+{
+ char *operation = own_buf + strlen ("Qbtrace:");
+
+ if (strncmp ("Qbtrace:", own_buf, strlen ("Qbtrace:")) != 0)
+ return 0;
+
+ if (strncmp ("on:", operation, strlen ("on:")) == 0)
+ {
+ char* ptid_str = operation + strlen ("on:");
+ ptid_t ptid = read_ptid (ptid_str, NULL);
+ struct thread_info *thread = find_thread_ptid (ptid);
+
+ if (!thread)
+ {
+ fprintf (stderr, "No such thread: %s\n", ptid_str);
+ write_enn (own_buf);
+ }
+ else if (thread->btrace)
+ {
+ fprintf (stderr, "Btrace already enabled for %s\n", ptid_str);
+ write_enn (own_buf);
+ }
+ else
+ {
+ thread->btrace = target_enable_btrace (thread->entry.id);
+ if (!thread->btrace)
+ {
+ fprintf (stderr, "Could not enable btrace for %s: %s\n",
+ ptid_str, strerror (errno));
+ write_enn (own_buf);
+ }
+ else
+ write_ok (own_buf);
+ }
+ }
+ else if (strncmp ("off:", operation, strlen ("off:")) == 0)
+ {
+ char* ptid_str = operation + strlen ("off:");
+ ptid_t ptid = read_ptid (ptid_str, NULL);
+ struct thread_info *thread = find_thread_ptid (ptid);
+
+ if (!thread)
+ {
+ fprintf (stderr, "No such thread: %s\n", ptid_str);
+ write_enn (own_buf);
+ }
+ else if (!thread->btrace)
+ {
+ fprintf (stderr, "Btrace not enabled for %s\n", ptid_str);
+ write_enn (own_buf);
+ }
+ else
+ {
+ int errcode = target_disable_btrace (thread->btrace);
+ if (errcode)
+ {
+ fprintf (stderr, "Could not disable btrace for %s: %s\n",
+ ptid_str, strerror (errcode));
+ write_enn (own_buf);
+ }
+ else
+ {
+ thread->btrace = NULL;
+ write_ok (own_buf);
+ }
+ }
+ }
+ else
+ {
+ fprintf (stderr, "Unknown btrace operation: %s. Use on or off.\n",
+ own_buf);
+ write_enn (own_buf);
+ }
+
+ return 1;
+}
+
static void
handle_general_set (char *own_buf)
{
@@ -600,6 +679,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;
@@ -1298,6 +1380,57 @@ handle_qxfer_fdpic (const char *annex, gdb_byte *readbuf,
return (*the_target->read_loadmap) (annex, offset, readbuf, len);
}
+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;
+ ptid_t ptid;
+ int error;
+
+ if (!the_target->read_btrace || writebuf)
+ return -2;
+
+ if (!target_running () || !annex)
+ return -1;
+
+ ptid = read_ptid ((char *) annex, NULL);
+ thread = find_thread_ptid (ptid);
+ if (!thread)
+ {
+ fprintf (stderr, "No such thread: %s\n", annex);
+ return -1;
+ }
+ else if (!thread->btrace)
+ {
+ fprintf (stderr, "Btrace not enabled for %s\n", annex);
+ return -1;
+ }
+
+ if (!offset)
+ {
+ buffer_free (&cache);
+
+ error = target_read_btrace (thread->btrace, &cache);
+ if (error)
+ return -error;
+ }
+ else if (offset >= cache.used_size)
+ {
+ buffer_free (&cache);
+ return 0;
+ }
+
+ 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 },
@@ -1311,6 +1444,7 @@ static const struct qxfer qxfer_packets[] =
{ "statictrace", handle_qxfer_statictrace },
{ "threads", handle_qxfer_threads },
{ "traceframe-info", handle_qxfer_traceframe_info },
+ { "btrace", handle_qxfer_btrace },
};
static int
@@ -1467,6 +1601,33 @@ crc32 (CORE_ADDR base, int len, unsigned int crc)
/* Handle all of the extended 'q' packets. */
+static int
+handle_btrace_query (char *own_buf)
+{
+ if (strncmp ("qbtrace:", own_buf, strlen ("qbtrace:")) == 0)
+ {
+ char *ptid_str = own_buf + strlen ("qbtrace:");
+ ptid_t ptid = read_ptid (ptid_str, NULL);
+ struct thread_info *thread = find_thread_ptid (ptid);
+
+ if (!thread)
+ {
+ fprintf (stderr, "No such thread: %s\n", ptid_str);
+ write_enn (own_buf);
+ }
+ else if (!thread->btrace)
+ {
+ fprintf (stderr, "Btrace not enabled for %s\n", ptid_str);
+ write_enn (own_buf);
+ }
+ else
+ strcpy (own_buf,
+ (target_btrace_has_changed (thread->btrace) ? "yes" : "no"));
+ return 1;
+ }
+ return 0;
+}
+
void
handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
{
@@ -1693,6 +1854,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+");
+ strcat (own_buf, ";Qbtrace+");
+ strcat (own_buf, ";qXfer:btrace:read+");
+ }
+
return;
}
@@ -1883,6 +2051,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (target_supports_tracepoints () && handle_tracepoint_query (own_buf))
return;
+ if (handle_btrace_query (own_buf))
+ return;
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index dcf0230..f89b106 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -22,6 +22,8 @@
#define TARGET_H
struct emit_ops;
+struct btrace_target_info;
+struct buffer;
/* Ways to "resume" a thread. */
@@ -397,6 +399,23 @@ 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);
+
+ /* Check whether branch trace changed on the target. */
+ int (*btrace_has_changed) (struct btrace_target_info *);
+
+ /* Read branch trace data into buffer.
+ Returns 0 on success, an error code, otherwise. */
+ int (*read_btrace) (struct btrace_target_info *, struct buffer *);
};
extern struct target_ops *the_target;
@@ -521,6 +540,25 @@ void set_target_ops (struct target_ops *);
(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 ? \
+ (*the_target->enable_btrace) (ptid) : (errno = ENOSYS, NULL))
+
+#define target_disable_btrace(tinfo) \
+ (the_target->disable_btrace ? \
+ (*the_target->disable_btrace) (tinfo) : (errno = ENOSYS))
+
+#define target_btrace_has_changed(tinfo) \
+ (the_target->btrace_has_changed ? \
+ (*the_target->btrace_has_changed) (tinfo) : (errno = ENOSYS, 0))
+
+#define target_read_btrace(tinfo, buffer) \
+ (the_target->read_btrace ? \
+ (*the_target->read_btrace) (tinfo, buffer) : (errno = ENOSYS))
+
/* Start non-stop mode, returns 0 on success, -1 on failure. */
int start_non_stop (int nonstop);
--
1.7.1
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH 00/16] branch tracing support
2012-05-10 15:15 [PATCH 00/16] branch tracing support markus.t.metzger
` (15 preceding siblings ...)
2012-05-10 15:18 ` [PATCH 15/16] gdbserver, btrace: add generic btrace support markus.t.metzger
@ 2012-05-11 0:25 ` Hui Zhu
2012-05-11 8:17 ` Metzger, Markus T
16 siblings, 1 reply; 24+ messages in thread
From: Hui Zhu @ 2012-05-11 0:25 UTC (permalink / raw)
To: markus.t.metzger; +Cc: gdb-patches, markus.t.metzger
Hi Markus,
Thanks for your work. I think this function is very interesting.
But I didn't find the patch for the doc in your patches list. I
suggest you add it.
PS, do you have any data about how much speed decrease when btrace enable.
Thanks,
Hui
On Thu, May 10, 2012 at 11:13 PM, <markus.t.metzger@intel.com> wrote:
> From: Markus Metzger <markus.t.metzger@intel.com>
>
> IA hardware offers a feature called Branch Trace Store (BTS) that stores a log
> of branches into an OS provided ring buffer.
>
> Linux supports this feature since 2.6.32 as part of the perf_event interface.
>
> Branch tracing is very useful to debug problems that do not immediatly result in
> a crash. It is particularly useful for bugs that make other debugger features
> fail, e.g. a corrupted stack that breaks unwinding.
>
> In comparison with reverse debugging, branch tracing is less powerful but
> faster. In addition, the list view (see below) provides a quick overview of
> where you are, comparable with the backtrace command.
>
> This series adds commands to enable/disable branch tracing as well as to display
> the recorded trace:
>
> - "btrace enable/disable" perform the obvious operation
>
> They accept an optional range argument specifying the range of threads to
> enable/disable branch tracing for. If no argument is given, they target the
> current thread.
>
> They further accept the following arguments:
>
> all targets all threads
> auto turns automatic enabling for new threads on/off
>
> - "btrace list" prints the blocks that have been traced; one line per block.
>
> The output may be configured using modifiers (default: /fl). It prints:
> the block number
> /a the begin and end code address of that block
> /f the function containing the block
> /l the source lines contained in the block
>
> It accepts an optional range argument specifying the range of blocks to be
> listed. If no argument is given, all blocks are listed.
>
> Blocks are ordered from newest to oldest; block 1 always contains the
> current location.
>
> (gdb) btrace list 24-34
> 24 in stdio_file_flush () at ../../../git/gdb/ui-file.c:525-529
> 25 in ui_file_data () at ../../../git/gdb/ui-file.c:175-180
> 26 in stdio_file_flush () at ../../../git/gdb/ui-file.c:522-523
> 27 in gdb_flush () at ../../../git/gdb/ui-file.c:185
> 28 in gdb_wait_for_event () at ../../../git/gdb/event-loop.c:840-847
> 29 in gdb_do_one_event () at ../../../git/gdb/event-loop.c:461
> 30 in gdb_do_one_event () at ../../../git/gdb/event-loop.c:453
> 31 in process_event () at ../../../git/gdb/event-loop.c:407
> 32 in process_event () at ../../../git/gdb/event-loop.c:361-367
> 33 in process_event () at ../../../git/gdb/event-loop.c:1041-1043
> 34 in process_event () at ../../../git/gdb/event-loop.c:1041-1045
>
> - "btrace" prints the branch trace disassembly
>
> Branch trace is printed block-by-block. Typically, one block at a time is
> printed. Repeated commands will iterate over all blocks similar to the list
> command.
>
> It supports the /m and /r modifiers accepted by the disassemble command.
>
> It accepts an optional range argument specifying the range of blocks to be
> printed. If more than one block is given, blocks are printed in reverse
> order to preserve the original control flow.
>
> (gdb) btrace /m 25
> ../../../git/gdb/ui-file.c:175 {
> 0x0000000000635410 <ui_file_data+0>: sub $0x8,%rsp
>
> ../../../git/gdb/ui-file.c:176 if (file->magic != &ui_file_magic)
> 0x0000000000635414 <ui_file_data+4>: cmpq $0xb33b94,(%rdi)
> 0x000000000063541b <ui_file_data+11>: jne 0x635426 <ui_file_data+22>
>
> ../../../git/gdb/ui-file.c:177 internal_error (__FILE__, __LINE__,
> 0x000000000063541d <ui_file_data+13>: mov 0x50(%rdi),%rax
>
> ../../../git/gdb/ui-file.c:178 _("ui_file_data: bad magic number"));
> ../../../git/gdb/ui-file.c:179 return file->to_data;
> ../../../git/gdb/ui-file.c:180 }
> 0x0000000000635421 <ui_file_data+17>: add $0x8,%rsp
> 0x0000000000635425 <ui_file_data+21>: retq
>
> Mixed source and disassembly does not work very well for inlined functions,
> a problem that it shares with the disassemble command.
>
> Barkha Ahuja (1):
> test, btrace: more branch tracing tests
>
> Markus Metzger (15):
> disas: add precise instructions flag
> source: add flags to print_source_lines ()
> source, disasm: optionally prefix source lines with filename
> thread, btrace: add generic branch trace support
> cli, btrace: add btrace cli
> configure: add check for perf_event header
> configure: autoreconf
> linux, btrace: perf_event based branch tracing
> btrace, linux: add linux native btrace target ops
> btrace, config: enable btrace for 32bit and 64bit linux native
> test, btrace: add branch trace tests
> xml, btrace: define btrace xml document style
> remote, btrace: add branch trace remote ops
> gdbserver, btrace: add generic btrace support
> gdbserver, linux, btrace: add btrace support for linux-low
>
> .gitignore | 2 +
> gdb/Makefile.in | 14 +-
> gdb/amd64-linux-nat.c | 2 +
> gdb/btrace.c | 939 ++++++++++++++++++++++
> gdb/btrace.h | 92 +++
> gdb/command.h | 2 +-
> gdb/common/linux-btrace.c | 368 +++++++++
> gdb/common/linux-btrace.h | 76 ++
> gdb/config.in | 3 +
> gdb/config/i386/linux.mh | 3 +-
> gdb/config/i386/linux64.mh | 2 +-
> gdb/configure | 13 +
> gdb/configure.ac | 2 +
> gdb/disasm.c | 40 +-
> gdb/disasm.h | 8 +-
> gdb/features/btrace.dtd | 12 +
> gdb/gdbserver/Makefile.in | 6 +-
> gdb/gdbserver/config.in | 3 +
> gdb/gdbserver/configure | 2 +-
> gdb/gdbserver/configure.ac | 2 +-
> gdb/gdbserver/configure.srv | 34 +-
> gdb/gdbserver/gdbthread.h | 5 +
> gdb/gdbserver/inferiors.c | 3 +
> gdb/gdbserver/linux-low.c | 42 +
> gdb/gdbserver/server.c | 171 ++++
> gdb/gdbserver/target.h | 38 +
> gdb/gdbthread.h | 4 +
> gdb/i386-linux-nat.c | 2 +
> gdb/infcmd.c | 2 +
> gdb/linux-nat-btrace.c | 86 ++
> gdb/linux-nat-btrace.h | 28 +
> gdb/remote.c | 208 +++++
> gdb/source.c | 19 +-
> gdb/symtab.h | 6 +
> gdb/target.c | 20 +
> gdb/target.h | 36 +-
> gdb/testsuite/configure.ac | 2 +-
> gdb/testsuite/gdb.base/page.exp | 3 +-
> gdb/testsuite/gdb.btrace/Makefile.in | 13 +
> gdb/testsuite/gdb.btrace/a.s | 24 +
> gdb/testsuite/gdb.btrace/allthreads_trace.exp | 270 +++++++
> gdb/testsuite/gdb.btrace/b.s | 23 +
> gdb/testsuite/gdb.btrace/dec.c | 4 +
> gdb/testsuite/gdb.btrace/decrement.exp | 140 ++++
> gdb/testsuite/gdb.btrace/decrement.s | 32 +
> gdb/testsuite/gdb.btrace/disable_all.exp | 198 +++++
> gdb/testsuite/gdb.btrace/enable.exp | 83 ++
> gdb/testsuite/gdb.btrace/enable_all.exp | 201 +++++
> gdb/testsuite/gdb.btrace/enable_range.exp | 198 +++++
> gdb/testsuite/gdb.btrace/inc.c | 4 +
> gdb/testsuite/gdb.btrace/list.exp | 169 ++++
> gdb/testsuite/gdb.btrace/list.s | 68 ++
> gdb/testsuite/gdb.btrace/list_function.c | 12 +
> gdb/testsuite/gdb.btrace/list_function.exp | 59 ++
> gdb/testsuite/gdb.btrace/list_options.exp | 107 +++
> gdb/testsuite/gdb.btrace/main.s | 32 +
> gdb/testsuite/gdb.btrace/main_asm.exp | 113 +++
> gdb/testsuite/gdb.btrace/main_segv.exp | 84 ++
> gdb/testsuite/gdb.btrace/main_segv.s | 28 +
> gdb/testsuite/gdb.btrace/sanity_crash.exp | 69 ++
> gdb/testsuite/gdb.btrace/sanity_crash.s | 52 ++
> gdb/testsuite/gdb.btrace/thr_callback_32.s | 116 +++
> gdb/testsuite/gdb.btrace/thr_callback_64.s | 116 +++
> gdb/testsuite/gdb.btrace/threads.c | 96 +++
> gdb/testsuite/gdb.btrace/threads_asm.c | 78 ++
> gdb/testsuite/gdb.btrace/threads_auto.exp | 113 +++
> gdb/testsuite/gdb.btrace/threads_independent.exp | 119 +++
> gdb/testsuite/gdb.btrace/threads_nonstop.exp | 182 +++++
> gdb/testsuite/gdb.btrace/trace_iteration.exp | 264 ++++++
> gdb/testsuite/lib/btrace.exp | 72 ++
> gdb/thread.c | 3 +
> 71 files changed, 5393 insertions(+), 49 deletions(-)
> create mode 100644 gdb/btrace.c
> create mode 100644 gdb/btrace.h
> create mode 100644 gdb/common/linux-btrace.c
> create mode 100644 gdb/common/linux-btrace.h
> create mode 100644 gdb/features/btrace.dtd
> create mode 100644 gdb/linux-nat-btrace.c
> create mode 100644 gdb/linux-nat-btrace.h
> create mode 100755 gdb/testsuite/gdb.btrace/Makefile.in
> create mode 100755 gdb/testsuite/gdb.btrace/a.s
> create mode 100755 gdb/testsuite/gdb.btrace/allthreads_trace.exp
> create mode 100755 gdb/testsuite/gdb.btrace/b.s
> create mode 100644 gdb/testsuite/gdb.btrace/dec.c
> create mode 100755 gdb/testsuite/gdb.btrace/decrement.exp
> create mode 100755 gdb/testsuite/gdb.btrace/decrement.s
> create mode 100755 gdb/testsuite/gdb.btrace/disable_all.exp
> create mode 100644 gdb/testsuite/gdb.btrace/enable.exp
> create mode 100755 gdb/testsuite/gdb.btrace/enable_all.exp
> create mode 100755 gdb/testsuite/gdb.btrace/enable_range.exp
> create mode 100644 gdb/testsuite/gdb.btrace/inc.c
> create mode 100644 gdb/testsuite/gdb.btrace/list.exp
> create mode 100644 gdb/testsuite/gdb.btrace/list.s
> create mode 100644 gdb/testsuite/gdb.btrace/list_function.c
> create mode 100644 gdb/testsuite/gdb.btrace/list_function.exp
> create mode 100755 gdb/testsuite/gdb.btrace/list_options.exp
> create mode 100755 gdb/testsuite/gdb.btrace/main.s
> create mode 100755 gdb/testsuite/gdb.btrace/main_asm.exp
> create mode 100755 gdb/testsuite/gdb.btrace/main_segv.exp
> create mode 100755 gdb/testsuite/gdb.btrace/main_segv.s
> create mode 100755 gdb/testsuite/gdb.btrace/sanity_crash.exp
> create mode 100755 gdb/testsuite/gdb.btrace/sanity_crash.s
> create mode 100755 gdb/testsuite/gdb.btrace/thr_callback_32.s
> create mode 100755 gdb/testsuite/gdb.btrace/thr_callback_64.s
> create mode 100755 gdb/testsuite/gdb.btrace/threads.c
> create mode 100755 gdb/testsuite/gdb.btrace/threads_asm.c
> create mode 100755 gdb/testsuite/gdb.btrace/threads_auto.exp
> create mode 100755 gdb/testsuite/gdb.btrace/threads_independent.exp
> create mode 100755 gdb/testsuite/gdb.btrace/threads_nonstop.exp
> create mode 100755 gdb/testsuite/gdb.btrace/trace_iteration.exp
> create mode 100644 gdb/testsuite/lib/btrace.exp
>
^ permalink raw reply [flat|nested] 24+ messages in thread* RE: [PATCH 00/16] branch tracing support
2012-05-11 0:25 ` [PATCH 00/16] branch tracing support Hui Zhu
@ 2012-05-11 8:17 ` Metzger, Markus T
0 siblings, 0 replies; 24+ messages in thread
From: Metzger, Markus T @ 2012-05-11 8:17 UTC (permalink / raw)
To: Hui Zhu; +Cc: gdb-patches, markus.t.metzger
[-- Attachment #1.1: Type: text/plain, Size: 964 bytes --]
> -----Original Message-----
> From: Hui Zhu [mailto:teawater@gmail.com]
> Sent: Friday, May 11, 2012 2:24 AM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org; markus.t.metzger@gmail.com
> Subject: Re: [PATCH 00/16] branch tracing support
>
> Hi Markus,
>
> Thanks for your work. I think this function is very interesting.
>
> But I didn't find the patch for the doc in your patches list. I
> suggest you add it.
I expect some discussion on the commands and their exact spelling. I will add
documentation once the UI is clear, if that's OK.
I tried to summarize it in the cover letter. I hope it's sufficiently detailed
for
discussion. If it helps, I can send a documentation patch, as well, but I'm
afraid
I might end up redoing it completely.
> PS, do you have any data about how much speed decrease when btrace
> enable.
The speed decrease depends very heavily on the application. We measured
between 8.7x and 66x overhead.
Regards,
Markus.
[-- Attachment #1.2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 7228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 417 bytes --]
--------------------------------------------------------------------------------------
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Douglas Lusk, Peter Gleissner, Hannes Schwaderer
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
^ permalink raw reply [flat|nested] 24+ messages in thread