/* Branch trace support for GDB, the GNU debugger.
- Copyright (C) 2013-2021 Free Software Foundation, Inc.
+ Copyright (C) 2013-2022 Free Software Foundation, Inc.
Contributed by Intel Corp. <markus.t.metzger@intel.com>
const struct frame_unwind *get_tailcall_unwinder () override;
- void commit_resume () override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
return &tp->btrace;
}
-/* Enable branch tracing for one thread. Warn on errors. */
+/* The new thread observer. */
static void
-record_btrace_enable_warn (struct thread_info *tp)
+record_btrace_on_new_thread (struct thread_info *tp)
{
/* Ignore this thread if its inferior is not recorded by us. */
target_ops *rec = tp->inf->target_at (record_stratum);
{
DEBUG ("attach thread observer");
- gdb::observers::new_thread.attach (record_btrace_enable_warn,
- record_btrace_thread_observer_token);
+ gdb::observers::new_thread.attach (record_btrace_on_new_thread,
+ record_btrace_thread_observer_token,
+ "record-btrace");
}
/* Disable automatic tracing of new threads. */
record_btrace_auto_enable ();
- push_target (&record_btrace_ops);
+ current_inferior ()->push_target (&record_btrace_ops);
record_btrace_async_inferior_event_handler
= create_async_event_handler (record_btrace_handle_async_inferior_event,
struct target_ops *beneath = this->beneath ();
/* Do not stop recording, just clean up GDB side. */
- unpush_target (this);
+ current_inferior ()->unpush_target (this);
/* Forward disconnect. */
beneath->disconnect (args, from_tty);
if (size > 0)
{
suffix = record_btrace_adjust_size (&size);
- printf_unfiltered (_("Buffer size: %u%s.\n"), size, suffix);
+ printf_filtered (_("Buffer size: %u%s.\n"), size, suffix);
}
}
if (size > 0)
{
suffix = record_btrace_adjust_size (&size);
- printf_unfiltered (_("Buffer size: %u%s.\n"), size, suffix);
+ printf_filtered (_("Buffer size: %u%s.\n"), size, suffix);
}
}
static void
record_btrace_print_conf (const struct btrace_config *conf)
{
- printf_unfiltered (_("Recording format: %s.\n"),
- btrace_format_string (conf->format));
+ printf_filtered (_("Recording format: %s.\n"),
+ btrace_format_string (conf->format));
switch (conf->format)
{
gaps = btinfo->ngaps;
}
- printf_unfiltered (_("Recorded %u instructions in %u functions (%u gaps) "
- "for thread %s (%s).\n"), insns, calls, gaps,
- print_thread_id (tp),
- target_pid_to_str (tp->ptid).c_str ());
+ printf_filtered (_("Recorded %u instructions in %u functions (%u gaps) "
+ "for thread %s (%s).\n"), insns, calls, gaps,
+ print_thread_id (tp),
+ target_pid_to_str (tp->ptid).c_str ());
if (btrace_is_replaying (tp))
- printf_unfiltered (_("Replay in progress. At instruction %u.\n"),
- btrace_insn_number (btinfo->replay));
+ printf_filtered (_("Replay in progress. At instruction %u.\n"),
+ btrace_insn_number (btinfo->replay));
}
/* Print a decode error. */
if (symtab == NULL)
return btrace_mk_line_range (NULL, 0, 0);
- ltable = SYMTAB_LINETABLE (symtab);
+ ltable = symtab->linetable ();
if (ltable == NULL)
return btrace_mk_line_range (symtab, 0, 0);
else
{
if (size < 0)
- printf_unfiltered (_("At the start of the branch trace record.\n"));
+ printf_filtered (_("At the start of the branch trace record.\n"));
else
- printf_unfiltered (_("At the end of the branch trace record.\n"));
+ printf_filtered (_("At the end of the branch trace record.\n"));
}
btrace_set_insn_history (btinfo, &begin, &end);
else
{
if (size < 0)
- printf_unfiltered (_("At the start of the branch trace record.\n"));
+ printf_filtered (_("At the start of the branch trace record.\n"));
else
- printf_unfiltered (_("At the end of the branch trace record.\n"));
+ printf_filtered (_("At the end of the branch trace record.\n"));
}
btrace_set_call_history (btinfo, &begin, &end);
{
case TARGET_OBJECT_MEMORY:
{
- struct target_section *section;
+ const struct target_section *section;
/* We do not allow writing memory in general. */
if (writebuf != NULL)
const struct frame_unwind record_btrace_frame_unwind =
{
+ "record-btrace",
NORMAL_FRAME,
record_btrace_frame_unwind_stop_reason,
record_btrace_frame_this_id,
const struct frame_unwind record_btrace_tailcall_frame_unwind =
{
+ "record-btrace tailcall",
TAILCALL_FRAME,
record_btrace_frame_unwind_stop_reason,
record_btrace_frame_this_id,
struct btrace_thread_info *btinfo;
DEBUG ("resuming thread %s (%s): %x (%s)", print_thread_id (tp),
- target_pid_to_str (tp->ptid).c_str (), flag,
+ tp->ptid.to_string ().c_str (), flag,
btrace_thread_flag_to_str (flag));
btinfo = &tp->btrace;
static struct frame_id
get_thread_current_frame_id (struct thread_info *tp)
{
- struct frame_id id;
- bool executing;
-
/* Set current thread, which is implicitly used by
get_current_frame. */
scoped_restore_current_thread restore_thread;
For the former, EXECUTING is true and we're in wait, about to
move the thread. Since we need to recompute the stack, we temporarily
set EXECUTING to false. */
- executing = tp->executing;
+ bool executing = tp->executing ();
set_executing (proc_target, inferior_ptid, false);
-
- id = null_frame_id;
- try
+ SCOPE_EXIT
{
- id = get_frame_id (get_current_frame ());
- }
- catch (const gdb_exception &except)
- {
- /* Restore the previous execution state. */
set_executing (proc_target, inferior_ptid, executing);
-
- throw;
- }
-
- /* Restore the previous execution state. */
- set_executing (proc_target, inferior_ptid, executing);
-
- return id;
+ };
+ return get_frame_id (get_current_frame ());
}
/* Start replaying a thread. */
{
enum btrace_thread_flag flag, cflag;
- DEBUG ("resume %s: %s%s", target_pid_to_str (ptid).c_str (),
+ DEBUG ("resume %s: %s%s", ptid.to_string ().c_str (),
::execution_direction == EXEC_REVERSE ? "reverse-" : "",
step ? "step" : "cont");
}
}
-/* The commit_resume method of target record-btrace. */
-
-void
-record_btrace_target::commit_resume ()
-{
- if ((::execution_direction != EXEC_REVERSE)
- && !record_is_replaying (minus_one_ptid))
- beneath ()->commit_resume ();
-}
-
/* Cancel resuming TP. */
static void
DEBUG ("cancel resume thread %s (%s): %x (%s)",
print_thread_id (tp),
- target_pid_to_str (tp->ptid).c_str (), flags.raw (),
+ tp->ptid.to_string ().c_str (), flags.raw (),
btrace_thread_flag_to_str (flags));
tp->btrace.flags &= ~(BTHR_MOVE | BTHR_STOP);
{
struct target_waitstatus status;
- status.kind = TARGET_WAITKIND_NO_HISTORY;
+ status.set_no_history ();
return status;
}
{
struct target_waitstatus status;
- status.kind = TARGET_WAITKIND_STOPPED;
- status.value.sig = GDB_SIGNAL_TRAP;
+ status.set_stopped (GDB_SIGNAL_TRAP);
return status;
}
{
struct target_waitstatus status;
- status.kind = TARGET_WAITKIND_STOPPED;
- status.value.sig = GDB_SIGNAL_0;
+ status.set_stopped (GDB_SIGNAL_0);
return status;
}
{
struct target_waitstatus status;
- status.kind = TARGET_WAITKIND_SPURIOUS;
+ status.set_spurious ();
return status;
}
{
struct target_waitstatus status;
- status.kind = TARGET_WAITKIND_NO_RESUMED;
+ status.set_no_resumed ();
return status;
}
{
struct target_waitstatus status;
- status.kind = TARGET_WAITKIND_IGNORE;
+ status.set_ignore ();
return status;
}
btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP);
DEBUG ("stepping thread %s (%s): %x (%s)", print_thread_id (tp),
- target_pid_to_str (tp->ptid).c_str (), flags.raw (),
+ tp->ptid.to_string ().c_str (), flags.raw (),
btrace_thread_flag_to_str (flags));
/* We can't step without an execution history. */
case BTHR_STEP:
status = record_btrace_single_step_forward (tp);
- if (status.kind != TARGET_WAITKIND_SPURIOUS)
+ if (status.kind () != TARGET_WAITKIND_SPURIOUS)
break;
return btrace_step_stopped ();
case BTHR_RSTEP:
status = record_btrace_single_step_backward (tp);
- if (status.kind != TARGET_WAITKIND_SPURIOUS)
+ if (status.kind () != TARGET_WAITKIND_SPURIOUS)
break;
return btrace_step_stopped ();
case BTHR_CONT:
status = record_btrace_single_step_forward (tp);
- if (status.kind != TARGET_WAITKIND_SPURIOUS)
+ if (status.kind () != TARGET_WAITKIND_SPURIOUS)
break;
btinfo->flags |= flags;
case BTHR_RCONT:
status = record_btrace_single_step_backward (tp);
- if (status.kind != TARGET_WAITKIND_SPURIOUS)
+ if (status.kind () != TARGET_WAITKIND_SPURIOUS)
break;
btinfo->flags |= flags;
/* We keep threads moving at the end of their execution history. The wait
method will stop the thread for whom the event is reported. */
- if (status.kind == TARGET_WAITKIND_NO_HISTORY)
+ if (status.kind () == TARGET_WAITKIND_NO_HISTORY)
btinfo->flags |= flags;
return status;
std::vector<thread_info *> moving;
std::vector<thread_info *> no_history;
- DEBUG ("wait %s (0x%x)", target_pid_to_str (ptid).c_str (),
+ /* Clear this, if needed we'll re-mark it below. */
+ clear_async_event_handler (record_btrace_async_inferior_event_handler);
+
+ DEBUG ("wait %s (0x%x)", ptid.to_string ().c_str (),
(unsigned) options);
/* As long as we're not replaying, just forward the request. */
{
*status = btrace_step_no_resumed ();
- DEBUG ("wait ended by %s: %s", target_pid_to_str (null_ptid).c_str (),
- target_waitstatus_to_string (status).c_str ());
+ DEBUG ("wait ended by %s: %s", null_ptid.to_string ().c_str (),
+ status->to_string ().c_str ());
return null_ptid;
}
*status = record_btrace_step_thread (tp);
- switch (status->kind)
+ switch (status->kind ())
{
case TARGET_WAITKIND_IGNORE:
ix++;
DEBUG ("wait ended by thread %s (%s): %s",
print_thread_id (eventing),
- target_pid_to_str (eventing->ptid).c_str (),
- target_waitstatus_to_string (status).c_str ());
+ eventing->ptid.to_string ().c_str (),
+ status->to_string ().c_str ());
return eventing->ptid;
}
void
record_btrace_target::stop (ptid_t ptid)
{
- DEBUG ("stop %s", target_pid_to_str (ptid).c_str ());
+ DEBUG ("stop %s", ptid.to_string ().c_str ());
/* As long as we're not replaying, just forward the request. */
if ((::execution_direction != EXEC_REVERSE)
/* Start anew from the new replay position. */
record_btrace_clear_histories (btinfo);
- inferior_thread ()->suspend.stop_pc
- = regcache_read_pc (get_current_regcache ());
+ inferior_thread ()->set_stop_pc (regcache_read_pc (get_current_regcache ()));
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
}
cmd_show_replay_memory_access (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (gdb_stdout, _("Replay memory access is %s.\n"),
+ fprintf_filtered (file, _("Replay memory access is %s.\n"),
replay_memory_access);
}
switch (record_btrace_cpu_state)
{
case CS_AUTO:
- printf_unfiltered (_("btrace cpu is 'auto'.\n"));
+ printf_filtered (_("btrace cpu is 'auto'.\n"));
return;
case CS_NONE:
- printf_unfiltered (_("btrace cpu is 'none'.\n"));
+ printf_filtered (_("btrace cpu is 'none'.\n"));
return;
case CS_CPU:
{
case CV_INTEL:
if (record_btrace_cpu.stepping == 0)
- printf_unfiltered (_("btrace cpu is 'intel: %u/%u'.\n"),
- record_btrace_cpu.family,
- record_btrace_cpu.model);
+ printf_filtered (_("btrace cpu is 'intel: %u/%u'.\n"),
+ record_btrace_cpu.family,
+ record_btrace_cpu.model);
else
- printf_unfiltered (_("btrace cpu is 'intel: %u/%u/%u'.\n"),
- record_btrace_cpu.family,
- record_btrace_cpu.model,
- record_btrace_cpu.stepping);
+ printf_filtered (_("btrace cpu is 'intel: %u/%u/%u'.\n"),
+ record_btrace_cpu.family,
+ record_btrace_cpu.model,
+ record_btrace_cpu.stepping);
return;
}
}
void
_initialize_record_btrace ()
{
- add_prefix_cmd ("btrace", class_obscure, cmd_record_btrace_start,
- _("Start branch trace recording."), &record_btrace_cmdlist,
- "record btrace ", 0, &record_cmdlist);
- add_alias_cmd ("b", "btrace", class_obscure, 1, &record_cmdlist);
+ cmd_list_element *record_btrace_cmd
+ = add_prefix_cmd ("btrace", class_obscure, cmd_record_btrace_start,
+ _("Start branch trace recording."),
+ &record_btrace_cmdlist, 0, &record_cmdlist);
+ add_alias_cmd ("b", record_btrace_cmd, class_obscure, 1, &record_cmdlist);
- add_cmd ("bts", class_obscure, cmd_record_btrace_bts_start,
- _("\
+ cmd_list_element *record_btrace_bts_cmd
+ = add_cmd ("bts", class_obscure, cmd_record_btrace_bts_start,
+ _("\
Start branch trace recording in Branch Trace Store (BTS) format.\n\n\
The processor stores a from/to record for each branch into a cyclic buffer.\n\
This format may not be available on all processors."),
- &record_btrace_cmdlist);
- add_alias_cmd ("bts", "btrace bts", class_obscure, 1, &record_cmdlist);
+ &record_btrace_cmdlist);
+ add_alias_cmd ("bts", record_btrace_bts_cmd, class_obscure, 1,
+ &record_cmdlist);
- add_cmd ("pt", class_obscure, cmd_record_btrace_pt_start,
- _("\
+ cmd_list_element *record_btrace_pt_cmd
+ = add_cmd ("pt", class_obscure, cmd_record_btrace_pt_start,
+ _("\
Start branch trace recording in Intel Processor Trace format.\n\n\
This format may not be available on all processors."),
- &record_btrace_cmdlist);
- add_alias_cmd ("pt", "btrace pt", class_obscure, 1, &record_cmdlist);
+ &record_btrace_cmdlist);
+ add_alias_cmd ("pt", record_btrace_pt_cmd, class_obscure, 1, &record_cmdlist);
- add_basic_prefix_cmd ("btrace", class_support,
- _("Set record options."), &set_record_btrace_cmdlist,
- "set record btrace ", 0, &set_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_prefix_cmd ("btrace", class_support,
+ _("Set record options."),
+ _("Show record options."),
+ &set_record_btrace_cmdlist,
+ &show_record_btrace_cmdlist,
+ &set_record_cmdlist, &show_record_cmdlist);
add_setshow_enum_cmd ("replay-memory-access", no_class,
replay_memory_access_types, &replay_memory_access, _("\
workarounds for a similar cpu that GDB supports.\n\n\
When set to \"none\", errata workarounds are disabled."),
&set_record_btrace_cpu_cmdlist,
- "set record btrace cpu ", 1,
+ 1,
&set_record_btrace_cmdlist);
add_cmd ("auto", class_support, cmd_set_record_btrace_cpu_auto, _("\
Show the cpu to be used for trace decode."),
&show_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_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_prefix_cmd ("bts", class_support,
+ _("Set record btrace bts options."),
+ _("Show record btrace bts options."),
+ &set_record_btrace_bts_cmdlist,
+ &show_record_btrace_bts_cmdlist,
+ &set_record_btrace_cmdlist,
+ &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_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_prefix_cmd ("pt", class_support,
+ _("Set record btrace pt options."),
+ _("Show record btrace pt options."),
+ &set_record_btrace_pt_cmdlist,
+ &show_record_btrace_pt_cmdlist,
+ &set_record_btrace_cmdlist,
+ &show_record_btrace_cmdlist);
add_setshow_uinteger_cmd ("buffer-size", no_class,
&record_btrace_conf.pt.size,