/* Branch trace support for GDB, the GNU debugger.
- Copyright (C) 2013-2019 Free Software Foundation, Inc.
+ Copyright (C) 2013-2023 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 "common/vec.h"
#include "inferior.h"
#include <algorithm>
+#include "gdbarch.h"
+#include "cli/cli-style.h"
+#include "async-event.h"
+#include <forward_list>
+#include "objfiles.h"
+#include "interps.h"
static const target_info record_btrace_target_info = {
"record-btrace",
strata stratum () const override { return record_stratum; }
void close () override;
- void async (int) override;
+ void async (bool) override;
void detach (inferior *inf, int from_tty) override
{ record_detach (this, inf, from_tty); }
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 *, int) override;
+ ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
void stop (ptid_t) override;
void update_thread_list () override;
do \
{ \
if (record_debug != 0) \
- fprintf_unfiltered (gdb_stdlog, \
- "[record-btrace] " msg "\n", ##args); \
+ gdb_printf (gdb_stdlog, \
+ "[record-btrace] " msg "\n", ##args); \
} \
while (0)
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)
{
- TRY
+ /* 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);
}
- CATCH (error, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &error)
{
- warning ("%s", error.message);
+ warning ("%s", error.what ());
}
- END_CATCH
}
/* Enable automatic tracing of new threads. */
{
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. */
static void
record_btrace_handle_async_inferior_event (gdb_client_data data)
{
- inferior_event_handler (INF_REG_EVENT, NULL);
+ inferior_event_handler (INF_REG_EVENT);
}
/* See record-btrace.h. */
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,
- NULL);
+ NULL, "record-btrace");
record_btrace_generating_corefile = 0;
format = btrace_format_short_string (record_btrace_conf.format);
- gdb::observers::record_changed.notify (current_inferior (), 1, "btrace", format);
+ interps_notify_record_changed (current_inferior (), 1, "btrace", format);
}
/* Disable btrace on a set of threads on scope exit. */
record_preopen ();
- if (!target_has_execution)
+ 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);
}
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);
/* 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);
}
/* The async method of target record-btrace. */
void
-record_btrace_target::async (int enable)
+record_btrace_target::async (bool enable)
{
if (enable)
mark_async_event_handler (record_btrace_async_inferior_event_handler);
if (size > 0)
{
suffix = record_btrace_adjust_size (&size);
- printf_unfiltered (_("Buffer size: %u%s.\n"), size, suffix);
+ gdb_printf (_("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);
+ gdb_printf (_("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));
+ gdb_printf (_("Recording format: %s.\n"),
+ btrace_format_string (conf->format));
switch (conf->format)
{
return;
}
- internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
+ internal_error (_("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;
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 ());
+ gdb_printf (_("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));
+ gdb_printf (_("Replay in progress. At instruction %u.\n"),
+ btrace_insn_number (btinfo->replay));
}
/* Print a decode error. */
if (!(format == BTRACE_FORMAT_PT && errcode > 0))
{
uiout->text (_("decode error ("));
- uiout->field_int ("errcode", errcode);
+ uiout->field_signed ("errcode", errcode);
uiout->text (_("): "));
}
uiout->text (errstr);
uiout->text (_("]\n"));
}
-/* Print an unsigned int. */
-
-static void
-ui_out_field_uint (struct ui_out *uiout, const char *fld, unsigned int val)
-{
- uiout->field_fmt (fld, "%u", val);
-}
-
/* A range of source lines. */
struct btrace_line_range
btrace_find_line_range (CORE_ADDR pc)
{
struct btrace_line_range range;
- struct linetable_entry *lines;
- struct linetable *ltable;
+ const linetable_entry *lines;
+ const linetable *ltable;
struct symtab *symtab;
int nlines, i;
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);
if (nlines <= 0)
return btrace_mk_line_range (symtab, 0, 0);
+ struct objfile *objfile = symtab->compunit ()->objfile ();
+ unrelocated_addr unrel_pc
+ = unrelocated_addr (pc - objfile->text_section_offset ());
+
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].unrelocated_pc () == unrel_pc && lines[i].line != 0
+ && lines[i].is_stmt)
range = btrace_line_range_add (range, lines[i].line);
}
static void
btrace_print_lines (struct btrace_line_range lines, struct ui_out *uiout,
- gdb::optional<ui_out_emit_tuple> *src_and_asm_tuple,
- gdb::optional<ui_out_emit_list> *asm_list,
+ std::optional<ui_out_emit_tuple> *src_and_asm_tuple,
+ std::optional<ui_out_emit_list> *asm_list,
gdb_disassembly_flags flags)
{
print_source_lines_flags psl_flags;
flags |= DISASSEMBLY_SPECULATIVE;
- struct gdbarch *gdbarch = target_gdbarch ();
+ gdbarch *gdbarch = current_inferior ()->arch ();
btrace_line_range last_lines = btrace_mk_line_range (NULL, 0, 0);
ui_out_emit_list list_emitter (uiout, "asm_insns");
- gdb::optional<ui_out_emit_tuple> src_and_asm_tuple;
- gdb::optional<ui_out_emit_list> asm_list;
+ std::optional<ui_out_emit_tuple> src_and_asm_tuple;
+ std::optional<ui_out_emit_list> asm_list;
- gdb_pretty_print_disassembler disasm (gdbarch);
+ gdb_pretty_print_disassembler disasm (gdbarch, uiout);
for (btrace_insn_iterator it = *begin; btrace_insn_cmp (&it, end) != 0;
- btrace_insn_next (&it, 1))
+ btrace_insn_next (&it, 1))
{
const struct btrace_insn *insn;
if ((insn->flags & BTRACE_INSN_FLAG_SPECULATIVE) != 0)
dinsn.is_speculative = 1;
- disasm.pretty_print_insn (uiout, &dinsn, flags);
+ disasm.pretty_print_insn (&dinsn, flags);
}
}
}
else
{
if (size < 0)
- printf_unfiltered (_("At the start of the branch trace record.\n"));
+ gdb_printf (_("At the start of the branch trace record.\n"));
else
- printf_unfiltered (_("At the end of the branch trace record.\n"));
+ gdb_printf (_("At the end of the branch trace record.\n"));
}
btrace_set_insn_history (btinfo, &begin, &end);
begin = bfun->insn_offset;
end = begin + size - 1;
- ui_out_field_uint (uiout, "insn begin", begin);
+ uiout->field_unsigned ("insn begin", begin);
uiout->text (",");
- ui_out_field_uint (uiout, "insn end", end);
+ uiout->field_unsigned ("insn end", end);
}
/* Compute the lowest and highest source line for the instructions in BFUN
if (sym == NULL)
goto out;
- symtab = symbol_symtab (sym);
+ symtab = sym->symtab ();
for (const btrace_insn &insn : bfun->insn)
{
return;
uiout->field_string ("file",
- symtab_to_filename_for_display (symbol_symtab (sym)),
- ui_out_style_kind::FILE);
+ symtab_to_filename_for_display (sym->symtab ()),
+ file_name_style.style ());
btrace_compute_src_line_range (bfun, &begin, &end);
if (end < begin)
return;
uiout->text (":");
- uiout->field_int ("min line", begin);
+ uiout->field_signed ("min line", begin);
if (end == begin)
return;
uiout->text (",");
- uiout->field_int ("max line", end);
+ uiout->field_signed ("max line", end);
}
/* Get the name of a branch trace function. */
sym = bfun->sym;
if (sym != NULL)
- return SYMBOL_PRINT_NAME (sym);
+ return sym->print_name ();
else if (msym != NULL)
- return MSYMBOL_PRINT_NAME (msym);
+ return msym->print_name ();
else
return "??";
}
msym = bfun->msym;
/* Print the function index. */
- ui_out_field_uint (uiout, "index", bfun->number);
+ uiout->field_unsigned ("index", bfun->number);
uiout->text ("\t");
/* Indicate gaps in the trace. */
}
if (sym != NULL)
- uiout->field_string ("function", SYMBOL_PRINT_NAME (sym),
- ui_out_style_kind::FUNCTION);
+ uiout->field_string ("function", sym->print_name (),
+ function_name_style.style ());
else if (msym != NULL)
- uiout->field_string ("function", MSYMBOL_PRINT_NAME (msym),
- ui_out_style_kind::FUNCTION);
+ uiout->field_string ("function", msym->print_name (),
+ function_name_style.style ());
else if (!uiout->is_mi_like_p ())
uiout->field_string ("function", "??",
- ui_out_style_kind::FUNCTION);
+ function_name_style.style ());
if ((flags & RECORD_PRINT_INSN_RANGE) != 0)
{
else
{
if (size < 0)
- printf_unfiltered (_("At the start of the branch trace record.\n"));
+ gdb_printf (_("At the start of the branch trace record.\n"));
else
- printf_unfiltered (_("At the end of the branch trace record.\n"));
+ gdb_printf (_("At the end of the branch trace record.\n"));
}
btrace_set_call_history (btinfo, &begin, &end);
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 = proc_target->find_thread (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;
{
case TARGET_OBJECT_MEMORY:
{
- struct target_section *section;
+ const struct target_section *section;
/* We do not allow writing memory in general. */
if (writebuf != NULL)
if (section != NULL)
{
/* Check if the section we found is readonly. */
- if ((bfd_get_section_flags (section->the_bfd_section->owner,
- section->the_bfd_section)
+ if ((bfd_section_flags (section->the_bfd_section)
& SEC_READONLY) != 0)
{
/* Truncate the request to fit into this section. */
replay_memory_access = replay_memory_access_read_write;
ret = 0;
- TRY
+ try
{
ret = this->beneath ()->insert_breakpoint (gdbarch, bp_tgt);
}
- CATCH (except, RETURN_MASK_ALL)
+ catch (const gdb_exception &except)
{
replay_memory_access = old;
- throw_exception (except);
+ throw;
}
- END_CATCH
replay_memory_access = old;
return ret;
replay_memory_access = replay_memory_access_read_write;
ret = 0;
- TRY
+ try
{
ret = this->beneath ()->remove_breakpoint (gdbarch, bp_tgt, reason);
}
- CATCH (except, RETURN_MASK_ALL)
+ catch (const gdb_exception &except)
{
replay_memory_access = old;
- throw_exception (except);
+ throw;
}
- END_CATCH
replay_memory_access = old;
return ret;
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
+ = current_inferior ()->process_target ()->find_thread (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;
&& record_is_replaying (regcache->ptid ()))
error (_("Cannot write registers while replaying."));
- gdb_assert (may_write_registers != 0);
+ gdb_assert (may_write_registers);
this->beneath ()->store_registers (regcache, regno);
}
struct thread_info *tp;
/* The frame info. */
- struct frame_info *frame;
+ frame_info *frame;
/* The branch trace function segment. */
const struct btrace_function *bfun;
/* Create a new btrace frame cache. */
static struct btrace_frame_cache *
-bfcache_new (struct frame_info *frame)
+bfcache_new (frame_info_ptr frame)
{
struct btrace_frame_cache *cache;
void **slot;
cache = FRAME_OBSTACK_ZALLOC (struct btrace_frame_cache);
- cache->frame = frame;
+ cache->frame = frame.get ();
slot = htab_find_slot (bfcache, cache, INSERT);
gdb_assert (*slot == NULL);
/* Extract the branch trace function from a branch trace frame. */
static const struct btrace_function *
-btrace_get_frame_function (struct frame_info *frame)
+btrace_get_frame_function (frame_info_ptr frame)
{
const struct btrace_frame_cache *cache;
struct btrace_frame_cache pattern;
void **slot;
- pattern.frame = frame;
+ pattern.frame = frame.get ();
slot = htab_find_slot (bfcache, &pattern, NO_INSERT);
if (slot == NULL)
/* Implement stop_reason method for record_btrace_frame_unwind. */
static enum unwind_stop_reason
-record_btrace_frame_unwind_stop_reason (struct frame_info *this_frame,
+record_btrace_frame_unwind_stop_reason (frame_info_ptr this_frame,
void **this_cache)
{
const struct btrace_frame_cache *cache;
/* Implement this_id method for record_btrace_frame_unwind. */
static void
-record_btrace_frame_this_id (struct frame_info *this_frame, void **this_cache,
+record_btrace_frame_this_id (frame_info_ptr this_frame, void **this_cache,
struct frame_id *this_id)
{
const struct btrace_frame_cache *cache;
/* Implement prev_register method for record_btrace_frame_unwind. */
static struct value *
-record_btrace_frame_prev_register (struct frame_info *this_frame,
+record_btrace_frame_prev_register (frame_info_ptr this_frame,
void **this_cache,
int regnum)
{
static int
record_btrace_frame_sniffer (const struct frame_unwind *self,
- struct frame_info *this_frame,
+ frame_info_ptr this_frame,
void **this_cache)
{
const struct btrace_function *bfun;
struct btrace_frame_cache *cache;
struct thread_info *tp;
- struct frame_info *next;
+ frame_info_ptr next;
/* THIS_FRAME does not contain a reference to its thread. */
tp = inferior_thread ();
static int
record_btrace_tailcall_frame_sniffer (const struct frame_unwind *self,
- struct frame_info *this_frame,
+ frame_info_ptr this_frame,
void **this_cache)
{
const struct btrace_function *bfun, *callee;
struct btrace_frame_cache *cache;
struct btrace_call_iterator it;
- struct frame_info *next;
+ frame_info_ptr next;
struct thread_info *tinfo;
next = get_next_frame (this_frame);
}
static void
-record_btrace_frame_dealloc_cache (struct frame_info *self, void *this_cache)
+record_btrace_frame_dealloc_cache (frame_info *self, void *this_cache)
{
struct btrace_frame_cache *cache;
void **slot;
}
/* btrace recording does not store previous memory content, neither the stack
- frames content. Any unwinding would return errorneous results as the stack
+ frames content. Any unwinding would return erroneous results as the stack
contents no longer matches the changed PC value restored from history.
Therefore this unwinder reports any possibly unwound registers as
<unavailable>. */
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,
/* Return a human-readable string for FLAG. */
static const char *
-btrace_thread_flag_to_str (enum btrace_thread_flag flag)
+btrace_thread_flag_to_str (btrace_thread_flags flag)
{
switch (flag)
{
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;
- int executing;
-
/* Set current thread, which is implicitly used by
get_current_frame. */
scoped_restore_current_thread restore_thread;
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.
For the latter, EXECUTING is false and this has no effect.
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 flase. */
- executing = tp->executing;
- set_executing (inferior_ptid, false);
-
- id = null_frame_id;
- TRY
+ set EXECUTING to false. */
+ bool executing = tp->executing ();
+ set_executing (proc_target, inferior_ptid, false);
+ SCOPE_EXIT
{
- id = get_frame_id (get_current_frame ());
- }
- CATCH (except, RETURN_MASK_ALL)
- {
- /* Restore the previous execution state. */
- set_executing (inferior_ptid, executing);
-
- throw_exception (except);
- }
- END_CATCH
-
- /* Restore the previous execution state. */
- set_executing (inferior_ptid, executing);
-
- return id;
+ set_executing (proc_target, inferior_ptid, executing);
+ };
+ return get_frame_id (get_current_frame ());
}
/* Start replaying a thread. */
/* We can't start replaying without trace. */
if (btinfo->functions.empty ())
- return NULL;
+ error (_("No trace."));
/* GDB stores the current frame_id when stepping in order to detects steps
into subroutines.
Since frames are computed differently when we're replaying, we need to
recompute those stored frames and fix them up so we can still detect
subroutines after we started replaying. */
- TRY
+ try
{
struct frame_id frame_id;
int upd_step_frame_id, upd_step_stack_frame_id;
frame_id = get_thread_current_frame_id (tp);
/* Check if we need to update any stepping-related frame id's. */
- upd_step_frame_id = frame_id_eq (frame_id,
- tp->control.step_frame_id);
- upd_step_stack_frame_id = frame_id_eq (frame_id,
- tp->control.step_stack_frame_id);
+ upd_step_frame_id = (frame_id == tp->control.step_frame_id);
+ upd_step_stack_frame_id = (frame_id == tp->control.step_stack_frame_id);
/* We start replaying at the end of the branch trace. This corresponds
to the current instruction. */
if (upd_step_stack_frame_id)
tp->control.step_stack_frame_id = frame_id;
}
- CATCH (except, RETURN_MASK_ALL)
+ catch (const gdb_exception &except)
{
xfree (btinfo->replay);
btinfo->replay = NULL;
registers_changed_thread (tp);
- throw_exception (except);
+ throw;
}
- END_CATCH
return replay;
}
{
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");
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);
}
/* Async support. */
if (target_can_async_p ())
{
- target_async (1);
+ target_async (true);
mark_async_event_handler (record_btrace_async_inferior_event_handler);
}
}
-/* 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
record_btrace_cancel_resume (struct thread_info *tp)
{
- enum btrace_thread_flag flags;
+ btrace_thread_flags flags;
flags = tp->btrace.flags & (BTHR_MOVE | BTHR_STOP);
if (flags == 0)
DEBUG ("cancel resume thread %s (%s): %x (%s)",
print_thread_id (tp),
- target_pid_to_str (tp->ptid).c_str (), flags,
+ 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;
}
if (insn == NULL)
return 0;
- return record_check_stopped_by_breakpoint (tp->inf->aspace, insn->pc,
+ return record_check_stopped_by_breakpoint (tp->inf->aspace.get (), insn->pc,
&btinfo->stop_reason);
}
{
struct btrace_thread_info *btinfo;
struct target_waitstatus status;
- enum btrace_thread_flag flags;
+ btrace_thread_flags flags;
btinfo = &tp->btrace;
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,
+ tp->ptid.to_string ().c_str (), flags.raw (),
btrace_thread_flag_to_str (flags));
/* We can't step without an execution history. */
switch (flags)
{
default:
- internal_error (__FILE__, __LINE__, _("invalid stepping type."));
+ internal_error (_("invalid stepping type."));
case BTHR_STOP:
return btrace_step_stopped_on_request ();
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;
ptid_t
record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
- int options)
+ target_wait_flags options)
{
std::vector<thread_info *> moving;
std::vector<thread_info *> no_history;
- DEBUG ("wait %s (0x%x)", target_pid_to_str (ptid).c_str (), options);
+ /* 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. */
if ((::execution_direction != EXEC_REVERSE)
}
/* 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);
{
*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++;
/* 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);
}
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)
}
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;
/* Start anew from the new replay position. */
record_btrace_clear_histories (btinfo);
- inferior_thread ()->suspend.stop_pc
- = regcache_read_pc (get_current_regcache ());
+ tp->set_stop_pc (regcache_read_pc (get_thread_regcache (tp)));
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
}
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);
}
record_btrace_conf.format = BTRACE_FORMAT_BTS;
- TRY
+ try
{
execute_command ("target record-btrace", from_tty);
}
- CATCH (exception, RETURN_MASK_ALL)
+ catch (const gdb_exception &exception)
{
record_btrace_conf.format = BTRACE_FORMAT_NONE;
- throw_exception (exception);
+ throw;
}
- END_CATCH
}
/* Start recording in Intel Processor Trace format. */
record_btrace_conf.format = BTRACE_FORMAT_PT;
- TRY
+ try
{
execute_command ("target record-btrace", from_tty);
}
- CATCH (exception, RETURN_MASK_ALL)
+ catch (const gdb_exception &exception)
{
record_btrace_conf.format = BTRACE_FORMAT_NONE;
- throw_exception (exception);
+ throw;
}
- END_CATCH
}
/* Alias for "target record". */
record_btrace_conf.format = BTRACE_FORMAT_PT;
- TRY
+ try
{
execute_command ("target record-btrace", from_tty);
}
- CATCH (exception, RETURN_MASK_ALL)
+ catch (const gdb_exception_error &exception)
{
record_btrace_conf.format = BTRACE_FORMAT_BTS;
- TRY
+ try
{
execute_command ("target record-btrace", from_tty);
}
- CATCH (ex, RETURN_MASK_ALL)
+ catch (const gdb_exception &ex)
{
record_btrace_conf.format = BTRACE_FORMAT_NONE;
- throw_exception (ex);
+ throw;
}
- END_CATCH
}
- END_CATCH
-}
-
-/* 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. */
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"),
- replay_memory_access);
+ gdb_printf (file, _("Replay memory access is %s.\n"),
+ replay_memory_access);
}
/* The "set record btrace cpu none" command. */
switch (record_btrace_cpu_state)
{
case CS_AUTO:
- printf_unfiltered (_("btrace cpu is 'auto'.\n"));
+ gdb_printf (_("btrace cpu is 'auto'.\n"));
return;
case CS_NONE:
- printf_unfiltered (_("btrace cpu is 'none'.\n"));
+ gdb_printf (_("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);
+ gdb_printf (_("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);
+ gdb_printf (_("btrace cpu is 'intel: %u/%u/%u'.\n"),
+ record_btrace_cpu.family,
+ record_btrace_cpu.model,
+ record_btrace_cpu.stepping);
return;
}
}
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
struct cmd_list_element *c,
const char *value)
{
- fprintf_filtered (file, _("The record/replay bts buffer size is %s.\n"),
- value);
+ gdb_printf (file, _("The record/replay bts buffer size is %s.\n"),
+ value);
}
/* The "record pt buffer-size" show value function. */
struct cmd_list_element *c,
const char *value)
{
- fprintf_filtered (file, _("The record/replay pt buffer size is %s.\n"),
- value);
+ gdb_printf (file, _("The record/replay pt buffer size is %s.\n"),
+ value);
}
/* 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 ", 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);
-
- add_prefix_cmd ("btrace", class_support, cmd_set_record_btrace,
- _("Set record options"), &set_record_btrace_cmdlist,
- "set record btrace ", 0, &set_record_cmdlist);
+ &record_btrace_cmdlist);
+ add_alias_cmd ("pt", record_btrace_pt_cmd, class_obscure, 1, &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_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_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_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_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_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_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,