/* Select target systems and architectures at runtime for GDB.
- Copyright (C) 1990-2020 Free Software Foundation, Inc.
+ Copyright (C) 1990-2023 Free Software Foundation, Inc.
Contributed by Cygnus Support.
#include "symtab.h"
#include "inferior.h"
#include "infrun.h"
+#include "observable.h"
#include "bfd.h"
#include "symfile.h"
#include "objfiles.h"
#include "exec.h"
#include "inline-frame.h"
#include "tracepoint.h"
-#include "gdb/fileio.h"
+#include "gdbsupport/fileio.h"
#include "gdbsupport/agent.h"
#include "auxv.h"
#include "target-debug.h"
#include <unordered_map>
#include "target-connection.h"
#include "valprint.h"
+#include "cli/cli-decode.h"
static void generic_tls_error (void) ATTRIBUTE_NORETURN;
static void default_rcmd (struct target_ops *, const char *, struct ui_file *);
static ptid_t default_get_ada_task_ptid (struct target_ops *self,
- long lwp, long tid);
+ long lwp, ULONGEST tid);
static void default_mourn_inferior (struct target_ops *self);
static struct target_ops *the_debug_target;
-/* Top of target stack. */
-/* The target structure we are currently using to talk to a process
- or file or whatever "inferior" we have. */
+/* Command list for target. */
+
+static struct cmd_list_element *targetlist = NULL;
+
+/* True if we should trust readonly sections from the
+ executable when reading memory. */
+
+static bool trust_readonly = false;
+
+/* Nonzero if we should show true memory content including
+ memory breakpoint inserted by gdb. */
+
+static int show_memory_breakpoints = 0;
+
+/* These globals control whether GDB attempts to perform these
+ operations; they are useful for targets that need to prevent
+ inadvertent disruption, such as in non-stop mode. */
+
+bool may_write_registers = true;
+
+bool may_write_memory = true;
+
+bool may_insert_breakpoints = true;
+
+bool may_insert_tracepoints = true;
+
+bool may_insert_fast_tracepoints = true;
+
+bool may_stop = true;
+
+/* Non-zero if we want to see trace of target level stuff. */
+
+static unsigned int targetdebug = 0;
+
+static void
+set_targetdebug (const char *args, int from_tty, struct cmd_list_element *c)
+{
+ if (targetdebug)
+ current_inferior ()->push_target (the_debug_target);
+ else
+ current_inferior ()->unpush_target (the_debug_target);
+}
+
+static void
+show_targetdebug (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ gdb_printf (file, _("Target debugging is %s.\n"), value);
+}
+
+int
+target_has_memory ()
+{
+ for (target_ops *t = current_inferior ()->top_target ();
+ t != NULL;
+ t = t->beneath ())
+ if (t->has_memory ())
+ return 1;
+
+ return 0;
+}
+
+int
+target_has_stack ()
+{
+ for (target_ops *t = current_inferior ()->top_target ();
+ t != NULL;
+ t = t->beneath ())
+ if (t->has_stack ())
+ return 1;
+
+ return 0;
+}
+
+int
+target_has_registers ()
+{
+ for (target_ops *t = current_inferior ()->top_target ();
+ t != NULL;
+ t = t->beneath ())
+ if (t->has_registers ())
+ return 1;
+
+ return 0;
+}
+
+bool
+target_has_execution (inferior *inf)
+{
+ if (inf == nullptr)
+ inf = current_inferior ();
+
+ for (target_ops *t = inf->top_target ();
+ t != nullptr;
+ t = inf->find_target_beneath (t))
+ if (t->has_execution (inf))
+ return true;
+
+ return false;
+}
+
+const char *
+target_shortname ()
+{
+ return current_inferior ()->top_target ()->shortname ();
+}
+
+/* See target.h. */
+
+bool
+target_attach_no_wait ()
+{
+ return current_inferior ()->top_target ()->attach_no_wait ();
+}
+
+/* See target.h. */
+
+void
+target_post_attach (int pid)
+{
+ return current_inferior ()->top_target ()->post_attach (pid);
+}
+
+/* See target.h. */
+
+void
+target_prepare_to_store (regcache *regcache)
+{
+ return current_inferior ()->top_target ()->prepare_to_store (regcache);
+}
+
+/* See target.h. */
+
+bool
+target_supports_enable_disable_tracepoint ()
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->supports_enable_disable_tracepoint ();
+}
+
+bool
+target_supports_string_tracing ()
+{
+ return current_inferior ()->top_target ()->supports_string_tracing ();
+}
+
+/* See target.h. */
+
+bool
+target_supports_evaluation_of_breakpoint_conditions ()
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->supports_evaluation_of_breakpoint_conditions ();
+}
+
+/* See target.h. */
+
+bool
+target_supports_dumpcore ()
+{
+ return current_inferior ()->top_target ()->supports_dumpcore ();
+}
+
+/* See target.h. */
+
+void
+target_dumpcore (const char *filename)
+{
+ return current_inferior ()->top_target ()->dumpcore (filename);
+}
+
+/* See target.h. */
+
+bool
+target_can_run_breakpoint_commands ()
+{
+ return current_inferior ()->top_target ()->can_run_breakpoint_commands ();
+}
+
+/* See target.h. */
+
+void
+target_files_info ()
+{
+ return current_inferior ()->top_target ()->files_info ();
+}
+
+/* See target.h. */
+
+int
+target_insert_fork_catchpoint (int pid)
+{
+ return current_inferior ()->top_target ()->insert_fork_catchpoint (pid);
+}
+
+/* See target.h. */
+
+int
+target_remove_fork_catchpoint (int pid)
+{
+ return current_inferior ()->top_target ()->remove_fork_catchpoint (pid);
+}
+
+/* See target.h. */
+
+int
+target_insert_vfork_catchpoint (int pid)
+{
+ return current_inferior ()->top_target ()->insert_vfork_catchpoint (pid);
+}
+
+/* See target.h. */
+
+int
+target_remove_vfork_catchpoint (int pid)
+{
+ return current_inferior ()->top_target ()->remove_vfork_catchpoint (pid);
+}
+
+/* See target.h. */
+
+int
+target_insert_exec_catchpoint (int pid)
+{
+ return current_inferior ()->top_target ()->insert_exec_catchpoint (pid);
+}
+
+/* See target.h. */
+
+int
+target_remove_exec_catchpoint (int pid)
+{
+ return current_inferior ()->top_target ()->remove_exec_catchpoint (pid);
+}
+
+/* See target.h. */
+
+int
+target_set_syscall_catchpoint (int pid, bool needed, int any_count,
+ gdb::array_view<const int> syscall_counts)
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->set_syscall_catchpoint (pid, needed, any_count,
+ syscall_counts);
+}
+
+/* See target.h. */
+
+void
+target_rcmd (const char *command, struct ui_file *outbuf)
+{
+ return current_inferior ()->top_target ()->rcmd (command, outbuf);
+}
+
+/* See target.h. */
+
+bool
+target_can_lock_scheduler ()
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return (target->get_thread_control_capabilities ()& tc_schedlock) != 0;
+}
+
+/* See target.h. */
+
+bool
+target_can_async_p ()
+{
+ return target_can_async_p (current_inferior ()->top_target ());
+}
+
+/* See target.h. */
+
+bool
+target_can_async_p (struct target_ops *target)
+{
+ if (!target_async_permitted)
+ return false;
+ return target->can_async_p ();
+}
+
+/* See target.h. */
+
+bool
+target_is_async_p ()
+{
+ bool result = current_inferior ()->top_target ()->is_async_p ();
+ gdb_assert (target_async_permitted || !result);
+ return result;
+}
+
+exec_direction_kind
+target_execution_direction ()
+{
+ return current_inferior ()->top_target ()->execution_direction ();
+}
+
+/* See target.h. */
+
+const char *
+target_extra_thread_info (thread_info *tp)
+{
+ return current_inferior ()->top_target ()->extra_thread_info (tp);
+}
+
+/* See target.h. */
+
+const char *
+target_pid_to_exec_file (int pid)
+{
+ return current_inferior ()->top_target ()->pid_to_exec_file (pid);
+}
+
+/* See target.h. */
+
+gdbarch *
+target_thread_architecture (ptid_t ptid)
+{
+ return current_inferior ()->top_target ()->thread_architecture (ptid);
+}
+
+/* See target.h. */
+
+int
+target_find_memory_regions (find_memory_region_ftype func, void *data)
+{
+ return current_inferior ()->top_target ()->find_memory_regions (func, data);
+}
+
+/* See target.h. */
+
+gdb::unique_xmalloc_ptr<char>
+target_make_corefile_notes (bfd *bfd, int *size_p)
+{
+ return current_inferior ()->top_target ()->make_corefile_notes (bfd, size_p);
+}
+
+gdb_byte *
+target_get_bookmark (const char *args, int from_tty)
+{
+ return current_inferior ()->top_target ()->get_bookmark (args, from_tty);
+}
+
+void
+target_goto_bookmark (const gdb_byte *arg, int from_tty)
+{
+ return current_inferior ()->top_target ()->goto_bookmark (arg, from_tty);
+}
+
+/* See target.h. */
+
+bool
+target_stopped_by_watchpoint ()
+{
+ return current_inferior ()->top_target ()->stopped_by_watchpoint ();
+}
+
+/* See target.h. */
+
+bool
+target_stopped_by_sw_breakpoint ()
+{
+ return current_inferior ()->top_target ()->stopped_by_sw_breakpoint ();
+}
+
+bool
+target_supports_stopped_by_sw_breakpoint ()
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->supports_stopped_by_sw_breakpoint ();
+}
+
+bool
+target_stopped_by_hw_breakpoint ()
+{
+ return current_inferior ()->top_target ()->stopped_by_hw_breakpoint ();
+}
+
+bool
+target_supports_stopped_by_hw_breakpoint ()
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->supports_stopped_by_hw_breakpoint ();
+}
+
+/* See target.h. */
+
+bool
+target_have_steppable_watchpoint ()
+{
+ return current_inferior ()->top_target ()->have_steppable_watchpoint ();
+}
+
+/* See target.h. */
+
+int
+target_can_use_hardware_watchpoint (bptype type, int cnt, int othertype)
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->can_use_hw_breakpoint (type, cnt, othertype);
+}
+
+/* See target.h. */
+
+int
+target_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->region_ok_for_hw_watchpoint (addr, len);
+}
+
+
+int
+target_can_do_single_step ()
+{
+ return current_inferior ()->top_target ()->can_do_single_step ();
+}
+
+/* See target.h. */
+
+int
+target_insert_watchpoint (CORE_ADDR addr, int len, target_hw_bp_type type,
+ expression *cond)
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->insert_watchpoint (addr, len, type, cond);
+}
+
+/* See target.h. */
+
+int
+target_remove_watchpoint (CORE_ADDR addr, int len, target_hw_bp_type type,
+ expression *cond)
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->remove_watchpoint (addr, len, type, cond);
+}
+
+/* See target.h. */
+
+int
+target_insert_hw_breakpoint (gdbarch *gdbarch, bp_target_info *bp_tgt)
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->insert_hw_breakpoint (gdbarch, bp_tgt);
+}
+
+/* See target.h. */
+
+int
+target_remove_hw_breakpoint (gdbarch *gdbarch, bp_target_info *bp_tgt)
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->remove_hw_breakpoint (gdbarch, bp_tgt);
+}
+
+/* See target.h. */
+
+bool
+target_can_accel_watchpoint_condition (CORE_ADDR addr, int len, int type,
+ expression *cond)
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->can_accel_watchpoint_condition (addr, len, type, cond);
+}
+
+/* See target.h. */
+
+bool
+target_can_execute_reverse ()
+{
+ return current_inferior ()->top_target ()->can_execute_reverse ();
+}
+
+ptid_t
+target_get_ada_task_ptid (long lwp, ULONGEST tid)
+{
+ return current_inferior ()->top_target ()->get_ada_task_ptid (lwp, tid);
+}
+
+bool
+target_filesystem_is_local ()
+{
+ return current_inferior ()->top_target ()->filesystem_is_local ();
+}
+
+void
+target_trace_init ()
+{
+ return current_inferior ()->top_target ()->trace_init ();
+}
+
+void
+target_download_tracepoint (bp_location *location)
+{
+ return current_inferior ()->top_target ()->download_tracepoint (location);
+}
+
+bool
+target_can_download_tracepoint ()
+{
+ return current_inferior ()->top_target ()->can_download_tracepoint ();
+}
+
+void
+target_download_trace_state_variable (const trace_state_variable &tsv)
+{
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->download_trace_state_variable (tsv);
+}
+
+void
+target_enable_tracepoint (bp_location *loc)
+{
+ return current_inferior ()->top_target ()->enable_tracepoint (loc);
+}
+
+void
+target_disable_tracepoint (bp_location *loc)
+{
+ return current_inferior ()->top_target ()->disable_tracepoint (loc);
+}
+
+void
+target_trace_start ()
+{
+ return current_inferior ()->top_target ()->trace_start ();
+}
+
+void
+target_trace_set_readonly_regions ()
+{
+ return current_inferior ()->top_target ()->trace_set_readonly_regions ();
+}
+
+int
+target_get_trace_status (trace_status *ts)
+{
+ return current_inferior ()->top_target ()->get_trace_status (ts);
+}
-target_ops *
-current_top_target ()
+void
+target_get_tracepoint_status (breakpoint *tp, uploaded_tp *utp)
{
- return current_inferior ()->top_target ();
+ return current_inferior ()->top_target ()->get_tracepoint_status (tp, utp);
}
-/* Command list for target. */
+void
+target_trace_stop ()
+{
+ return current_inferior ()->top_target ()->trace_stop ();
+}
-static struct cmd_list_element *targetlist = NULL;
+int
+target_trace_find (trace_find_type type, int num,
+ CORE_ADDR addr1, CORE_ADDR addr2, int *tpp)
+{
+ target_ops *target = current_inferior ()->top_target ();
-/* True if we should trust readonly sections from the
- executable when reading memory. */
+ return target->trace_find (type, num, addr1, addr2, tpp);
+}
-static bool trust_readonly = false;
+bool
+target_get_trace_state_variable_value (int tsv, LONGEST *val)
+{
+ target_ops *target = current_inferior ()->top_target ();
-/* Nonzero if we should show true memory content including
- memory breakpoint inserted by gdb. */
+ return target->get_trace_state_variable_value (tsv, val);
+}
-static int show_memory_breakpoints = 0;
+int
+target_save_trace_data (const char *filename)
+{
+ return current_inferior ()->top_target ()->save_trace_data (filename);
+}
-/* These globals control whether GDB attempts to perform these
- operations; they are useful for targets that need to prevent
- inadvertent disruption, such as in non-stop mode. */
+int
+target_upload_tracepoints (uploaded_tp **utpp)
+{
+ return current_inferior ()->top_target ()->upload_tracepoints (utpp);
+}
-bool may_write_registers = true;
+int
+target_upload_trace_state_variables (uploaded_tsv **utsvp)
+{
+ target_ops *target = current_inferior ()->top_target ();
-bool may_write_memory = true;
+ return target->upload_trace_state_variables (utsvp);
+}
-bool may_insert_breakpoints = true;
+LONGEST
+target_get_raw_trace_data (gdb_byte *buf, ULONGEST offset, LONGEST len)
+{
+ target_ops *target = current_inferior ()->top_target ();
-bool may_insert_tracepoints = true;
+ return target->get_raw_trace_data (buf, offset, len);
+}
-bool may_insert_fast_tracepoints = true;
+int
+target_get_min_fast_tracepoint_insn_len ()
+{
+ target_ops *target = current_inferior ()->top_target ();
-bool may_stop = true;
+ return target->get_min_fast_tracepoint_insn_len ();
+}
-/* Non-zero if we want to see trace of target level stuff. */
+void
+target_set_disconnected_tracing (int val)
+{
+ return current_inferior ()->top_target ()->set_disconnected_tracing (val);
+}
-static unsigned int targetdebug = 0;
+void
+target_set_circular_trace_buffer (int val)
+{
+ return current_inferior ()->top_target ()->set_circular_trace_buffer (val);
+}
-static void
-set_targetdebug (const char *args, int from_tty, struct cmd_list_element *c)
+void
+target_set_trace_buffer_size (LONGEST val)
{
- if (targetdebug)
- push_target (the_debug_target);
- else
- unpush_target (the_debug_target);
+ return current_inferior ()->top_target ()->set_trace_buffer_size (val);
}
-static void
-show_targetdebug (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
+bool
+target_set_trace_notes (const char *user, const char *notes,
+ const char *stopnotes)
{
- fprintf_filtered (file, _("Target debugging is %s.\n"), value);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->set_trace_notes (user, notes, stopnotes);
}
-int
-target_has_memory ()
+bool
+target_get_tib_address (ptid_t ptid, CORE_ADDR *addr)
{
- for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
- if (t->has_memory ())
- return 1;
+ return current_inferior ()->top_target ()->get_tib_address (ptid, addr);
+}
- return 0;
+void
+target_set_permissions ()
+{
+ return current_inferior ()->top_target ()->set_permissions ();
}
-int
-target_has_stack ()
+bool
+target_static_tracepoint_marker_at (CORE_ADDR addr,
+ static_tracepoint_marker *marker)
{
- for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
- if (t->has_stack ())
- return 1;
+ target_ops *target = current_inferior ()->top_target ();
- return 0;
+ return target->static_tracepoint_marker_at (addr, marker);
}
-int
-target_has_registers ()
+std::vector<static_tracepoint_marker>
+target_static_tracepoint_markers_by_strid (const char *marker_id)
{
- for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
- if (t->has_registers ())
- return 1;
+ target_ops *target = current_inferior ()->top_target ();
- return 0;
+ return target->static_tracepoint_markers_by_strid (marker_id);
+}
+
+traceframe_info_up
+target_traceframe_info ()
+{
+ return current_inferior ()->top_target ()->traceframe_info ();
}
bool
-target_has_execution (inferior *inf)
+target_use_agent (bool use)
{
- if (inf == nullptr)
- inf = current_inferior ();
+ return current_inferior ()->top_target ()->use_agent (use);
+}
- for (target_ops *t = inf->top_target ();
- t != nullptr;
- t = inf->find_target_beneath (t))
- if (t->has_execution (inf))
- return true;
+bool
+target_can_use_agent ()
+{
+ return current_inferior ()->top_target ()->can_use_agent ();
+}
- return false;
+bool
+target_augmented_libraries_svr4_read ()
+{
+ return current_inferior ()->top_target ()->augmented_libraries_svr4_read ();
+}
+
+bool
+target_supports_memory_tagging ()
+{
+ return current_inferior ()->top_target ()->supports_memory_tagging ();
+}
+
+bool
+target_fetch_memtags (CORE_ADDR address, size_t len, gdb::byte_vector &tags,
+ int type)
+{
+ return current_inferior ()->top_target ()->fetch_memtags (address, len, tags, type);
+}
+
+bool
+target_store_memtags (CORE_ADDR address, size_t len,
+ const gdb::byte_vector &tags, int type)
+{
+ return current_inferior ()->top_target ()->store_memtags (address, len, tags, type);
+}
+
+void
+target_log_command (const char *p)
+{
+ return current_inferior ()->top_target ()->log_command (p);
}
/* This is used to implement the various target commands. */
static void
open_target (const char *args, int from_tty, struct cmd_list_element *command)
{
- auto *ti = static_cast<target_info *> (get_cmd_context (command));
+ auto *ti = static_cast<target_info *> (command->context ());
target_open_ftype *func = target_factories[ti];
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog, "-> %s->open (...)\n",
- ti->shortname);
+ gdb_printf (gdb_stdlog, "-> %s->open (...)\n",
+ ti->shortname);
func (args, from_tty);
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog, "<- %s->open (%s, %d)\n",
- ti->shortname, args, from_tty);
+ gdb_printf (gdb_stdlog, "<- %s->open (%s, %d)\n",
+ ti->shortname, args, from_tty);
}
/* See target.h. */
auto &func_slot = target_factories[&t];
if (func_slot != nullptr)
- internal_error (__FILE__, __LINE__,
- _("target already added (\"%s\")."), t.shortname);
+ internal_error (_("target already added (\"%s\")."), t.shortname);
func_slot = func;
if (targetlist == NULL)
Remaining arguments are interpreted by the target protocol. For more\n\
information on the arguments for a particular protocol, type\n\
`help target ' followed by the protocol name."),
- &targetlist, "target ", 0, &cmdlist);
+ &targetlist, 0, &cmdlist);
c = add_cmd (t.shortname, no_class, t.doc, &targetlist);
- set_cmd_context (c, (void *) &t);
- set_cmd_sfunc (c, open_target);
+ c->set_context ((void *) &t);
+ c->func = open_target;
if (completer != NULL)
set_cmd_completer (c, completer);
}
add_deprecated_target_alias (const target_info &tinfo, const char *alias)
{
struct cmd_list_element *c;
- char *alt;
/* If we use add_alias_cmd, here, we do not get the deprecated warning,
see PR cli/15104. */
c = add_cmd (alias, no_class, tinfo.doc, &targetlist);
- set_cmd_sfunc (c, open_target);
- set_cmd_context (c, (void *) &tinfo);
- alt = xstrprintf ("target %s", tinfo.shortname);
- deprecate_cmd (c, alt);
+ c->func = open_target;
+ c->set_context ((void *) &tinfo);
+ gdb::unique_xmalloc_ptr<char> alt
+ = xstrprintf ("target %s", tinfo.shortname);
+ deprecate_cmd (c, alt.release ());
}
/* Stub functions */
void
target_kill (void)
{
- current_top_target ()->kill ();
+
+ /* If the commit_resume_state of the to-be-killed-inferior's process stratum
+ is true, and this inferior is the last live inferior with resumed threads
+ of that target, then we want to leave commit_resume_state to false, as the
+ target won't have any resumed threads anymore. We achieve this with
+ this scoped_disable_commit_resumed. On construction, it will set the flag
+ to false. On destruction, it will only set it to true if there are resumed
+ threads left. */
+ scoped_disable_commit_resumed disable ("killing");
+ current_inferior ()->top_target ()->kill ();
}
void
target_load (const char *arg, int from_tty)
{
target_dcache_invalidate ();
- current_top_target ()->load (arg, from_tty);
+ current_inferior ()->top_target ()->load (arg, from_tty);
}
/* Define it. */
void
target_terminal::init (void)
{
- current_top_target ()->terminal_init ();
+ current_inferior ()->top_target ()->terminal_init ();
m_terminal_state = target_terminal_state::is_ours;
}
if (inf->terminal_state != target_terminal_state::is_inferior)
{
- current_top_target ()->terminal_inferior ();
+ current_inferior ()->top_target ()->terminal_inferior ();
inf->terminal_state = target_terminal_state::is_inferior;
}
if (inf->terminal_state == target_terminal_state::is_ours_for_output)
{
set_current_inferior (inf);
- current_top_target ()->terminal_inferior ();
+ current_inferior ()->top_target ()->terminal_inferior ();
inf->terminal_state = target_terminal_state::is_inferior;
}
}
if (inf->terminal_state == target_terminal_state::is_inferior)
{
set_current_inferior (inf);
- current_top_target ()->terminal_save_inferior ();
+ current_inferior ()->top_target ()->terminal_save_inferior ();
}
}
{
set_current_inferior (inf);
if (desired_state == target_terminal_state::is_ours)
- current_top_target ()->terminal_ours ();
+ current_inferior ()->top_target ()->terminal_ours ();
else if (desired_state == target_terminal_state::is_ours_for_output)
- current_top_target ()->terminal_ours_for_output ();
+ current_inferior ()->top_target ()->terminal_ours_for_output ();
else
gdb_assert_not_reached ("unhandled desired state");
inf->terminal_state = desired_state;
void
target_terminal::info (const char *arg, int from_tty)
{
- current_top_target ()->terminal_info (arg, from_tty);
+ current_inferior ()->top_target ()->terminal_info (arg, from_tty);
}
/* See target.h. */
tcomplain (void)
{
error (_("You can't do that when your target is `%s'"),
- current_top_target ()->shortname ());
+ current_inferior ()->top_target ()->shortname ());
}
void
static void
default_terminal_info (struct target_ops *self, const char *args, int from_tty)
{
- printf_unfiltered (_("No saved terminal information.\n"));
+ gdb_printf (_("No saved terminal information.\n"));
}
/* A default implementation for the to_get_ada_task_ptid target method.
inferior_ptid. */
static ptid_t
-default_get_ada_task_ptid (struct target_ops *self, long lwp, long tid)
+default_get_ada_task_ptid (struct target_ops *self, long lwp, ULONGEST tid)
{
return ptid_t (inferior_ptid.pid (), lwp, tid);
}
/* See target.h. */
void
-decref_target (target_ops *t)
+target_ops_ref_policy::decref (target_ops *t)
{
t->decref ();
if (t->refcount () == 0)
void
target_stack::push (target_ops *t)
{
- t->incref ();
+ /* We must create a new reference first. It is possible that T is
+ already pushed on this target stack, in which case we will first
+ unpush it below, before re-pushing it. If we don't increment the
+ reference count now, then when we unpush it, we might end up deleting
+ T, which is not good. */
+ auto ref = target_ops_ref::new_reference (t);
strata stratum = t->stratum ();
- if (stratum == process_stratum)
- connection_list_add (as_process_stratum_target (t));
-
/* If there's already a target at this stratum, remove it. */
- if (m_stack[stratum] != NULL)
- unpush (m_stack[stratum]);
+ if (m_stack[stratum].get () != nullptr)
+ unpush (m_stack[stratum].get ());
/* Now add the new one. */
- m_stack[stratum] = t;
+ m_stack[stratum] = std::move (ref);
if (m_top < stratum)
m_top = stratum;
-}
-
-/* See target.h. */
-
-void
-push_target (struct target_ops *t)
-{
- current_inferior ()->push_target (t);
-}
-
-/* See target.h. */
-void
-push_target (target_ops_up &&t)
-{
- current_inferior ()->push_target (t.get ());
- t.release ();
-}
-
-/* See target.h. */
-
-int
-unpush_target (struct target_ops *t)
-{
- return current_inferior ()->unpush_target (t);
+ if (stratum == process_stratum)
+ connection_list_add (as_process_stratum_target (t));
}
/* See target.h. */
strata stratum = t->stratum ();
if (stratum == dummy_stratum)
- internal_error (__FILE__, __LINE__,
- _("Attempt to unpush the dummy target"));
+ internal_error (_("Attempt to unpush the dummy target"));
/* Look for the specified target. Note that a target can only occur
once in the target stack. */
return false;
}
- /* Unchain the target. */
- m_stack[stratum] = NULL;
-
if (m_top == stratum)
- m_top = t->beneath ()->stratum ();
-
- /* Finally close the target, if there are no inferiors
- referencing this target still. Note we do this after unchaining,
- so any target method calls from within the target_close
- implementation don't end up in T anymore. Do leave the target
- open if we have are other inferiors referencing this target
- still. */
- decref_target (t);
-
- return true;
-}
-
-/* Unpush TARGET and assert that it worked. */
+ m_top = this->find_beneath (t)->stratum ();
-static void
-unpush_target_and_assert (struct target_ops *target)
-{
- if (!unpush_target (target))
- {
- fprintf_unfiltered (gdb_stderr,
- "pop_all_targets couldn't find target %s\n",
- target->shortname ());
- internal_error (__FILE__, __LINE__,
- _("failed internal consistency check"));
- }
-}
-
-void
-pop_all_targets_above (enum strata above_stratum)
-{
- while ((int) (current_top_target ()->stratum ()) > (int) above_stratum)
- unpush_target_and_assert (current_top_target ());
-}
+ /* Move the target reference off the target stack, this sets the pointer
+ held in m_stack to nullptr, and places the reference in ref. When
+ ref goes out of scope its reference count will be decremented, which
+ might cause the target to close.
-/* See target.h. */
+ We have to do it this way, and not just set the value in m_stack to
+ nullptr directly, because doing so would decrement the reference
+ count first, which might close the target, and closing the target
+ does a check that the target is not on any inferiors target_stack. */
+ auto ref = std::move (m_stack[stratum]);
-void
-pop_all_targets_at_and_above (enum strata stratum)
-{
- while ((int) (current_top_target ()->stratum ()) >= (int) stratum)
- unpush_target_and_assert (current_top_target ());
+ return true;
}
void
-pop_all_targets (void)
-{
- pop_all_targets_above (dummy_stratum);
-}
-
-/* Return true if T is now pushed in the current inferior's target
- stack. Return false otherwise. */
-
-bool
-target_is_pushed (target_ops *t)
+target_unpusher::operator() (struct target_ops *ops) const
{
- return current_inferior ()->target_is_pushed (t);
+ current_inferior ()->unpush_target (ops);
}
/* Default implementation of to_get_thread_local_address. */
target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset)
{
volatile CORE_ADDR addr = 0;
- struct target_ops *target = current_top_target ();
+ struct target_ops *target = current_inferior ()->top_target ();
struct gdbarch *gdbarch = target_gdbarch ();
+ /* If OBJFILE is a separate debug object file, look for the
+ original object file. */
+ if (objfile->separate_debug_objfile_backlink != NULL)
+ objfile = objfile->separate_debug_objfile_backlink;
+
if (gdbarch_fetch_tls_load_module_address_p (gdbarch))
{
ptid_t ptid = inferior_ptid;
/* Fetch the load module address for this objfile. */
lm_addr = gdbarch_fetch_tls_load_module_address (gdbarch,
- objfile);
+ objfile);
if (gdbarch_get_thread_local_address_p (gdbarch))
addr = gdbarch_get_thread_local_address (gdbarch, ptid, lm_addr,
addr = target->get_thread_local_address (ptid, lm_addr, offset);
}
/* If an error occurred, print TLS related messages here. Otherwise,
- throw the error to some higher catcher. */
+ throw the error to some higher catcher. */
catch (const gdb_exception &ex)
{
int objfile_is_library = (objfile->flags & OBJF_SHARED);
case TLS_LOAD_MODULE_NOT_FOUND_ERROR:
if (objfile_is_library)
error (_("Cannot find shared library `%s' in dynamic"
- " linker's load module list"), objfile_name (objfile));
+ " linker's load module list"), objfile_name (objfile));
else
error (_("Cannot find executable file `%s' in dynamic"
- " linker's load module list"), objfile_name (objfile));
+ " linker's load module list"), objfile_name (objfile));
break;
case TLS_NOT_ALLOCATED_YET_ERROR:
if (objfile_is_library)
error (_("The inferior has not yet allocated storage for"
- " thread-local variables in\n"
- "the shared library `%s'\n"
- "for %s"),
+ " thread-local variables in\n"
+ "the shared library `%s'\n"
+ "for %s"),
objfile_name (objfile),
target_pid_to_str (ptid).c_str ());
else
error (_("The inferior has not yet allocated storage for"
- " thread-local variables in\n"
- "the executable `%s'\n"
- "for %s"),
+ " thread-local variables in\n"
+ "the executable `%s'\n"
+ "for %s"),
objfile_name (objfile),
target_pid_to_str (ptid).c_str ());
break;
case TLS_GENERIC_ERROR:
if (objfile_is_library)
error (_("Cannot find thread-local storage for %s, "
- "shared library %s:\n%s"),
+ "shared library %s:\n%s"),
target_pid_to_str (ptid).c_str (),
objfile_name (objfile), ex.what ());
else
error (_("Cannot find thread-local storage for %s, "
- "executable file %s:\n%s"),
+ "executable file %s:\n%s"),
target_pid_to_str (ptid).c_str (),
objfile_name (objfile), ex.what ());
break;
};
-/* See target.h. */
-
-gdb::unique_xmalloc_ptr<char>
-target_read_string (CORE_ADDR memaddr, int len, int *bytes_read)
-{
- gdb::unique_xmalloc_ptr<gdb_byte> buffer;
-
- int ignore;
- if (bytes_read == nullptr)
- bytes_read = &ignore;
-
- /* Note that the endian-ness does not matter here. */
- int errcode = read_string (memaddr, -1, 1, len, BFD_ENDIAN_LITTLE,
- &buffer, bytes_read);
- if (errcode != 0)
- return {};
-
- return gdb::unique_xmalloc_ptr<char> ((char *) buffer.release ());
-}
-
-target_section_table *
+const target_section_table *
target_get_section_table (struct target_ops *target)
{
return target->get_section_table ();
/* Find a section containing ADDR. */
-struct target_section *
+const struct target_section *
target_section_by_addr (struct target_ops *target, CORE_ADDR addr)
{
- target_section_table *table = target_get_section_table (target);
+ const target_section_table *table = target_get_section_table (target);
if (table == NULL)
return NULL;
- for (target_section &secp : *table)
+ for (const target_section &secp : *table)
{
if (addr >= secp.addr && addr < secp.endaddr)
return &secp;
return NULL;
}
+/* See target.h. */
+
+const target_section_table *
+default_get_section_table ()
+{
+ return ¤t_program_space->target_sections ();
+}
/* Helper for the memory xfer routines. Checks the attributes of the
memory region of MEMADDR against the read or write being attempted.
break;
/* Don't continue past targets which have all the memory.
- At one time, this code was necessary to read data from
+ At one time, this code was necessary to read data from
executables / shared libraries when data for the requested
addresses weren't available in the core file. But now the
core target handles this case itself. */
if (pc_in_unmapped_range (memaddr, section))
{
- target_section_table *table = target_get_section_table (ops);
+ const target_section_table *table = target_get_section_table (ops);
const char *section_name = section->the_bfd_section->name;
memaddr = overlay_mapped_address (memaddr, section);
/* Try the executable files, if "trust-readonly-sections" is set. */
if (readbuf != NULL && trust_readonly)
{
- struct target_section *secp;
-
- secp = target_section_by_addr (ops, memaddr);
+ const struct target_section *secp
+ = target_section_by_addr (ops, memaddr);
if (secp != NULL
&& (bfd_section_flags (secp->the_bfd_section) & SEC_READONLY))
{
- target_section_table *table = target_get_section_table (ops);
+ const target_section_table *table = target_get_section_table (ops);
return section_table_xfer_memory_partial (readbuf, writebuf,
memaddr, len, xfered_len,
*table);
if (len == 0)
return TARGET_XFER_EOF;
- memaddr = address_significant (target_gdbarch (), memaddr);
+ memaddr = gdbarch_remove_non_address_bits (target_gdbarch (), memaddr);
/* Fill in READBUF with breakpoint shadows, or WRITEBUF with
breakpoint insns, thus hiding out from higher layers whether
{
const unsigned char *myaddr = NULL;
- fprintf_unfiltered (gdb_stdlog,
- "%s:target_xfer_partial "
- "(%d, %s, %s, %s, %s, %s) = %d, %s",
- ops->shortname (),
- (int) object,
- (annex ? annex : "(null)"),
- host_address_to_string (readbuf),
- host_address_to_string (writebuf),
- core_addr_to_string_nz (offset),
- pulongest (len), retval,
- pulongest (*xfered_len));
+ gdb_printf (gdb_stdlog,
+ "%s:target_xfer_partial "
+ "(%d, %s, %s, %s, %s, %s) = %d, %s",
+ ops->shortname (),
+ (int) object,
+ (annex ? annex : "(null)"),
+ host_address_to_string (readbuf),
+ host_address_to_string (writebuf),
+ core_addr_to_string_nz (offset),
+ pulongest (len), retval,
+ pulongest (*xfered_len));
if (readbuf)
myaddr = readbuf;
{
int i;
- fputs_unfiltered (", bytes =", gdb_stdlog);
+ gdb_puts (", bytes =", gdb_stdlog);
for (i = 0; i < *xfered_len; i++)
{
if ((((intptr_t) &(myaddr[i])) & 0xf) == 0)
{
if (targetdebug < 2 && i > 0)
{
- fprintf_unfiltered (gdb_stdlog, " ...");
+ gdb_printf (gdb_stdlog, " ...");
break;
}
- fprintf_unfiltered (gdb_stdlog, "\n");
+ gdb_printf (gdb_stdlog, "\n");
}
- fprintf_unfiltered (gdb_stdlog, " %02x", myaddr[i] & 0xff);
+ gdb_printf (gdb_stdlog, " %02x", myaddr[i] & 0xff);
}
}
- fputc_unfiltered ('\n', gdb_stdlog);
+ gdb_putc ('\n', gdb_stdlog);
}
/* Check implementations of to_xfer_partial update *XFERED_LEN
int
target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
{
- if (target_read (current_top_target (), TARGET_OBJECT_MEMORY, NULL,
+ if (target_read (current_inferior ()->top_target (),
+ TARGET_OBJECT_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
int
target_read_raw_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
{
- if (target_read (current_top_target (), TARGET_OBJECT_RAW_MEMORY, NULL,
+ if (target_read (current_inferior ()->top_target (),
+ TARGET_OBJECT_RAW_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
int
target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
{
- if (target_read (current_top_target (), TARGET_OBJECT_STACK_MEMORY, NULL,
+ if (target_read (current_inferior ()->top_target (),
+ TARGET_OBJECT_STACK_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
int
target_read_code (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
{
- if (target_read (current_top_target (), TARGET_OBJECT_CODE_MEMORY, NULL,
+ if (target_read (current_inferior ()->top_target (),
+ TARGET_OBJECT_CODE_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
int
target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
{
- if (target_write (current_top_target (), TARGET_OBJECT_MEMORY, NULL,
+ if (target_write (current_inferior ()->top_target (),
+ TARGET_OBJECT_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
int
target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
{
- if (target_write (current_top_target (), TARGET_OBJECT_RAW_MEMORY, NULL,
+ if (target_write (current_inferior ()->top_target (),
+ TARGET_OBJECT_RAW_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
std::vector<mem_region>
target_memory_map (void)
{
- std::vector<mem_region> result = current_top_target ()->memory_map ();
+ target_ops *target = current_inferior ()->top_target ();
+ std::vector<mem_region> result = target->memory_map ();
if (result.empty ())
return result;
void
target_flash_erase (ULONGEST address, LONGEST length)
{
- current_top_target ()->flash_erase (address, length);
+ current_inferior ()->top_target ()->flash_erase (address, length);
}
void
target_flash_done (void)
{
- current_top_target ()->flash_done ();
+ current_inferior ()->top_target ()->flash_done ();
}
static void
show_trust_readonly (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file,
- _("Mode for reading from readonly sections is %s.\n"),
- value);
+ gdb_printf (file,
+ _("Mode for reading from readonly sections is %s.\n"),
+ value);
}
/* Target vector read/write partial wrapper functions. */
return 1;
}
- return current_top_target ()->insert_breakpoint (gdbarch, bp_tgt);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->insert_breakpoint (gdbarch, bp_tgt);
}
/* See target.h. */
return 1;
}
- return current_top_target ()->remove_breakpoint (gdbarch, bp_tgt, reason);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->remove_breakpoint (gdbarch, bp_tgt, reason);
}
static void
{
int has_all_mem = 0;
- if (symfile_objfile != NULL)
- printf_unfiltered (_("Symbols from \"%s\".\n"),
- objfile_name (symfile_objfile));
+ if (current_program_space->symfile_object_file != NULL)
+ {
+ objfile *objf = current_program_space->symfile_object_file;
+ gdb_printf (_("Symbols from \"%s\".\n"),
+ objfile_name (objf));
+ }
- for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+ for (target_ops *t = current_inferior ()->top_target ();
+ t != NULL;
+ t = t->beneath ())
{
if (!t->has_memory ())
continue;
if ((int) (t->stratum ()) <= (int) dummy_stratum)
continue;
if (has_all_mem)
- printf_unfiltered (_("\tWhile running this, "
- "GDB does not access memory from...\n"));
- printf_unfiltered ("%s:\n", t->longname ());
+ gdb_printf (_("\tWhile running this, "
+ "GDB does not access memory from...\n"));
+ gdb_printf ("%s:\n", t->longname ());
t->files_info ();
has_all_mem = t->has_all_memory ();
}
/* attach_flag may be set if the previous process associated with
the inferior was attached to. */
- current_inferior ()->attach_flag = 0;
+ current_inferior ()->attach_flag = false;
current_inferior ()->highest_thread_num = 0;
it doesn't (which seems like a win for UDI), remove it now. */
/* Leave the exec target, though. The user may be switching from a
live process to a core of the same program. */
- pop_all_targets_above (file_stratum);
+ current_inferior ()->pop_all_targets_above (file_stratum);
target_pre_inferior (from_tty);
}
void
target_detach (inferior *inf, int from_tty)
{
+ /* Thread's don't need to be resumed until the end of this function. */
+ scoped_disable_commit_resumed disable_commit_resumed ("detaching");
+
/* After we have detached, we will clear the register cache for this inferior
by calling registers_changed_ptid. We must save the pid_ptid before
detaching, as the target detach method will clear inf->pid. */
assertion. */
gdb_assert (inf == current_inferior ());
- if (gdbarch_has_global_breakpoints (target_gdbarch ()))
- /* Don't remove global breakpoints here. They're removed on
- disconnection from the target. */
- ;
- else
- /* If we're in breakpoints-always-inserted mode, have to remove
- breakpoints before detaching. */
- remove_breakpoints_inf (current_inferior ());
-
prepare_for_detach ();
/* Hold a strong reference because detaching may unpush the
target. */
auto proc_target_ref = target_ops_ref::new_reference (inf->process_target ());
- current_top_target ()->detach (inf, from_tty);
+ current_inferior ()->top_target ()->detach (inf, from_tty);
process_stratum_target *proc_target
= as_process_stratum_target (proc_target_ref.get ());
inferior_ptid matches save_pid_ptid, but in our case, it does not
call it, as inferior_ptid has been reset. */
reinit_frame_cache ();
+
+ disable_commit_resumed.reset_and_commit ();
}
void
disconnecting. */
remove_breakpoints ();
- current_top_target ()->disconnect (args, from_tty);
+ current_inferior ()->top_target ()->disconnect (args, from_tty);
}
/* See target/target.h. */
target_wait (ptid_t ptid, struct target_waitstatus *status,
target_wait_flags options)
{
- target_ops *target = current_top_target ();
+ target_ops *target = current_inferior ()->top_target ();
+ process_stratum_target *proc_target = current_inferior ()->process_target ();
- if (!target->can_async_p ())
+ gdb_assert (!proc_target->commit_resumed_state);
+
+ if (!target_can_async_p (target))
gdb_assert ((options & TARGET_WNOHANG) == 0);
- return target->wait (ptid, status, options);
+ try
+ {
+ gdb::observers::target_pre_wait.notify (ptid);
+ ptid_t event_ptid = target->wait (ptid, status, options);
+ gdb::observers::target_post_wait.notify (event_ptid);
+ return event_ptid;
+ }
+ catch (...)
+ {
+ gdb::observers::target_post_wait.notify (null_ptid);
+ throw;
+ }
}
/* See target.h. */
ptid_t ptid, struct target_waitstatus *status,
target_wait_flags options)
{
- status->kind = TARGET_WAITKIND_IGNORE;
+ status->set_ignore ();
return minus_one_ptid;
}
std::string
target_pid_to_str (ptid_t ptid)
{
- return current_top_target ()->pid_to_str (ptid);
+ return current_inferior ()->top_target ()->pid_to_str (ptid);
}
const char *
{
gdb_assert (info->inf == current_inferior ());
- return current_top_target ()->thread_name (info);
+ return current_inferior ()->top_target ()->thread_name (info);
}
struct thread_info *
int handle_len,
struct inferior *inf)
{
- return current_top_target ()->thread_handle_to_thread_info (thread_handle,
- handle_len, inf);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->thread_handle_to_thread_info (thread_handle, handle_len, inf);
}
/* See target.h. */
gdb::byte_vector
target_thread_info_to_thread_handle (struct thread_info *tip)
{
- return current_top_target ()->thread_info_to_thread_handle (tip);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->thread_info_to_thread_handle (tip);
}
void
-target_resume (ptid_t ptid, int step, enum gdb_signal signal)
+target_resume (ptid_t scope_ptid, int step, enum gdb_signal signal)
{
process_stratum_target *curr_target = current_inferior ()->process_target ();
+ gdb_assert (!curr_target->commit_resumed_state);
+
+ gdb_assert (inferior_ptid != null_ptid);
+ gdb_assert (inferior_ptid.matches (scope_ptid));
target_dcache_invalidate ();
- current_top_target ()->resume (ptid, step, signal);
+ current_inferior ()->top_target ()->resume (scope_ptid, step, signal);
- registers_changed_ptid (curr_target, ptid);
+ registers_changed_ptid (curr_target, scope_ptid);
/* We only set the internal executing state here. The user/frontend
running state is set at a higher level. This also clears the
thread's stop_pc as side effect. */
- set_executing (curr_target, ptid, true);
- clear_inline_frame_state (curr_target, ptid);
-}
+ set_executing (curr_target, scope_ptid, true);
+ clear_inline_frame_state (curr_target, scope_ptid);
-/* If true, target_commit_resume is a nop. */
-static int defer_target_commit_resume;
+ if (target_can_async_p ())
+ target_async (true);
+}
/* See target.h. */
void
-target_commit_resume (void)
+target_commit_resumed ()
{
- if (defer_target_commit_resume)
- return;
-
- current_top_target ()->commit_resume ();
+ gdb_assert (current_inferior ()->process_target ()->commit_resumed_state);
+ current_inferior ()->top_target ()->commit_resumed ();
}
/* See target.h. */
-scoped_restore_tmpl<int>
-make_scoped_defer_target_commit_resume ()
+bool
+target_has_pending_events ()
{
- return make_scoped_restore (&defer_target_commit_resume, 1);
+ return current_inferior ()->top_target ()->has_pending_events ();
}
void
target_pass_signals (gdb::array_view<const unsigned char> pass_signals)
{
- current_top_target ()->pass_signals (pass_signals);
+ current_inferior ()->top_target ()->pass_signals (pass_signals);
}
void
target_program_signals (gdb::array_view<const unsigned char> program_signals)
{
- current_top_target ()->program_signals (program_signals);
+ current_inferior ()->top_target ()->program_signals (program_signals);
}
-static bool
-default_follow_fork (struct target_ops *self, bool follow_child,
- bool detach_fork)
+static void
+default_follow_fork (struct target_ops *self, inferior *child_inf,
+ ptid_t child_ptid, target_waitkind fork_kind,
+ bool follow_child, bool detach_fork)
{
/* Some target returned a fork event, but did not know how to follow it. */
- internal_error (__FILE__, __LINE__,
- _("could not find a target to follow fork"));
+ internal_error (_("could not find a target to follow fork"));
}
-/* Look through the list of possible targets for a target that can
- follow forks. */
+/* See target.h. */
-bool
-target_follow_fork (bool follow_child, bool detach_fork)
+void
+target_follow_fork (inferior *child_inf, ptid_t child_ptid,
+ target_waitkind fork_kind, bool follow_child,
+ bool detach_fork)
{
- return current_top_target ()->follow_fork (follow_child, detach_fork);
+ target_ops *target = current_inferior ()->top_target ();
+
+ /* Check consistency between CHILD_INF, CHILD_PTID, FOLLOW_CHILD and
+ DETACH_FORK. */
+ if (child_inf != nullptr)
+ {
+ gdb_assert (follow_child || !detach_fork);
+ gdb_assert (child_inf->pid == child_ptid.pid ());
+ }
+ else
+ gdb_assert (!follow_child && detach_fork);
+
+ return target->follow_fork (child_inf, child_ptid, fork_kind, follow_child,
+ detach_fork);
}
-/* Target wrapper for follow exec hook. */
+/* See target.h. */
void
-target_follow_exec (struct inferior *inf, const char *execd_pathname)
+target_follow_exec (inferior *follow_inf, ptid_t ptid,
+ const char *execd_pathname)
{
- current_top_target ()->follow_exec (inf, execd_pathname);
+ current_inferior ()->top_target ()->follow_exec (follow_inf, ptid,
+ execd_pathname);
}
static void
default_mourn_inferior (struct target_ops *self)
{
- internal_error (__FILE__, __LINE__,
- _("could not find a target to follow mourn inferior"));
+ internal_error (_("could not find a target to follow mourn inferior"));
}
void
target_mourn_inferior (ptid_t ptid)
{
- gdb_assert (ptid == inferior_ptid);
- current_top_target ()->mourn_inferior ();
+ gdb_assert (ptid.pid () == inferior_ptid.pid ());
+ current_inferior ()->top_target ()->mourn_inferior ();
/* We no longer need to keep handles on any of the object files.
Make sure to release them to avoid unnecessarily locking any
{
auto read_memory = [=] (CORE_ADDR addr, gdb_byte *result, size_t len)
{
- return target_read (current_top_target (), TARGET_OBJECT_MEMORY, NULL,
+ return target_read (current_inferior ()->top_target (),
+ TARGET_OBJECT_MEMORY, NULL,
result, addr, len) == len;
};
const gdb_byte *pattern, ULONGEST pattern_len,
CORE_ADDR *found_addrp)
{
- return current_top_target ()->search_memory (start_addr, search_space_len,
- pattern, pattern_len, found_addrp);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->search_memory (start_addr, search_space_len, pattern,
+ pattern_len, found_addrp);
}
/* Look through the currently pushed targets. If none of them will
void
target_require_runnable (void)
{
- for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+ for (target_ops *t = current_inferior ()->top_target ();
+ t != NULL;
+ t = t->beneath ())
{
/* If this target knows how to create a new program, then
assume we will still be able to after killing the current
/* This function is only called if the target is running. In that
case there should have been a process_stratum target and it
should either know how to create inferiors, or not... */
- internal_error (__FILE__, __LINE__, _("No targets found"));
+ internal_error (_("No targets found"));
}
/* Whether GDB is allowed to fall back to the default run target for
show_auto_connect_native_target (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file,
- _("Whether GDB may automatically connect to the "
- "native target is %s.\n"),
- value);
+ gdb_printf (file,
+ _("Whether GDB may automatically connect to the "
+ "native target is %s.\n"),
+ value);
}
/* A pointer to the target that can respond to "run" or "attach".
set_native_target (target_ops *target)
{
if (the_native_target != NULL)
- internal_error (__FILE__, __LINE__,
- _("native target already set (\"%s\")."),
+ internal_error (_("native target already set (\"%s\")."),
the_native_target->longname ());
the_native_target = target;
find_attach_target (void)
{
/* If a target on the current stack can attach, use it. */
- for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+ for (target_ops *t = current_inferior ()->top_target ();
+ t != NULL;
+ t = t->beneath ())
{
if (t->can_attach ())
return t;
find_run_target (void)
{
/* If a target on the current stack can run, use it. */
- for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+ for (target_ops *t = current_inferior ()->top_target ();
+ t != NULL;
+ t = t->beneath ())
{
if (t->can_create_inferior ())
return t;
if (t->info_proc (args, what))
{
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_info_proc (\"%s\", %d)\n", args, what);
+ gdb_printf (gdb_stdlog,
+ "target_info_proc (\"%s\", %d)\n", args, what);
return 1;
}
int
target_supports_disable_randomization (void)
{
- return current_top_target ()->supports_disable_randomization ();
+ return current_inferior ()->top_target ()->supports_disable_randomization ();
}
/* See target/target.h. */
int
target_supports_multi_process (void)
{
- return current_top_target ()->supports_multi_process ();
+ return current_inferior ()->top_target ()->supports_multi_process ();
}
/* See target.h. */
{
struct address_space *aspace;
- aspace = current_top_target ()->thread_address_space (ptid);
+ aspace = current_inferior ()->top_target ()->thread_address_space (ptid);
gdb_assert (aspace != NULL);
return aspace;
int
target_can_run ()
{
- for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+ for (target_ops *t = current_inferior ()->top_target ();
+ t != NULL;
+ t = t->beneath ())
{
if (t->can_run ())
return 1;
list each time a new file is opened. */
static int lowest_closed_fd;
-/* Invalidate the target associated with open handles that were open
- on target TARG, since we're about to close (and maybe destroy) the
- target. The handles remain open from the client's perspective, but
- trying to do anything with them other than closing them will fail
- with EIO. */
+/* See target.h. */
-static void
+void
fileio_handles_invalidate_target (target_ops *targ)
{
for (fileio_fh_t &fh : fileio_fhandles)
int
target_ops::fileio_open (struct inferior *inf, const char *filename,
int flags, int mode, int warn_if_slow,
- int *target_errno)
+ fileio_error *target_errno)
{
*target_errno = FILEIO_ENOSYS;
return -1;
int
target_ops::fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
- ULONGEST offset, int *target_errno)
+ ULONGEST offset, fileio_error *target_errno)
{
*target_errno = FILEIO_ENOSYS;
return -1;
int
target_ops::fileio_pread (int fd, gdb_byte *read_buf, int len,
- ULONGEST offset, int *target_errno)
+ ULONGEST offset, fileio_error *target_errno)
{
*target_errno = FILEIO_ENOSYS;
return -1;
}
int
-target_ops::fileio_fstat (int fd, struct stat *sb, int *target_errno)
+target_ops::fileio_fstat (int fd, struct stat *sb, fileio_error *target_errno)
{
*target_errno = FILEIO_ENOSYS;
return -1;
}
int
-target_ops::fileio_close (int fd, int *target_errno)
+target_ops::fileio_close (int fd, fileio_error *target_errno)
{
*target_errno = FILEIO_ENOSYS;
return -1;
int
target_ops::fileio_unlink (struct inferior *inf, const char *filename,
- int *target_errno)
+ fileio_error *target_errno)
{
*target_errno = FILEIO_ENOSYS;
return -1;
gdb::optional<std::string>
target_ops::fileio_readlink (struct inferior *inf, const char *filename,
- int *target_errno)
+ fileio_error *target_errno)
{
*target_errno = FILEIO_ENOSYS;
return {};
int
target_fileio_open (struct inferior *inf, const char *filename,
- int flags, int mode, bool warn_if_slow, int *target_errno)
+ int flags, int mode, bool warn_if_slow, fileio_error *target_errno)
{
for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
{
fd = acquire_fileio_fd (t, fd);
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_open (%d,%s,0x%x,0%o,%d)"
- " = %d (%d)\n",
- inf == NULL ? 0 : inf->num,
- filename, flags, mode,
- warn_if_slow, fd,
- fd != -1 ? 0 : *target_errno);
+ gdb_printf (gdb_stdlog,
+ "target_fileio_open (%d,%s,0x%x,0%o,%d)"
+ " = %d (%d)\n",
+ inf == NULL ? 0 : inf->num,
+ filename, flags, mode,
+ warn_if_slow, fd,
+ fd != -1 ? 0 : *target_errno);
return fd;
}
int
target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
- ULONGEST offset, int *target_errno)
+ ULONGEST offset, fileio_error *target_errno)
{
fileio_fh_t *fh = fileio_fd_to_fh (fd);
int ret = -1;
if (fh->is_closed ())
- *target_errno = EBADF;
+ *target_errno = FILEIO_EBADF;
else if (fh->target == NULL)
- *target_errno = EIO;
+ *target_errno = FILEIO_EIO;
else
ret = fh->target->fileio_pwrite (fh->target_fd, write_buf,
len, offset, target_errno);
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_pwrite (%d,...,%d,%s) "
- "= %d (%d)\n",
- fd, len, pulongest (offset),
- ret, ret != -1 ? 0 : *target_errno);
+ gdb_printf (gdb_stdlog,
+ "target_fileio_pwrite (%d,...,%d,%s) "
+ "= %d (%d)\n",
+ fd, len, pulongest (offset),
+ ret, ret != -1 ? 0 : *target_errno);
return ret;
}
int
target_fileio_pread (int fd, gdb_byte *read_buf, int len,
- ULONGEST offset, int *target_errno)
+ ULONGEST offset, fileio_error *target_errno)
{
fileio_fh_t *fh = fileio_fd_to_fh (fd);
int ret = -1;
if (fh->is_closed ())
- *target_errno = EBADF;
+ *target_errno = FILEIO_EBADF;
else if (fh->target == NULL)
- *target_errno = EIO;
+ *target_errno = FILEIO_EIO;
else
ret = fh->target->fileio_pread (fh->target_fd, read_buf,
len, offset, target_errno);
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_pread (%d,...,%d,%s) "
- "= %d (%d)\n",
- fd, len, pulongest (offset),
- ret, ret != -1 ? 0 : *target_errno);
+ gdb_printf (gdb_stdlog,
+ "target_fileio_pread (%d,...,%d,%s) "
+ "= %d (%d)\n",
+ fd, len, pulongest (offset),
+ ret, ret != -1 ? 0 : *target_errno);
return ret;
}
/* See target.h. */
int
-target_fileio_fstat (int fd, struct stat *sb, int *target_errno)
+target_fileio_fstat (int fd, struct stat *sb, fileio_error *target_errno)
{
fileio_fh_t *fh = fileio_fd_to_fh (fd);
int ret = -1;
if (fh->is_closed ())
- *target_errno = EBADF;
+ *target_errno = FILEIO_EBADF;
else if (fh->target == NULL)
- *target_errno = EIO;
+ *target_errno = FILEIO_EIO;
else
ret = fh->target->fileio_fstat (fh->target_fd, sb, target_errno);
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_fstat (%d) = %d (%d)\n",
- fd, ret, ret != -1 ? 0 : *target_errno);
+ gdb_printf (gdb_stdlog,
+ "target_fileio_fstat (%d) = %d (%d)\n",
+ fd, ret, ret != -1 ? 0 : *target_errno);
return ret;
}
/* See target.h. */
int
-target_fileio_close (int fd, int *target_errno)
+target_fileio_close (int fd, fileio_error *target_errno)
{
fileio_fh_t *fh = fileio_fd_to_fh (fd);
int ret = -1;
if (fh->is_closed ())
- *target_errno = EBADF;
+ *target_errno = FILEIO_EBADF;
else
{
if (fh->target != NULL)
}
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_close (%d) = %d (%d)\n",
- fd, ret, ret != -1 ? 0 : *target_errno);
+ gdb_printf (gdb_stdlog,
+ "target_fileio_close (%d) = %d (%d)\n",
+ fd, ret, ret != -1 ? 0 : *target_errno);
return ret;
}
int
target_fileio_unlink (struct inferior *inf, const char *filename,
- int *target_errno)
+ fileio_error *target_errno)
{
for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
{
continue;
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_unlink (%d,%s)"
- " = %d (%d)\n",
- inf == NULL ? 0 : inf->num, filename,
- ret, ret != -1 ? 0 : *target_errno);
+ gdb_printf (gdb_stdlog,
+ "target_fileio_unlink (%d,%s)"
+ " = %d (%d)\n",
+ inf == NULL ? 0 : inf->num, filename,
+ ret, ret != -1 ? 0 : *target_errno);
return ret;
}
gdb::optional<std::string>
target_fileio_readlink (struct inferior *inf, const char *filename,
- int *target_errno)
+ fileio_error *target_errno)
{
for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
{
continue;
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_readlink (%d,%s)"
- " = %s (%d)\n",
- inf == NULL ? 0 : inf->num,
- filename, ret ? ret->c_str () : "(nil)",
- ret ? 0 : *target_errno);
+ gdb_printf (gdb_stdlog,
+ "target_fileio_readlink (%d,%s)"
+ " = %s (%d)\n",
+ inf == NULL ? 0 : inf->num,
+ filename, ret ? ret->c_str () : "(nil)",
+ ret ? 0 : *target_errno);
return ret;
}
{
if (m_fd >= 0)
{
- int target_errno;
+ fileio_error target_errno;
target_fileio_close (m_fd, &target_errno);
}
size_t buf_alloc, buf_pos;
gdb_byte *buf;
LONGEST n;
- int target_errno;
+ fileio_error target_errno;
scoped_target_fd fd (target_fileio_open (inf, filename, FILEIO_O_RDONLY,
0700, false, &target_errno));
{
/* Look for a non-empty slot at stratum levels beneath T's. */
for (int stratum = t->stratum () - 1; stratum >= 0; --stratum)
- if (m_stack[stratum] != NULL)
- return m_stack[stratum];
+ if (m_stack[stratum].get () != NULL)
+ return m_stack[stratum].get ();
return NULL;
}
if (!from_tty)
return;
+ pid = inferior_ptid.pid ();
exec_file = get_exec_file (0);
- if (exec_file == NULL)
- exec_file = "";
+ if (exec_file == nullptr)
+ gdb_printf ("Detaching from pid %s\n",
+ target_pid_to_str (ptid_t (pid)).c_str ());
+ else
+ gdb_printf (_("Detaching from program: %s, %s\n"), exec_file,
+ target_pid_to_str (ptid_t (pid)).c_str ());
+}
- pid = inferior_ptid.pid ();
- printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
- target_pid_to_str (ptid_t (pid)).c_str ());
+/* See target.h */
+
+void
+target_announce_attach (int from_tty, int pid)
+{
+ if (!from_tty)
+ return;
+
+ const char *exec_file = get_exec_file (0);
+
+ if (exec_file != nullptr)
+ gdb_printf ("Attaching to program: %s, %s\n", exec_file,
+ target_pid_to_str (ptid_t (pid)).c_str ());
+ else
+ gdb_printf ("Attaching to %s\n",
+ target_pid_to_str (ptid_t (pid)).c_str ());
}
/* The inferior process has died. Long live the inferior! */
void
target_close (struct target_ops *targ)
{
- gdb_assert (!target_is_pushed (targ));
+ for (inferior *inf : all_inferiors ())
+ gdb_assert (!inf->target_is_pushed (targ));
fileio_handles_invalidate_target (targ);
targ->close ();
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog, "target_close ()\n");
+ gdb_printf (gdb_stdlog, "target_close ()\n");
}
int
target_thread_alive (ptid_t ptid)
{
- return current_top_target ()->thread_alive (ptid);
+ return current_inferior ()->top_target ()->thread_alive (ptid);
}
void
target_update_thread_list (void)
{
- current_top_target ()->update_thread_list ();
+ current_inferior ()->top_target ()->update_thread_list ();
}
void
target_stop (ptid_t ptid)
{
+ process_stratum_target *proc_target = current_inferior ()->process_target ();
+
+ gdb_assert (!proc_target->commit_resumed_state);
+
if (!may_stop)
{
warning (_("May not interrupt or stop the target, ignoring attempt"));
return;
}
- current_top_target ()->stop (ptid);
+ current_inferior ()->top_target ()->stop (ptid);
}
void
return;
}
- current_top_target ()->interrupt ();
+ current_inferior ()->top_target ()->interrupt ();
}
/* See target.h. */
{
/* A thread can be THREAD_STOPPED and executing, while
running an infcall. */
- if (thr->state == THREAD_RUNNING || thr->executing)
+ if (thr->state == THREAD_RUNNING || thr->executing ())
{
/* We can get here quite deep in target layers. Avoid
switching thread context or anything that would
through the target_stack. */
scoped_restore_current_inferior restore_inferior;
set_current_inferior (inf);
- current_top_target ()->pass_ctrlc ();
+ current_inferior ()->top_target ()->pass_ctrlc ();
return;
}
}
non_stop = true;
target_stop (ptid);
- memset (&status, 0, sizeof (status));
target_wait (ptid, &status, 0);
non_stop = was_non_stop;
void
target_fetch_registers (struct regcache *regcache, int regno)
{
- current_top_target ()->fetch_registers (regcache, regno);
+ current_inferior ()->top_target ()->fetch_registers (regcache, regno);
if (targetdebug)
regcache->debug_print_register ("target_fetch_registers", regno);
}
if (!may_write_registers)
error (_("Writing to registers is not allowed (regno %d)"), regno);
- current_top_target ()->store_registers (regcache, regno);
+ current_inferior ()->top_target ()->store_registers (regcache, regno);
if (targetdebug)
{
regcache->debug_print_register ("target_store_registers", regno);
int
target_core_of_thread (ptid_t ptid)
{
- return current_top_target ()->core_of_thread (ptid);
+ return current_inferior ()->top_target ()->core_of_thread (ptid);
}
int
const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
{
/* Start over from the top of the target stack. */
- return simple_verify_memory (current_top_target (),
+ return simple_verify_memory (current_inferior ()->top_target (),
data, memaddr, size);
}
int
target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
{
- return current_top_target ()->verify_memory (data, memaddr, size);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->verify_memory (data, memaddr, size);
}
/* The documentation for this function is in its prototype declaration in
target_insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
enum target_hw_bp_type rw)
{
- return current_top_target ()->insert_mask_watchpoint (addr, mask, rw);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->insert_mask_watchpoint (addr, mask, rw);
}
/* The documentation for this function is in its prototype declaration in
target_remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
enum target_hw_bp_type rw)
{
- return current_top_target ()->remove_mask_watchpoint (addr, mask, rw);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->remove_mask_watchpoint (addr, mask, rw);
}
/* The documentation for this function is in its prototype declaration
int
target_masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask)
{
- return current_top_target ()->masked_watch_num_registers (addr, mask);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->masked_watch_num_registers (addr, mask);
}
/* The documentation for this function is in its prototype declaration
int
target_ranged_break_num_registers (void)
{
- return current_top_target ()->ranged_break_num_registers ();
+ return current_inferior ()->top_target ()->ranged_break_num_registers ();
}
/* See target.h. */
struct btrace_target_info *
-target_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
+target_enable_btrace (thread_info *tp, const struct btrace_config *conf)
{
- return current_top_target ()->enable_btrace (ptid, conf);
+ return current_inferior ()->top_target ()->enable_btrace (tp, conf);
}
/* See target.h. */
void
target_disable_btrace (struct btrace_target_info *btinfo)
{
- current_top_target ()->disable_btrace (btinfo);
+ current_inferior ()->top_target ()->disable_btrace (btinfo);
}
/* See target.h. */
void
target_teardown_btrace (struct btrace_target_info *btinfo)
{
- current_top_target ()->teardown_btrace (btinfo);
+ current_inferior ()->top_target ()->teardown_btrace (btinfo);
}
/* See target.h. */
struct btrace_target_info *btinfo,
enum btrace_read_type type)
{
- return current_top_target ()->read_btrace (btrace, btinfo, type);
+ target_ops *target = current_inferior ()->top_target ();
+
+ return target->read_btrace (btrace, btinfo, type);
}
/* See target.h. */
const struct btrace_config *
target_btrace_conf (const struct btrace_target_info *btinfo)
{
- return current_top_target ()->btrace_conf (btinfo);
+ return current_inferior ()->top_target ()->btrace_conf (btinfo);
}
/* See target.h. */
void
target_stop_recording (void)
{
- current_top_target ()->stop_recording ();
+ current_inferior ()->top_target ()->stop_recording ();
}
/* See target.h. */
void
target_save_record (const char *filename)
{
- current_top_target ()->save_record (filename);
+ current_inferior ()->top_target ()->save_record (filename);
}
/* See target.h. */
int
target_supports_delete_record ()
{
- return current_top_target ()->supports_delete_record ();
+ return current_inferior ()->top_target ()->supports_delete_record ();
}
/* See target.h. */
void
target_delete_record (void)
{
- current_top_target ()->delete_record ();
+ current_inferior ()->top_target ()->delete_record ();
}
/* See target.h. */
enum record_method
target_record_method (ptid_t ptid)
{
- return current_top_target ()->record_method (ptid);
+ return current_inferior ()->top_target ()->record_method (ptid);
}
/* See target.h. */
int
target_record_is_replaying (ptid_t ptid)
{
- return current_top_target ()->record_is_replaying (ptid);
+ return current_inferior ()->top_target ()->record_is_replaying (ptid);
}
/* See target.h. */
int
target_record_will_replay (ptid_t ptid, int dir)
{
- return current_top_target ()->record_will_replay (ptid, dir);
+ return current_inferior ()->top_target ()->record_will_replay (ptid, dir);
}
/* See target.h. */
void
target_record_stop_replaying (void)
{
- current_top_target ()->record_stop_replaying ();
+ current_inferior ()->top_target ()->record_stop_replaying ();
}
/* See target.h. */
void
target_goto_record_begin (void)
{
- current_top_target ()->goto_record_begin ();
+ current_inferior ()->top_target ()->goto_record_begin ();
}
/* See target.h. */
void
target_goto_record_end (void)
{
- current_top_target ()->goto_record_end ();
+ current_inferior ()->top_target ()->goto_record_end ();
}
/* See target.h. */
void
target_goto_record (ULONGEST insn)
{
- current_top_target ()->goto_record (insn);
+ current_inferior ()->top_target ()->goto_record (insn);
}
/* See target.h. */
void
target_insn_history (int size, gdb_disassembly_flags flags)
{
- current_top_target ()->insn_history (size, flags);
+ current_inferior ()->top_target ()->insn_history (size, flags);
}
/* See target.h. */
target_insn_history_from (ULONGEST from, int size,
gdb_disassembly_flags flags)
{
- current_top_target ()->insn_history_from (from, size, flags);
+ current_inferior ()->top_target ()->insn_history_from (from, size, flags);
}
/* See target.h. */
target_insn_history_range (ULONGEST begin, ULONGEST end,
gdb_disassembly_flags flags)
{
- current_top_target ()->insn_history_range (begin, end, flags);
+ current_inferior ()->top_target ()->insn_history_range (begin, end, flags);
}
/* See target.h. */
void
target_call_history (int size, record_print_flags flags)
{
- current_top_target ()->call_history (size, flags);
+ current_inferior ()->top_target ()->call_history (size, flags);
}
/* See target.h. */
void
target_call_history_from (ULONGEST begin, int size, record_print_flags flags)
{
- current_top_target ()->call_history_from (begin, size, flags);
+ current_inferior ()->top_target ()->call_history_from (begin, size, flags);
}
/* See target.h. */
void
target_call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flags)
{
- current_top_target ()->call_history_range (begin, end, flags);
+ current_inferior ()->top_target ()->call_history_range (begin, end, flags);
}
/* See target.h. */
const struct frame_unwind *
target_get_unwinder (void)
{
- return current_top_target ()->get_unwinder ();
+ return current_inferior ()->top_target ()->get_unwinder ();
}
/* See target.h. */
const struct frame_unwind *
target_get_tailcall_unwinder (void)
{
- return current_top_target ()->get_tailcall_unwinder ();
+ return current_inferior ()->top_target ()->get_tailcall_unwinder ();
}
/* See target.h. */
void
target_prepare_to_generate_core (void)
{
- current_top_target ()->prepare_to_generate_core ();
+ current_inferior ()->top_target ()->prepare_to_generate_core ();
}
/* See target.h. */
void
target_done_generating_core (void)
{
- current_top_target ()->done_generating_core ();
+ current_inferior ()->top_target ()->done_generating_core ();
}
\f
{
/* Is this a flash memory region? */
if (m.attrib.mode == MEM_FLASH)
- {
- found_flash_region = true;
- target_flash_erase (m.lo, m.hi - m.lo);
+ {
+ found_flash_region = true;
+ target_flash_erase (m.lo, m.hi - m.lo);
ui_out_emit_tuple tuple_emitter (current_uiout, "erased-regions");
- current_uiout->message (_("Erasing flash memory region at address "));
- current_uiout->field_core_addr ("address", gdbarch, m.lo);
- current_uiout->message (", size = ");
- current_uiout->field_string ("size", hex_string (m.hi - m.lo));
- current_uiout->message ("\n");
- }
+ current_uiout->message (_("Erasing flash memory region at address "));
+ current_uiout->field_core_addr ("address", gdbarch, m.lo);
+ current_uiout->message (", size = ");
+ current_uiout->field_string ("size", hex_string (m.hi - m.lo));
+ current_uiout->message ("\n");
+ }
}
/* Did we do any flash operations? If so, we need to finalize them. */
static void
maintenance_print_target_stack (const char *cmd, int from_tty)
{
- printf_filtered (_("The current target stack is:\n"));
+ gdb_printf (_("The current target stack is:\n"));
- for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+ for (target_ops *t = current_inferior ()->top_target ();
+ t != NULL;
+ t = t->beneath ())
{
if (t->stratum () == debug_stratum)
continue;
- printf_filtered (" - %s (%s)\n", t->shortname (), t->longname ());
+ gdb_printf (" - %s (%s)\n", t->shortname (), t->longname ());
}
}
/* See target.h. */
void
-target_async (int enable)
+target_async (bool enable)
{
+ /* If we are trying to enable async mode then it must be the case that
+ async mode is possible for this target. */
+ gdb_assert (!enable || target_can_async_p ());
infrun_async (enable);
- current_top_target ()->async (enable);
+ current_inferior ()->top_target ()->async (enable);
}
/* See target.h. */
void
target_thread_events (int enable)
{
- current_top_target ()->thread_events (enable);
+ current_inferior ()->top_target ()->thread_events (enable);
}
/* Controls if targets can report that they can/are async. This is
just for maintainers to use when debugging gdb. */
bool target_async_permitted = true;
-/* The set command writes to this variable. If the inferior is
- executing, target_async_permitted is *not* updated. */
-static bool target_async_permitted_1 = true;
-
static void
-maint_set_target_async_command (const char *args, int from_tty,
- struct cmd_list_element *c)
+set_maint_target_async (bool permitted)
{
if (have_live_inferiors ())
- {
- target_async_permitted_1 = target_async_permitted;
- error (_("Cannot change this setting while the inferior is running."));
- }
+ error (_("Cannot change this setting while the inferior is running."));
+
+ target_async_permitted = permitted;
+}
- target_async_permitted = target_async_permitted_1;
+static bool
+get_maint_target_async ()
+{
+ return target_async_permitted;
}
static void
-maint_show_target_async_command (struct ui_file *file, int from_tty,
- struct cmd_list_element *c,
- const char *value)
+show_maint_target_async (ui_file *file, int from_tty,
+ cmd_list_element *c, const char *value)
{
- fprintf_filtered (file,
- _("Controlling the inferior in "
- "asynchronous mode is %s.\n"), value);
+ gdb_printf (file,
+ _("Controlling the inferior in "
+ "asynchronous mode is %s.\n"), value);
}
/* Return true if the target operates in non-stop mode even with "set
static int
target_always_non_stop_p (void)
{
- return current_top_target ()->always_non_stop_p ();
+ return current_inferior ()->top_target ()->always_non_stop_p ();
}
/* See target.h. */
-int
-target_is_non_stop_p (void)
+bool
+target_is_non_stop_p ()
{
- return (non_stop
- || target_non_stop_enabled == AUTO_BOOLEAN_TRUE
- || (target_non_stop_enabled == AUTO_BOOLEAN_AUTO
- && target_always_non_stop_p ()));
+ return ((non_stop
+ || target_non_stop_enabled == AUTO_BOOLEAN_TRUE
+ || (target_non_stop_enabled == AUTO_BOOLEAN_AUTO
+ && target_always_non_stop_p ()))
+ && target_can_async_p ());
}
/* See target.h. */
mode. This is just for maintainers to use when debugging gdb. */
enum auto_boolean target_non_stop_enabled = AUTO_BOOLEAN_AUTO;
-/* The set command writes to this variable. If the inferior is
- executing, target_non_stop_enabled is *not* updated. */
-static enum auto_boolean target_non_stop_enabled_1 = AUTO_BOOLEAN_AUTO;
-
-/* Implementation of "maint set target-non-stop". */
+/* Set callback for maint target-non-stop setting. */
static void
-maint_set_target_non_stop_command (const char *args, int from_tty,
- struct cmd_list_element *c)
+set_maint_target_non_stop (auto_boolean enabled)
{
if (have_live_inferiors ())
- {
- target_non_stop_enabled_1 = target_non_stop_enabled;
- error (_("Cannot change this setting while the inferior is running."));
- }
+ error (_("Cannot change this setting while the inferior is running."));
- target_non_stop_enabled = target_non_stop_enabled_1;
+ target_non_stop_enabled = enabled;
}
-/* Implementation of "maint show target-non-stop". */
+/* Get callback for maint target-non-stop setting. */
+
+static auto_boolean
+get_maint_target_non_stop ()
+{
+ return target_non_stop_enabled;
+}
static void
-maint_show_target_non_stop_command (struct ui_file *file, int from_tty,
- struct cmd_list_element *c,
- const char *value)
+show_maint_target_non_stop (ui_file *file, int from_tty,
+ cmd_list_element *c, const char *value)
{
if (target_non_stop_enabled == AUTO_BOOLEAN_AUTO)
- fprintf_filtered (file,
- _("Whether the target is always in non-stop mode "
- "is %s (currently %s).\n"), value,
- target_always_non_stop_p () ? "on" : "off");
+ gdb_printf (file,
+ _("Whether the target is always in non-stop mode "
+ "is %s (currently %s).\n"), value,
+ target_always_non_stop_p () ? "on" : "off");
else
- fprintf_filtered (file,
- _("Whether the target is always in non-stop mode "
- "is %s.\n"), value);
+ gdb_printf (file,
+ _("Whether the target is always in non-stop mode "
+ "is %s.\n"), value);
}
/* Temporary copies of permission settings. */
_("Send a command to the remote monitor (remote targets only)."));
add_cmd ("target-stack", class_maintenance, maintenance_print_target_stack,
- _("Print the name of each layer of the internal target stack."),
- &maintenanceprintlist);
+ _("Print the name of each layer of the internal target stack."),
+ &maintenanceprintlist);
add_setshow_boolean_cmd ("target-async", no_class,
- &target_async_permitted_1, _("\
+ _("\
Set whether gdb controls the inferior in asynchronous mode."), _("\
Show whether gdb controls the inferior in asynchronous mode."), _("\
Tells gdb whether to control the inferior in asynchronous mode."),
- maint_set_target_async_command,
- maint_show_target_async_command,
+ set_maint_target_async,
+ get_maint_target_async,
+ show_maint_target_async,
&maintenance_set_cmdlist,
&maintenance_show_cmdlist);
add_setshow_auto_boolean_cmd ("target-non-stop", no_class,
- &target_non_stop_enabled_1, _("\
+ _("\
Set whether gdb always controls the inferior in non-stop mode."), _("\
Show whether gdb always controls the inferior in non-stop mode."), _("\
Tells gdb whether to control the inferior in non-stop mode."),
- maint_set_target_non_stop_command,
- maint_show_target_non_stop_command,
+ set_maint_target_non_stop,
+ get_maint_target_non_stop,
+ show_maint_target_non_stop,
&maintenance_set_cmdlist,
&maintenance_show_cmdlist);
&setlist, &showlist);
add_com ("flash-erase", no_class, flash_erase_command,
- _("Erase all flash memory regions."));
+ _("Erase all flash memory regions."));
add_setshow_boolean_cmd ("auto-connect-native-target", class_support,
&auto_connect_native_target, _("\