/* Branch trace support for GDB, the GNU debugger.
- Copyright (C) 2013-2019 Free Software Foundation, Inc.
+ Copyright (C) 2013-2020 Free Software Foundation, Inc.
Contributed by Intel Corp. <markus.t.metzger@intel.com>
#include "frame-unwind.h"
#include "hashtab.h"
#include "infrun.h"
-#include "event-loop.h"
+#include "gdbsupport/event-loop.h"
#include "inf-loop.h"
#include "inferior.h"
#include <algorithm>
#include "gdbarch.h"
#include "cli/cli-style.h"
+#include "async-event.h"
static const target_info record_btrace_target_info = {
"record-btrace",
static void
record_btrace_enable_warn (struct thread_info *tp)
{
+ /* Ignore this thread if its inferior is not recorded by us. */
+ target_ops *rec = tp->inf->target_at (record_stratum);
+ if (rec != &record_btrace_ops)
+ return;
+
try
{
btrace_enable (tp, &record_btrace_conf);
if (!target_has_execution)
error (_("The program is not being run."));
- for (thread_info *tp : all_non_exited_threads ())
+ for (thread_info *tp : current_inferior ()->non_exited_threads ())
if (args == NULL || *args == 0 || number_is_in_list (args, tp->global_num))
{
btrace_enable (tp, &record_btrace_conf);
record_btrace_auto_disable ();
- for (thread_info *tp : all_non_exited_threads ())
+ for (thread_info *tp : current_inferior ()->non_exited_threads ())
if (tp->btrace.target != NULL)
btrace_disable (tp);
}
/* We should have already stopped recording.
Tear down btrace in case we have not. */
- for (thread_info *tp : all_non_exited_threads ())
+ for (thread_info *tp : current_inferior ()->non_exited_threads ())
btrace_teardown (tp);
}
return;
}
- internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+ internal_error (__FILE__, __LINE__, _("Unknown branch trace format."));
}
/* The info_record method of target record-btrace. */
DEBUG ("info");
- tp = find_thread_ptid (inferior_ptid);
- if (tp == NULL)
+ if (inferior_ptid == null_ptid)
error (_("No thread."));
+ tp = inferior_thread ();
+
validate_registers_access ();
btinfo = &tp->btrace;
range = btrace_mk_line_range (symtab, 0, 0);
for (i = 0; i < nlines - 1; i++)
{
- if ((lines[i].pc == pc) && (lines[i].line != 0))
+ /* The test of is_stmt here was added when the is_stmt field was
+ introduced to the 'struct linetable_entry' structure. This
+ ensured that this loop maintained the same behaviour as before we
+ introduced is_stmt. That said, it might be that we would be
+ better off not checking is_stmt here, this would lead to us
+ possibly adding more line numbers to the range. At the time this
+ change was made I was unsure how to test this so chose to go with
+ maintaining the existing experience. */
+ if ((lines[i].pc == pc) && (lines[i].line != 0)
+ && (lines[i].is_stmt == 1))
range = btrace_line_range_add (range, lines[i].line);
}
sym = bfun->sym;
if (sym != NULL)
- return SYMBOL_PRINT_NAME (sym);
+ return sym->print_name ();
else if (msym != NULL)
return msym->print_name ();
else
}
if (sym != NULL)
- uiout->field_string ("function", SYMBOL_PRINT_NAME (sym),
+ uiout->field_string ("function", sym->print_name (),
function_name_style.style ());
else if (msym != NULL)
uiout->field_string ("function", msym->print_name (),
enum record_method
record_btrace_target::record_method (ptid_t ptid)
{
- struct thread_info * const tp = find_thread_ptid (ptid);
+ process_stratum_target *proc_target = current_inferior ()->process_target ();
+ thread_info *const tp = find_thread_ptid (proc_target, ptid);
if (tp == NULL)
error (_("No thread."));
bool
record_btrace_target::record_is_replaying (ptid_t ptid)
{
- for (thread_info *tp : all_non_exited_threads (ptid))
+ process_stratum_target *proc_target = current_inferior ()->process_target ();
+ for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
if (btrace_is_replaying (tp))
return true;
void
record_btrace_target::fetch_registers (struct regcache *regcache, int regno)
{
- struct btrace_insn_iterator *replay;
- struct thread_info *tp;
+ btrace_insn_iterator *replay = nullptr;
- tp = find_thread_ptid (regcache->ptid ());
- gdb_assert (tp != NULL);
+ /* Thread-db may ask for a thread's registers before GDB knows about the
+ thread. We forward the request to the target beneath in this
+ case. */
+ thread_info *tp = find_thread_ptid (regcache->target (), regcache->ptid ());
+ if (tp != nullptr)
+ replay = tp->btrace.replay;
- replay = tp->btrace.replay;
- if (replay != NULL && !record_btrace_generating_corefile)
+ if (replay != nullptr && !record_btrace_generating_corefile)
{
const struct btrace_insn *insn;
struct gdbarch *gdbarch;
get_thread_current_frame_id (struct thread_info *tp)
{
struct frame_id id;
- int executing;
+ bool executing;
/* Set current thread, which is implicitly used by
get_current_frame. */
switch_to_thread (tp);
+ process_stratum_target *proc_target = tp->inf->process_target ();
+
/* Clear the executing flag to allow changes to the current frame.
We are not actually running, yet. We just started a reverse execution
command or a record goto command.
move the thread. Since we need to recompute the stack, we temporarily
set EXECUTING to false. */
executing = tp->executing;
- set_executing (inferior_ptid, false);
+ set_executing (proc_target, inferior_ptid, false);
id = null_frame_id;
try
catch (const gdb_exception &except)
{
/* Restore the previous execution state. */
- set_executing (inferior_ptid, executing);
+ set_executing (proc_target, inferior_ptid, executing);
throw;
}
/* Restore the previous execution state. */
- set_executing (inferior_ptid, executing);
+ set_executing (proc_target, inferior_ptid, executing);
return id;
}
record_btrace_wait below.
For all-stop targets, we only step INFERIOR_PTID and continue others. */
+
+ process_stratum_target *proc_target = current_inferior ()->process_target ();
+
if (!target_is_non_stop_p ())
{
gdb_assert (inferior_ptid.matches (ptid));
- for (thread_info *tp : all_non_exited_threads (ptid))
+ for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
{
if (tp->ptid.matches (inferior_ptid))
record_btrace_resume_thread (tp, flag);
}
else
{
- for (thread_info *tp : all_non_exited_threads (ptid))
+ for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
record_btrace_resume_thread (tp, flag);
}
}
/* Keep a work list of moving threads. */
- for (thread_info *tp : all_non_exited_threads (ptid))
+ process_stratum_target *proc_target = current_inferior ()->process_target ();
+ for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
if ((tp->btrace.flags & (BTHR_MOVE | BTHR_STOP)) != 0)
moving.push_back (tp);
/* Stop all other threads. */
if (!target_is_non_stop_p ())
{
- for (thread_info *tp : all_non_exited_threads ())
+ for (thread_info *tp : current_inferior ()->non_exited_threads ())
record_btrace_cancel_resume (tp);
}
}
else
{
- for (thread_info *tp : all_non_exited_threads (ptid))
+ process_stratum_target *proc_target
+ = current_inferior ()->process_target ();
+
+ for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
{
tp->btrace.flags &= ~BTHR_MOVE;
tp->btrace.flags |= BTHR_STOP;
void
record_btrace_target::record_stop_replaying ()
{
- for (thread_info *tp : all_non_exited_threads ())
+ for (thread_info *tp : current_inferior ()->non_exited_threads ())
record_btrace_stop_replaying (tp);
}
}
}
-/* The "set record btrace" command. */
-
-static void
-cmd_set_record_btrace (const char *args, int from_tty)
-{
- printf_unfiltered (_("\"set record btrace\" must be followed "
- "by an appropriate subcommand.\n"));
- help_list (set_record_btrace_cmdlist, "set record btrace ",
- all_commands, gdb_stdout);
-}
-
-/* The "show record btrace" command. */
-
-static void
-cmd_show_record_btrace (const char *args, int from_tty)
-{
- cmd_show_list (show_record_btrace_cmdlist, from_tty, "");
-}
-
/* The "show record btrace replay-memory-access" command. */
static void
error (_("Internal error: bad cpu state."));
}
-/* The "s record btrace bts" command. */
-
-static void
-cmd_set_record_btrace_bts (const char *args, int from_tty)
-{
- printf_unfiltered (_("\"set record btrace bts\" must be followed "
- "by an appropriate subcommand.\n"));
- help_list (set_record_btrace_bts_cmdlist, "set record btrace bts ",
- all_commands, gdb_stdout);
-}
-
-/* The "show record btrace bts" command. */
-
-static void
-cmd_show_record_btrace_bts (const char *args, int from_tty)
-{
- cmd_show_list (show_record_btrace_bts_cmdlist, from_tty, "");
-}
-
-/* The "set record btrace pt" command. */
-
-static void
-cmd_set_record_btrace_pt (const char *args, int from_tty)
-{
- printf_unfiltered (_("\"set record btrace pt\" must be followed "
- "by an appropriate subcommand.\n"));
- help_list (set_record_btrace_pt_cmdlist, "set record btrace pt ",
- all_commands, gdb_stdout);
-}
-
-/* The "show record btrace pt" command. */
-
-static void
-cmd_show_record_btrace_pt (const char *args, int from_tty)
-{
- cmd_show_list (show_record_btrace_pt_cmdlist, from_tty, "");
-}
-
/* The "record bts buffer-size" show value function. */
static void
/* Initialize btrace commands. */
+void _initialize_record_btrace ();
void
-_initialize_record_btrace (void)
+_initialize_record_btrace ()
{
add_prefix_cmd ("btrace", class_obscure, cmd_record_btrace_start,
_("Start branch trace recording."), &record_btrace_cmdlist,
&record_btrace_cmdlist);
add_alias_cmd ("pt", "btrace pt", class_obscure, 1, &record_cmdlist);
- add_prefix_cmd ("btrace", class_support, cmd_set_record_btrace,
- _("Set record options."), &set_record_btrace_cmdlist,
- "set record btrace ", 0, &set_record_cmdlist);
+ add_basic_prefix_cmd ("btrace", class_support,
+ _("Set record options."), &set_record_btrace_cmdlist,
+ "set record btrace ", 0, &set_record_cmdlist);
- add_prefix_cmd ("btrace", class_support, cmd_show_record_btrace,
- _("Show record options."), &show_record_btrace_cmdlist,
- "show record btrace ", 0, &show_record_cmdlist);
+ add_show_prefix_cmd ("btrace", class_support,
+ _("Show record options."), &show_record_btrace_cmdlist,
+ "show record btrace ", 0, &show_record_cmdlist);
add_setshow_enum_cmd ("replay-memory-access", no_class,
replay_memory_access_types, &replay_memory_access, _("\
Show the cpu to be used for trace decode."),
&show_record_btrace_cmdlist);
- add_prefix_cmd ("bts", class_support, cmd_set_record_btrace_bts,
- _("Set record btrace bts options."),
- &set_record_btrace_bts_cmdlist,
- "set record btrace bts ", 0, &set_record_btrace_cmdlist);
+ add_basic_prefix_cmd ("bts", class_support,
+ _("Set record btrace bts options."),
+ &set_record_btrace_bts_cmdlist,
+ "set record btrace bts ", 0,
+ &set_record_btrace_cmdlist);
- add_prefix_cmd ("bts", class_support, cmd_show_record_btrace_bts,
- _("Show record btrace bts options."),
- &show_record_btrace_bts_cmdlist,
- "show record btrace bts ", 0, &show_record_btrace_cmdlist);
+ add_show_prefix_cmd ("bts", class_support,
+ _("Show record btrace bts options."),
+ &show_record_btrace_bts_cmdlist,
+ "show record btrace bts ", 0,
+ &show_record_btrace_cmdlist);
add_setshow_uinteger_cmd ("buffer-size", no_class,
&record_btrace_conf.bts.size,
&set_record_btrace_bts_cmdlist,
&show_record_btrace_bts_cmdlist);
- add_prefix_cmd ("pt", class_support, cmd_set_record_btrace_pt,
- _("Set record btrace pt options."),
- &set_record_btrace_pt_cmdlist,
- "set record btrace pt ", 0, &set_record_btrace_cmdlist);
-
- add_prefix_cmd ("pt", class_support, cmd_show_record_btrace_pt,
- _("Show record btrace pt options."),
- &show_record_btrace_pt_cmdlist,
- "show record btrace pt ", 0, &show_record_btrace_cmdlist);
+ add_basic_prefix_cmd ("pt", class_support,
+ _("Set record btrace pt options."),
+ &set_record_btrace_pt_cmdlist,
+ "set record btrace pt ", 0,
+ &set_record_btrace_cmdlist);
+
+ add_show_prefix_cmd ("pt", class_support,
+ _("Show record btrace pt options."),
+ &show_record_btrace_pt_cmdlist,
+ "show record btrace pt ", 0,
+ &show_record_btrace_cmdlist);
add_setshow_uinteger_cmd ("buffer-size", no_class,
&record_btrace_conf.pt.size,