/* Select target systems and architectures at runtime for GDB.
- Copyright (C) 1990-2018 Free Software Foundation, Inc.
+ Copyright (C) 1990-2020 Free Software Foundation, Inc.
Contributed by Cygnus Support.
#include "inline-frame.h"
#include "tracepoint.h"
#include "gdb/fileio.h"
-#include "agent.h"
+#include "gdbsupport/agent.h"
#include "auxv.h"
#include "target-debug.h"
#include "top.h"
#include "event-top.h"
#include <algorithm>
-#include "byte-vector.h"
+#include "gdbsupport/byte-vector.h"
#include "terminal.h"
-#include <algorithm>
+#include <unordered_map>
+#include "target-connection.h"
static void generic_tls_error (void) ATTRIBUTE_NORETURN;
const gdb_byte *data,
CORE_ADDR memaddr, ULONGEST size);
-static struct address_space *default_thread_address_space
- (struct target_ops *self, ptid_t ptid);
-
static void tcomplain (void) ATTRIBUTE_NORETURN;
static struct target_ops *find_default_run_target (const char *);
-static struct gdbarch *default_thread_architecture (struct target_ops *ops,
- ptid_t ptid);
-
static int dummy_find_memory_regions (struct target_ops *self,
find_memory_region_ftype ignore1,
void *ignore2);
static char *dummy_make_corefile_notes (struct target_ops *self,
bfd *ignore1, int *ignore2);
-static const char *default_pid_to_str (struct target_ops *ops, ptid_t ptid);
+static std::string default_pid_to_str (struct target_ops *ops, ptid_t ptid);
static enum exec_direction_kind default_execution_direction
(struct target_ops *self);
-/* Vector of existing target structures. */
-typedef struct target_ops *target_ops_p;
-DEF_VEC_P (target_ops_p);
-static VEC (target_ops_p) *target_structs;
+/* Mapping between target_info objects (which have address identity)
+ and corresponding open/factory function/callback. Each add_target
+ call adds one entry to this map, and registers a "target
+ TARGET_NAME" command that when invoked calls the factory registered
+ here. The target_info object is associated with the command via
+ the command's context. */
+static std::unordered_map<const target_info *, target_open_ftype *>
+ target_factories;
-/* The initial current target, so that there is always a semi-valid
- current target. */
+/* The singleton debug target. */
-static struct target_ops *the_dummy_target;
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. */
-struct target_ops *target_stack;
+target_ops *
+current_top_target ()
+{
+ return current_inferior ()->top_target ();
+}
/* Command list for target. */
static struct cmd_list_element *targetlist = NULL;
-/* Nonzero if we should trust readonly sections from the
+/* True if we should trust readonly sections from the
executable when reading memory. */
-static int trust_readonly = 0;
+static bool trust_readonly = false;
/* Nonzero if we should show true memory content including
memory breakpoint inserted by gdb. */
/* These globals control whether GDB attempts to perform these
operations; they are useful for targets that need to prevent
- inadvertant disruption, such as in non-stop mode. */
+ inadvertent disruption, such as in non-stop mode. */
-int may_write_registers = 1;
+bool may_write_registers = true;
-int may_write_memory = 1;
+bool may_write_memory = true;
-int may_insert_breakpoints = 1;
+bool may_insert_breakpoints = true;
-int may_insert_tracepoints = 1;
+bool may_insert_tracepoints = true;
-int may_insert_fast_tracepoints = 1;
+bool may_insert_fast_tracepoints = true;
-int may_stop = 1;
+bool may_stop = true;
/* Non-zero if we want to see trace of target level stuff. */
gdb_stdout);
}
-/* Default target_has_* methods for process_stratum targets. */
-
-int
-default_child_has_all_memory ()
-{
- /* If no inferior selected, then we can't read memory here. */
- if (ptid_equal (inferior_ptid, null_ptid))
- return 0;
-
- return 1;
-}
-
-int
-default_child_has_memory ()
-{
- /* If no inferior selected, then we can't read memory here. */
- if (ptid_equal (inferior_ptid, null_ptid))
- return 0;
-
- return 1;
-}
-
-int
-default_child_has_stack ()
-{
- /* If no inferior selected, there's no stack. */
- if (ptid_equal (inferior_ptid, null_ptid))
- return 0;
-
- return 1;
-}
-
-int
-default_child_has_registers ()
-{
- /* Can't read registers from no inferior. */
- if (ptid_equal (inferior_ptid, null_ptid))
- return 0;
-
- return 1;
-}
-
-int
-default_child_has_execution (ptid_t the_ptid)
-{
- /* If there's no thread selected, then we can't make it run through
- hoops. */
- if (ptid_equal (the_ptid, null_ptid))
- return 0;
-
- return 1;
-}
-
-
int
target_has_all_memory_1 (void)
{
- struct target_ops *t;
-
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
if (t->has_all_memory ())
return 1;
int
target_has_memory_1 (void)
{
- struct target_ops *t;
-
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
if (t->has_memory ())
return 1;
int
target_has_stack_1 (void)
{
- struct target_ops *t;
-
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
if (t->has_stack ())
return 1;
int
target_has_registers_1 (void)
{
- struct target_ops *t;
-
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
if (t->has_registers ())
return 1;
return 0;
}
-int
-target_has_execution_1 (ptid_t the_ptid)
+bool
+target_has_execution_1 (inferior *inf)
{
- struct target_ops *t;
+ for (target_ops *t = inf->top_target ();
+ t != nullptr;
+ t = inf->find_target_beneath (t))
+ if (t->has_execution (inf))
+ return true;
- for (t = target_stack; t != NULL; t = t->beneath)
- if (t->has_execution (the_ptid))
- return 1;
-
- return 0;
+ return false;
}
int
target_has_execution_current (void)
{
- return target_has_execution_1 (inferior_ptid);
+ return target_has_execution_1 (current_inferior ());
}
/* This is used to implement the various target commands. */
static void
open_target (const char *args, int from_tty, struct cmd_list_element *command)
{
- struct target_ops *ops = (struct target_ops *) get_cmd_context (command);
+ auto *ti = static_cast<target_info *> (get_cmd_context (command));
+ target_open_ftype *func = target_factories[ti];
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog, "-> %s->to_open (...)\n",
- ops->shortname ());
+ fprintf_unfiltered (gdb_stdlog, "-> %s->open (...)\n",
+ ti->shortname);
- ops->open (args, from_tty);
+ func (args, from_tty);
if (targetdebug)
- fprintf_unfiltered (gdb_stdlog, "<- %s->to_open (%s, %d)\n",
- ops->shortname (), args, from_tty);
+ fprintf_unfiltered (gdb_stdlog, "<- %s->open (%s, %d)\n",
+ ti->shortname, args, from_tty);
}
-/* Add possible target architecture T to the list and add a new
- command 'target T->shortname ()'. Set COMPLETER as the command's
- completer if not NULL. */
+/* See target.h. */
void
-add_target_with_completer (struct target_ops *t,
- completer_ftype *completer)
+add_target (const target_info &t, target_open_ftype *func,
+ completer_ftype *completer)
{
struct cmd_list_element *c;
- VEC_safe_push (target_ops_p, target_structs, t);
+ auto &func_slot = target_factories[&t];
+ if (func_slot != nullptr)
+ internal_error (__FILE__, __LINE__,
+ _("target already added (\"%s\")."), t.shortname);
+ func_slot = func;
if (targetlist == NULL)
add_prefix_cmd ("target", class_run, target_command, _("\
information on the arguments for a particular protocol, type\n\
`help target ' followed by the protocol name."),
&targetlist, "target ", 0, &cmdlist);
- c = add_cmd (t->shortname (), no_class, t->doc (), &targetlist);
+ c = add_cmd (t.shortname, no_class, t.doc, &targetlist);
+ set_cmd_context (c, (void *) &t);
set_cmd_sfunc (c, open_target);
- set_cmd_context (c, t);
if (completer != NULL)
set_cmd_completer (c, completer);
}
-/* Add a possible target architecture to the list. */
-
-void
-add_target (struct target_ops *t)
-{
- add_target_with_completer (t, NULL);
-}
-
/* See target.h. */
void
-add_deprecated_target_alias (struct target_ops *t, const char *alias)
+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, t->doc (), &targetlist);
+ c = add_cmd (alias, no_class, tinfo.doc, &targetlist);
set_cmd_sfunc (c, open_target);
- set_cmd_context (c, t);
- alt = xstrprintf ("target %s", t->shortname ());
+ set_cmd_context (c, (void *) &tinfo);
+ alt = xstrprintf ("target %s", tinfo.shortname);
deprecate_cmd (c, alt);
}
void
target_kill (void)
{
- target_stack->kill ();
+ current_top_target ()->kill ();
}
void
target_load (const char *arg, int from_tty)
{
target_dcache_invalidate ();
- target_stack->load (arg, from_tty);
+ current_top_target ()->load (arg, from_tty);
}
/* Define it. */
void
target_terminal::init (void)
{
- target_stack->terminal_init ();
+ current_top_target ()->terminal_init ();
m_terminal_state = target_terminal_state::is_ours;
}
if (inf->terminal_state != target_terminal_state::is_inferior)
{
- target_stack->terminal_inferior ();
+ current_top_target ()->terminal_inferior ();
inf->terminal_state = target_terminal_state::is_inferior;
}
{
scoped_restore_current_inferior restore_inferior;
- struct inferior *inf;
- ALL_INFERIORS (inf)
+ for (::inferior *inf : all_inferiors ())
{
if (inf->terminal_state == target_terminal_state::is_ours_for_output)
{
set_current_inferior (inf);
- target_stack->terminal_inferior ();
+ current_top_target ()->terminal_inferior ();
inf->terminal_state = target_terminal_state::is_inferior;
}
}
target_terminal_is_ours_kind (target_terminal_state desired_state)
{
scoped_restore_current_inferior restore_inferior;
- struct inferior *inf;
/* Must do this in two passes. First, have all inferiors save the
current terminal settings. Then, after all inferiors have add a
chance to safely save the terminal settings, restore GDB's
terminal settings. */
- ALL_INFERIORS (inf)
+ for (inferior *inf : all_inferiors ())
{
if (inf->terminal_state == target_terminal_state::is_inferior)
{
set_current_inferior (inf);
- target_stack->terminal_save_inferior ();
+ current_top_target ()->terminal_save_inferior ();
}
}
- ALL_INFERIORS (inf)
+ for (inferior *inf : all_inferiors ())
{
/* Note we don't check is_inferior here like above because we
need to handle 'is_ours_for_output -> is_ours' too. Careful
{
set_current_inferior (inf);
if (desired_state == target_terminal_state::is_ours)
- target_stack->terminal_ours ();
+ current_top_target ()->terminal_ours ();
else if (desired_state == target_terminal_state::is_ours_for_output)
- target_stack->terminal_ours_for_output ();
+ current_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)
{
- target_stack->terminal_info (arg, from_tty);
+ current_top_target ()->terminal_info (arg, from_tty);
}
/* See target.h. */
-int
+bool
target_supports_terminal_ours (void)
{
- return target_stack->supports_terminal_ours ();
+ /* The current top target is the target at the top of the target
+ stack of the current inferior. While normally there's always an
+ inferior, we must check for nullptr here because we can get here
+ very early during startup, before the initial inferior is first
+ created. */
+ inferior *inf = current_inferior ();
+
+ if (inf == nullptr)
+ return false;
+ return inf->top_target ()->supports_terminal_ours ();
}
static void
tcomplain (void)
{
error (_("You can't do that when your target is `%s'"),
- target_stack->shortname ());
+ current_top_target ()->shortname ());
}
void
static ptid_t
default_get_ada_task_ptid (struct target_ops *self, long lwp, long tid)
{
- return ptid_build (ptid_get_pid (inferior_ptid), lwp, tid);
+ return ptid_t (inferior_ptid.pid (), lwp, tid);
}
static enum exec_direction_kind
to_execution_direction must be implemented for reverse async");
}
-/* Push a new target type into the stack of the existing target accessors,
- possibly superseding some of the existing accessors.
-
- Rather than allow an empty stack, we always have the dummy target at
- the bottom stratum, so we can call the function vectors without
- checking them. */
+/* See target.h. */
void
-push_target (struct target_ops *t)
+decref_target (target_ops *t)
{
- struct target_ops **cur;
-
- /* Find the proper stratum to install this target in. */
- for (cur = &target_stack; (*cur) != NULL; cur = &(*cur)->beneath)
+ t->decref ();
+ if (t->refcount () == 0)
{
- if ((int) (t->to_stratum) >= (int) (*cur)->to_stratum)
- break;
+ if (t->stratum () == process_stratum)
+ connection_list_remove (as_process_stratum_target (t));
+ target_close (t);
}
+}
- /* If there's already targets at this stratum, remove them. */
- /* FIXME: cagney/2003-10-15: I think this should be popping all
- targets to CUR, and not just those at this stratum level. */
- while ((*cur) != NULL && t->to_stratum == (*cur)->to_stratum)
- {
- /* There's already something at this stratum level. Close it,
- and un-hook it from the stack. */
- struct target_ops *tmp = (*cur);
+/* See target.h. */
- (*cur) = (*cur)->beneath;
- tmp->beneath = NULL;
- target_close (tmp);
- }
+void
+target_stack::push (target_ops *t)
+{
+ t->incref ();
+
+ 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. */
- /* We have removed all targets in our stratum, now add the new one. */
- t->beneath = (*cur);
- (*cur) = t;
+ if (m_stack[stratum] != NULL)
+ unpush (m_stack[stratum]);
+
+ /* Now add the new one. */
+ m_stack[stratum] = t;
+
+ 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 ();
}
-/* Remove a target_ops vector from the stack, wherever it may be.
- Return how many times it was removed (0 or 1). */
+/* See target.h. */
int
unpush_target (struct target_ops *t)
{
- struct target_ops **cur;
- struct target_ops *tmp;
+ return current_inferior ()->unpush_target (t);
+}
+
+/* See target.h. */
- if (t->to_stratum == dummy_stratum)
+bool
+target_stack::unpush (target_ops *t)
+{
+ gdb_assert (t != NULL);
+
+ strata stratum = t->stratum ();
+
+ if (stratum == dummy_stratum)
internal_error (__FILE__, __LINE__,
_("Attempt to unpush the dummy target"));
- /* Look for the specified target. Note that we assume that a target
- can only occur once in the target stack. */
+ /* Look for the specified target. Note that a target can only occur
+ once in the target stack. */
- for (cur = &target_stack; (*cur) != NULL; cur = &(*cur)->beneath)
+ if (m_stack[stratum] != t)
{
- if ((*cur) == t)
- break;
+ /* If T wasn't pushed, quit. Only open targets should be
+ closed. */
+ return false;
}
- /* If we don't find target_ops, quit. Only open targets should be
- closed. */
- if ((*cur) == NULL)
- return 0;
-
/* Unchain the target. */
- tmp = (*cur);
- (*cur) = (*cur)->beneath;
- tmp->beneath = NULL;
+ m_stack[stratum] = NULL;
- /* Finally close the target. Note we do this after unchaining, so
- any target method calls from within the target_close
- implementation don't end up in T anymore. */
- target_close (t);
+ if (m_top == stratum)
+ m_top = t->beneath ()->stratum ();
- return 1;
+ /* 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. */
void
pop_all_targets_above (enum strata above_stratum)
{
- while ((int) (target_stack->to_stratum) > (int) above_stratum)
- unpush_target_and_assert (target_stack);
+ while ((int) (current_top_target ()->stratum ()) > (int) above_stratum)
+ unpush_target_and_assert (current_top_target ());
}
/* See target.h. */
void
pop_all_targets_at_and_above (enum strata stratum)
{
- while ((int) (target_stack->to_stratum) >= (int) stratum)
- unpush_target_and_assert (target_stack);
+ while ((int) (current_top_target ()->stratum ()) >= (int) stratum)
+ unpush_target_and_assert (current_top_target ());
}
void
pop_all_targets_above (dummy_stratum);
}
-/* Return 1 if T is now pushed in the target stack. Return 0 otherwise. */
+/* Return true if T is now pushed in the current inferior's target
+ stack. Return false otherwise. */
-int
-target_is_pushed (struct target_ops *t)
+bool
+target_is_pushed (target_ops *t)
{
- struct target_ops *cur;
-
- for (cur = target_stack; cur != NULL; cur = cur->beneath)
- if (cur == t)
- return 1;
-
- return 0;
+ return current_inferior ()->target_is_pushed (t);
}
/* 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 = target_stack;
+ struct target_ops *target = current_top_target ();
+ struct gdbarch *gdbarch = target_gdbarch ();
- if (gdbarch_fetch_tls_load_module_address_p (target_gdbarch ()))
+ if (gdbarch_fetch_tls_load_module_address_p (gdbarch))
{
ptid_t ptid = inferior_ptid;
- TRY
+ try
{
CORE_ADDR lm_addr;
/* Fetch the load module address for this objfile. */
- lm_addr = gdbarch_fetch_tls_load_module_address (target_gdbarch (),
+ lm_addr = gdbarch_fetch_tls_load_module_address (gdbarch,
objfile);
- addr = target->get_thread_local_address (ptid, lm_addr, offset);
+ if (gdbarch_get_thread_local_address_p (gdbarch))
+ addr = gdbarch_get_thread_local_address (gdbarch, ptid, lm_addr,
+ offset);
+ else
+ 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. */
- CATCH (ex, RETURN_MASK_ALL)
+ catch (const gdb_exception &ex)
{
int objfile_is_library = (objfile->flags & OBJF_SHARED);
" thread-local variables in\n"
"the shared library `%s'\n"
"for %s"),
- objfile_name (objfile), target_pid_to_str (ptid));
+ 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"),
- objfile_name (objfile), target_pid_to_str (ptid));
+ 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"),
- target_pid_to_str (ptid),
- objfile_name (objfile), ex.message);
+ 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"),
- target_pid_to_str (ptid),
- objfile_name (objfile), ex.message);
+ target_pid_to_str (ptid).c_str (),
+ objfile_name (objfile), ex.what ());
break;
default:
- throw_exception (ex);
+ throw;
break;
}
}
- END_CATCH
}
- /* It wouldn't be wrong here to try a gdbarch method, too; finding
- TLS is an ABI-specific thing. But we don't do that yet. */
else
error (_("Cannot find thread-local variables on this target"));
if (ops->has_all_memory ())
break;
- ops = ops->beneath;
+ ops = ops->beneath ();
}
while (ops != NULL);
first, so that if it fails, we don't write to the cache contents
that never made it to the target. */
if (writebuf != NULL
- && !ptid_equal (inferior_ptid, null_ptid)
+ && inferior_ptid != null_ptid
&& target_dcache_init_p ()
&& (stack_cache_enabled_p () || code_cache_enabled_p ()))
{
secp = target_section_by_addr (ops, memaddr);
if (secp != NULL
- && (bfd_get_section_flags (secp->the_bfd_section->owner,
- secp->the_bfd_section)
- & SEC_READONLY))
+ && (bfd_section_flags (secp->the_bfd_section) & SEC_READONLY))
{
table = target_get_section_table (ops);
return section_table_xfer_memory_partial (readbuf, writebuf,
®ion))
return TARGET_XFER_E_IO;
- if (!ptid_equal (inferior_ptid, null_ptid))
- inf = find_inferior_ptid (inferior_ptid);
+ if (inferior_ptid != null_ptid)
+ inf = current_inferior ();
else
inf = NULL;
int
target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
{
- if (target_read (target_stack, TARGET_OBJECT_MEMORY, NULL,
+ if (target_read (current_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 (target_stack, TARGET_OBJECT_RAW_MEMORY, NULL,
+ if (target_read (current_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 (target_stack, TARGET_OBJECT_STACK_MEMORY, NULL,
+ if (target_read (current_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 (target_stack, TARGET_OBJECT_CODE_MEMORY, NULL,
+ if (target_read (current_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 (target_stack, TARGET_OBJECT_MEMORY, NULL,
+ if (target_write (current_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 (target_stack, TARGET_OBJECT_RAW_MEMORY, NULL,
+ if (target_write (current_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 = target_stack->memory_map ();
+ std::vector<mem_region> result = current_top_target ()->memory_map ();
if (result.empty ())
return result;
void
target_flash_erase (ULONGEST address, LONGEST length)
{
- target_stack->flash_erase (address, length);
+ current_top_target ()->flash_erase (address, length);
}
void
target_flash_done (void)
{
- target_stack->flash_done ();
+ current_top_target ()->flash_done ();
}
static void
if (!buf)
return {};
- if (buf->back () != '\0')
+ if (buf->empty () || buf->back () != '\0')
buf->push_back ('\0');
/* Check for embedded NUL bytes; but allow trailing NULs. */
return 1;
}
- return target_stack->insert_breakpoint (gdbarch, bp_tgt);
+ return current_top_target ()->insert_breakpoint (gdbarch, bp_tgt);
}
/* See target.h. */
return 1;
}
- return target_stack->remove_breakpoint (gdbarch, bp_tgt, reason);
+ return current_top_target ()->remove_breakpoint (gdbarch, bp_tgt, reason);
}
static void
info_target_command (const char *args, int from_tty)
{
- struct target_ops *t;
int has_all_mem = 0;
if (symfile_objfile != NULL)
printf_unfiltered (_("Symbols from \"%s\".\n"),
objfile_name (symfile_objfile));
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
{
if (!t->has_memory ())
continue;
- if ((int) (t->to_stratum) <= (int) dummy_stratum)
+ if ((int) (t->stratum ()) <= (int) dummy_stratum)
continue;
if (has_all_mem)
printf_unfiltered (_("\tWhile running this, "
agent_capability_invalidate ();
}
-/* Callback for iterate_over_inferiors. Gets rid of the given
- inferior. */
-
-static int
-dispose_inferior (struct inferior *inf, void *args)
-{
- struct thread_info *thread;
-
- thread = any_thread_of_process (inf->pid);
- if (thread)
- {
- switch_to_thread (thread->ptid);
-
- /* Core inferiors actually should be detached, not killed. */
- if (target_has_execution)
- target_kill ();
- else
- target_detach (inf, 0);
- }
-
- return 0;
-}
-
/* This is to be called by the open routine before it does
anything. */
{
dont_repeat ();
- if (have_inferiors ())
+ if (current_inferior ()->pid != 0)
{
if (!from_tty
- || !have_live_inferiors ()
+ || !target_has_execution
|| query (_("A program is being debugged already. Kill it? ")))
- iterate_over_inferiors (dispose_inferior, NULL);
+ {
+ /* Core inferiors actually should be detached, not
+ killed. */
+ if (target_has_execution)
+ target_kill ();
+ else
+ target_detach (current_inferior (), 0);
+ }
else
error (_("Program not killed."));
}
void
target_detach (inferior *inf, int from_tty)
{
+ /* 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. */
+ ptid_t save_pid_ptid = ptid_t (inf->pid);
+
/* As long as some to_detach implementations rely on the current_inferior
(either directly, or indirectly, like through target_gdbarch or by
reading memory), INF needs to be the current inferior. When that
;
else
/* If we're in breakpoints-always-inserted mode, have to remove
- them before detaching. */
- remove_breakpoints_pid (ptid_get_pid (inferior_ptid));
+ breakpoints before detaching. */
+ remove_breakpoints_inf (current_inferior ());
prepare_for_detach ();
- target_stack->detach (inf, from_tty);
+ /* 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);
+
+ process_stratum_target *proc_target
+ = as_process_stratum_target (proc_target_ref.get ());
+
+ registers_changed_ptid (proc_target, save_pid_ptid);
+
+ /* We have to ensure we have no frame cache left. Normally,
+ registers_changed_ptid (save_pid_ptid) calls reinit_frame_cache when
+ inferior_ptid matches save_pid_ptid, but in our case, it does not
+ call it, as inferior_ptid has been reset. */
+ reinit_frame_cache ();
}
void
disconnecting. */
remove_breakpoints ();
- target_stack->disconnect (args, from_tty);
+ current_top_target ()->disconnect (args, from_tty);
}
/* See target/target.h. */
ptid_t
target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
{
- return target_stack->wait (ptid, status, options);
+ return current_top_target ()->wait (ptid, status, options);
}
/* See target.h. */
return minus_one_ptid;
}
-const char *
+std::string
target_pid_to_str (ptid_t ptid)
{
- return target_stack->pid_to_str (ptid);
+ return current_top_target ()->pid_to_str (ptid);
}
const char *
target_thread_name (struct thread_info *info)
{
- return target_stack->thread_name (info);
+ gdb_assert (info->inf == current_inferior ());
+
+ return current_top_target ()->thread_name (info);
}
struct thread_info *
int handle_len,
struct inferior *inf)
{
- return target_stack->thread_handle_to_thread_info (thread_handle,
+ return current_top_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);
+}
+
void
target_resume (ptid_t ptid, int step, enum gdb_signal signal)
{
+ process_stratum_target *curr_target = current_inferior ()->process_target ();
+
target_dcache_invalidate ();
- target_stack->resume (ptid, step, signal);
+ current_top_target ()->resume (ptid, step, signal);
- registers_changed_ptid (ptid);
+ registers_changed_ptid (curr_target, ptid);
/* We only set the internal executing state here. The user/frontend
- running state is set at a higher level. */
- set_executing (ptid, 1);
- clear_inline_frame_state (ptid);
+ running state is set at a higher level. This also clears the
+ thread's stop_pc as side effect. */
+ set_executing (curr_target, ptid, 1);
+ clear_inline_frame_state (curr_target, ptid);
}
/* If true, target_commit_resume is a nop. */
if (defer_target_commit_resume)
return;
- target_stack->commit_resume ();
+ current_top_target ()->commit_resume ();
}
/* See target.h. */
}
void
-target_pass_signals (int numsigs, unsigned char *pass_signals)
+target_pass_signals (gdb::array_view<const unsigned char> pass_signals)
{
- target_stack->pass_signals (numsigs, pass_signals);
+ current_top_target ()->pass_signals (pass_signals);
}
void
-target_program_signals (int numsigs, unsigned char *program_signals)
+target_program_signals (gdb::array_view<const unsigned char> program_signals)
{
- target_stack->program_signals (numsigs, program_signals);
+ current_top_target ()->program_signals (program_signals);
}
static int
int
target_follow_fork (int follow_child, int detach_fork)
{
- return target_stack->follow_fork (follow_child, detach_fork);
+ return current_top_target ()->follow_fork (follow_child, detach_fork);
}
/* Target wrapper for follow exec hook. */
void
-target_follow_exec (struct inferior *inf, char *execd_pathname)
+target_follow_exec (struct inferior *inf, const char *execd_pathname)
{
- target_stack->follow_exec (inf, execd_pathname);
+ current_top_target ()->follow_exec (inf, execd_pathname);
}
static void
void
target_mourn_inferior (ptid_t ptid)
{
- gdb_assert (ptid_equal (ptid, inferior_ptid));
- target_stack->mourn_inferior ();
+ gdb_assert (ptid == inferior_ptid);
+ current_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
CORE_ADDR *found_addrp)
{
/* Start over from the top of the target stack. */
- return simple_search_memory (target_stack,
+ return simple_search_memory (current_top_target (),
start_addr, search_space_len,
pattern, pattern_len, found_addrp);
}
const gdb_byte *pattern, ULONGEST pattern_len,
CORE_ADDR *found_addrp)
{
- return target_stack->search_memory (start_addr, search_space_len,
+ return current_top_target ()->search_memory (start_addr, search_space_len,
pattern, pattern_len, found_addrp);
}
void
target_require_runnable (void)
{
- struct target_ops *t;
-
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_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
/* Do not worry about targets at certain strata that can not
create inferiors. Assume they will be pushed again if
necessary, and continue to the process_stratum. */
- if (t->to_stratum > process_stratum)
+ if (t->stratum () > process_stratum)
continue;
error (_("The \"%s\" target does not support \"run\". "
/* Whether GDB is allowed to fall back to the default run target for
"run", "attach", etc. when no target is connected yet. */
-static int auto_connect_native_target = 1;
+static bool auto_connect_native_target = true;
static void
show_auto_connect_native_target (struct ui_file *file, int from_tty,
value);
}
+/* A pointer to the target that can respond to "run" or "attach".
+ Native targets are always singletons and instantiated early at GDB
+ startup. */
+static target_ops *the_native_target;
+
+/* See target.h. */
+
+void
+set_native_target (target_ops *target)
+{
+ if (the_native_target != NULL)
+ internal_error (__FILE__, __LINE__,
+ _("native target already set (\"%s\")."),
+ the_native_target->longname ());
+
+ the_native_target = target;
+}
+
+/* See target.h. */
+
+target_ops *
+get_native_target ()
+{
+ return the_native_target;
+}
+
/* Look through the list of possible targets for a target that can
execute a run or attach command without any other data. This is
used to locate the default process stratum.
static struct target_ops *
find_default_run_target (const char *do_mesg)
{
- struct target_ops *runable = NULL;
+ if (auto_connect_native_target && the_native_target != NULL)
+ return the_native_target;
- if (auto_connect_native_target)
- {
- struct target_ops *t;
- int count = 0;
- int i;
-
- for (i = 0; VEC_iterate (target_ops_p, target_structs, i, t); ++i)
- {
- if (t->can_run ())
- {
- runable = t;
- ++count;
- }
- }
-
- if (count != 1)
- runable = NULL;
- }
-
- if (runable == NULL)
- {
- if (do_mesg)
- error (_("Don't know how to %s. Try \"help target\"."), do_mesg);
- else
- return NULL;
- }
-
- return runable;
+ if (do_mesg != NULL)
+ error (_("Don't know how to %s. Try \"help target\"."), do_mesg);
+ return NULL;
}
/* See target.h. */
struct target_ops *
find_attach_target (void)
{
- struct target_ops *t;
-
/* If a target on the current stack can attach, use it. */
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
{
if (t->can_attach ())
- break;
+ return t;
}
/* Otherwise, use the default run target for attaching. */
- if (t == NULL)
- t = find_default_run_target ("attach");
-
- return t;
+ return find_default_run_target ("attach");
}
/* See target.h. */
struct target_ops *
find_run_target (void)
{
- struct target_ops *t;
-
/* If a target on the current stack can run, use it. */
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
{
if (t->can_create_inferior ())
- break;
+ return t;
}
/* Otherwise, use the default run target. */
- if (t == NULL)
- t = find_default_run_target ("run");
-
- return t;
+ return find_default_run_target ("run");
}
bool
if (t == NULL)
t = find_default_run_target (NULL);
- for (; t != NULL; t = t->beneath)
+ for (; t != NULL; t = t->beneath ())
{
if (t->info_proc (args, what))
{
int
target_supports_disable_randomization (void)
{
- return target_stack->supports_disable_randomization ();
+ return current_top_target ()->supports_disable_randomization ();
}
/* See target/target.h. */
int
target_supports_multi_process (void)
{
- return target_stack->supports_multi_process ();
+ return current_top_target ()->supports_multi_process ();
}
/* See target.h. */
return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type);
}
-static struct address_space *
-default_thread_address_space (struct target_ops *self, ptid_t ptid)
-{
- struct inferior *inf;
-
- /* Fall-back to the "main" address space of the inferior. */
- inf = find_inferior_ptid (ptid);
-
- if (inf == NULL || inf->aspace == NULL)
- internal_error (__FILE__, __LINE__,
- _("Can't determine the current "
- "address space of thread %s\n"),
- target_pid_to_str (ptid));
-
- return inf->aspace;
-}
-
/* Determine the current address space of thread PTID. */
struct address_space *
{
struct address_space *aspace;
- aspace = target_stack->thread_address_space (ptid);
+ aspace = current_top_target ()->thread_address_space (ptid);
gdb_assert (aspace != NULL);
return aspace;
}
-void
-target_ops::open (const char *, int)
+/* See target.h. */
+
+target_ops *
+target_ops::beneath () const
{
- gdb_assert_not_reached ("target_ops::open called");
+ return current_inferior ()->find_target_beneath (this);
}
void
gdb_assert_not_reached ("target_ops::create_inferior called");
}
-int
+bool
target_ops::can_run ()
{
- return 0;
+ return false;
}
int
target_can_run ()
{
- struct target_ops *t;
-
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
{
if (t->can_run ())
return 1;
int flags, int mode, int warn_if_slow,
int *target_errno)
{
- struct target_ops *t;
-
- for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
{
int fd = t->fileio_open (inf, filename, flags, mode,
warn_if_slow, target_errno);
target_fileio_unlink (struct inferior *inf, const char *filename,
int *target_errno)
{
- struct target_ops *t;
-
- for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
{
int ret = t->fileio_unlink (inf, filename, target_errno);
target_fileio_readlink (struct inferior *inf, const char *filename,
int *target_errno)
{
- struct target_ops *t;
-
- for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
{
gdb::optional<std::string> ret
= t->fileio_readlink (inf, filename, target_errno);
return gdb::unique_xmalloc_ptr<char> (nullptr);
if (transferred == 0)
- return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
+ return make_unique_xstrdup ("");
bufstr[transferred] = 0;
return addr >= start && addr < start + length;
}
-static struct gdbarch *
-default_thread_architecture (struct target_ops *ops, ptid_t ptid)
-{
- inferior *inf = find_inferior_ptid (ptid);
- gdb_assert (inf != NULL);
- return inf->gdbarch;
-}
-
-/*
- * Find the next target down the stack from the specified target.
- */
+/* See target.h. */
-struct target_ops *
-find_target_beneath (struct target_ops *t)
+target_ops *
+target_stack::find_beneath (const target_ops *t) const
{
- return t->beneath;
+ /* 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];
+
+ return NULL;
}
/* See target.h. */
struct target_ops *
find_target_at (enum strata stratum)
{
- struct target_ops *t;
-
- for (t = target_stack; t != NULL; t = t->beneath)
- if (t->to_stratum == stratum)
- return t;
-
- return NULL;
+ return current_inferior ()->target_at (stratum);
}
\f
if (exec_file == NULL)
exec_file = "";
- pid = ptid_get_pid (inferior_ptid);
+ pid = inferior_ptid.pid ();
printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
- target_pid_to_str (pid_to_ptid (pid)));
- gdb_flush (gdb_stdout);
+ target_pid_to_str (ptid_t (pid)).c_str ());
}
/* The inferior process has died. Long live the inferior! */
void
generic_mourn_inferior (void)
{
- ptid_t ptid;
+ inferior *inf = current_inferior ();
- ptid = inferior_ptid;
inferior_ptid = null_ptid;
/* Mark breakpoints uninserted in case something tries to delete a
fail, since the inferior is long gone). */
mark_breakpoints_out ();
- if (!ptid_equal (ptid, null_ptid))
- {
- int pid = ptid_get_pid (ptid);
- exit_inferior (pid);
- }
+ if (inf->pid != 0)
+ exit_inferior (inf);
/* Note this wipes step-resume breakpoints, so needs to be done
after exit_inferior, which ends up referencing the step-resume
/* Convert a normal process ID to a string. Returns the string in a
static buffer. */
-const char *
+std::string
normal_pid_to_str (ptid_t ptid)
{
- static char buf[32];
-
- xsnprintf (buf, sizeof buf, "process %d", ptid_get_pid (ptid));
- return buf;
+ return string_printf ("process %d", ptid.pid ());
}
-static const char *
+static std::string
default_pid_to_str (struct target_ops *ops, ptid_t ptid)
{
return normal_pid_to_str (ptid);
#include "target-delegates.c"
+/* The initial current target, so that there is always a semi-valid
+ current target. */
-dummy_target::dummy_target ()
-{
- to_stratum = dummy_stratum;
-}
+static dummy_target the_dummy_target;
-const char *
-dummy_target::shortname ()
-{
- return "None";
-}
+/* See target.h. */
-const char *
-dummy_target::longname ()
+target_ops *
+get_dummy_target ()
{
- return _("None");
+ return &the_dummy_target;
}
-const char *
-dummy_target::doc ()
-{
- return "";
-}
+static const target_info dummy_target_info = {
+ "None",
+ N_("None"),
+ ""
+};
-debug_target::debug_target ()
+strata
+dummy_target::stratum () const
{
- to_stratum = debug_stratum;
+ return dummy_stratum;
}
-const char *
-debug_target::shortname ()
+strata
+debug_target::stratum () const
{
- return beneath->shortname ();
+ return debug_stratum;
}
-const char *
-debug_target::longname ()
+const target_info &
+dummy_target::info () const
{
- return beneath->longname ();
+ return dummy_target_info;
}
-const char *
-debug_target::doc ()
+const target_info &
+debug_target::info () const
{
- return beneath->doc ();
+ return beneath ()->info ();
}
\f
int
target_thread_alive (ptid_t ptid)
{
- return target_stack->thread_alive (ptid);
+ return current_top_target ()->thread_alive (ptid);
}
void
target_update_thread_list (void)
{
- target_stack->update_thread_list ();
+ current_top_target ()->update_thread_list ();
}
void
return;
}
- target_stack->stop (ptid);
+ current_top_target ()->stop (ptid);
}
void
return;
}
- target_stack->interrupt ();
+ current_top_target ()->interrupt ();
}
/* See target.h. */
void
target_pass_ctrlc (void)
{
- target_stack->pass_ctrlc ();
+ /* Pass the Ctrl-C to the first target that has a thread
+ running. */
+ for (inferior *inf : all_inferiors ())
+ {
+ target_ops *proc_target = inf->process_target ();
+ if (proc_target == NULL)
+ continue;
+
+ for (thread_info *thr : inf->threads ())
+ {
+ /* A thread can be THREAD_STOPPED and executing, while
+ running an infcall. */
+ if (thr->state == THREAD_RUNNING || thr->executing)
+ {
+ /* We can get here quite deep in target layers. Avoid
+ switching thread context or anything that would
+ communicate with the target (e.g., to fetch
+ registers), or flushing e.g., the frame cache. We
+ just switch inferior in order to be able to call
+ through the target_stack. */
+ scoped_restore_current_inferior restore_inferior;
+ set_current_inferior (inf);
+ current_top_target ()->pass_ctrlc ();
+ return;
+ }
+ }
+ }
}
/* See target.h. */
target_stop_and_wait (ptid_t ptid)
{
struct target_waitstatus status;
- int was_non_stop = non_stop;
+ bool was_non_stop = non_stop;
- non_stop = 1;
+ non_stop = true;
target_stop (ptid);
memset (&status, 0, sizeof (status));
target_resume (ptid, 0, signal);
}
-/* Concatenate ELEM to LIST, a comma separate list, and return the
- result. The LIST incoming argument is released. */
+/* Concatenate ELEM to LIST, a comma-separated list. */
-static char *
-str_comma_list_concat_elem (char *list, const char *elem)
+static void
+str_comma_list_concat_elem (std::string *list, const char *elem)
{
- if (list == NULL)
- return xstrdup (elem);
- else
- return reconcat (list, list, ", ", elem, (char *) NULL);
+ if (!list->empty ())
+ list->append (", ");
+
+ list->append (elem);
}
/* Helper for target_options_to_string. If OPT is present in
TARGET_OPTIONS, append the OPT_STR (string version of OPT) in RET.
- Returns the new resulting string. OPT is removed from
- TARGET_OPTIONS. */
+ OPT is removed from TARGET_OPTIONS. */
-static char *
-do_option (int *target_options, char *ret,
+static void
+do_option (int *target_options, std::string *ret,
int opt, const char *opt_str)
{
if ((*target_options & opt) != 0)
{
- ret = str_comma_list_concat_elem (ret, opt_str);
+ str_comma_list_concat_elem (ret, opt_str);
*target_options &= ~opt;
}
-
- return ret;
}
-char *
+/* See target.h. */
+
+std::string
target_options_to_string (int target_options)
{
- char *ret = NULL;
+ std::string ret;
#define DO_TARG_OPTION(OPT) \
- ret = do_option (&target_options, ret, OPT, #OPT)
+ do_option (&target_options, &ret, OPT, #OPT)
DO_TARG_OPTION (TARGET_WNOHANG);
if (target_options != 0)
- ret = str_comma_list_concat_elem (ret, "unknown???");
+ str_comma_list_concat_elem (&ret, "unknown???");
- if (ret == NULL)
- ret = xstrdup ("");
return ret;
}
void
target_fetch_registers (struct regcache *regcache, int regno)
{
- target_stack->fetch_registers (regcache, regno);
+ current_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);
- target_stack->store_registers (regcache, regno);
+ current_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 target_stack->core_of_thread (ptid);
+ return current_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 (target_stack,
+ return simple_verify_memory (current_top_target (),
data, memaddr, size);
}
int
target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
{
- return target_stack->verify_memory (data, memaddr, size);
+ return current_top_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 target_stack->insert_mask_watchpoint (addr, mask, rw);
+ return current_top_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 target_stack->remove_mask_watchpoint (addr, mask, rw);
+ return current_top_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 target_stack->masked_watch_num_registers (addr, mask);
+ return current_top_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 target_stack->ranged_break_num_registers ();
+ return current_top_target ()->ranged_break_num_registers ();
}
/* See target.h. */
struct btrace_target_info *
target_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
{
- return target_stack->enable_btrace (ptid, conf);
+ return current_top_target ()->enable_btrace (ptid, conf);
}
/* See target.h. */
void
target_disable_btrace (struct btrace_target_info *btinfo)
{
- target_stack->disable_btrace (btinfo);
+ current_top_target ()->disable_btrace (btinfo);
}
/* See target.h. */
void
target_teardown_btrace (struct btrace_target_info *btinfo)
{
- target_stack->teardown_btrace (btinfo);
+ current_top_target ()->teardown_btrace (btinfo);
}
/* See target.h. */
struct btrace_target_info *btinfo,
enum btrace_read_type type)
{
- return target_stack->read_btrace (btrace, btinfo, type);
+ return current_top_target ()->read_btrace (btrace, btinfo, type);
}
/* See target.h. */
const struct btrace_config *
target_btrace_conf (const struct btrace_target_info *btinfo)
{
- return target_stack->btrace_conf (btinfo);
+ return current_top_target ()->btrace_conf (btinfo);
}
/* See target.h. */
void
target_stop_recording (void)
{
- target_stack->stop_recording ();
+ current_top_target ()->stop_recording ();
}
/* See target.h. */
void
target_save_record (const char *filename)
{
- target_stack->save_record (filename);
+ current_top_target ()->save_record (filename);
}
/* See target.h. */
int
target_supports_delete_record ()
{
- return target_stack->supports_delete_record ();
+ return current_top_target ()->supports_delete_record ();
}
/* See target.h. */
void
target_delete_record (void)
{
- target_stack->delete_record ();
+ current_top_target ()->delete_record ();
}
/* See target.h. */
enum record_method
target_record_method (ptid_t ptid)
{
- return target_stack->record_method (ptid);
+ return current_top_target ()->record_method (ptid);
}
/* See target.h. */
int
target_record_is_replaying (ptid_t ptid)
{
- return target_stack->record_is_replaying (ptid);
+ return current_top_target ()->record_is_replaying (ptid);
}
/* See target.h. */
int
target_record_will_replay (ptid_t ptid, int dir)
{
- return target_stack->record_will_replay (ptid, dir);
+ return current_top_target ()->record_will_replay (ptid, dir);
}
/* See target.h. */
void
target_record_stop_replaying (void)
{
- target_stack->record_stop_replaying ();
+ current_top_target ()->record_stop_replaying ();
}
/* See target.h. */
void
target_goto_record_begin (void)
{
- target_stack->goto_record_begin ();
+ current_top_target ()->goto_record_begin ();
}
/* See target.h. */
void
target_goto_record_end (void)
{
- target_stack->goto_record_end ();
+ current_top_target ()->goto_record_end ();
}
/* See target.h. */
void
target_goto_record (ULONGEST insn)
{
- target_stack->goto_record (insn);
+ current_top_target ()->goto_record (insn);
}
/* See target.h. */
void
target_insn_history (int size, gdb_disassembly_flags flags)
{
- target_stack->insn_history (size, flags);
+ current_top_target ()->insn_history (size, flags);
}
/* See target.h. */
target_insn_history_from (ULONGEST from, int size,
gdb_disassembly_flags flags)
{
- target_stack->insn_history_from (from, size, flags);
+ current_top_target ()->insn_history_from (from, size, flags);
}
/* See target.h. */
target_insn_history_range (ULONGEST begin, ULONGEST end,
gdb_disassembly_flags flags)
{
- target_stack->insn_history_range (begin, end, flags);
+ current_top_target ()->insn_history_range (begin, end, flags);
}
/* See target.h. */
void
target_call_history (int size, record_print_flags flags)
{
- target_stack->call_history (size, flags);
+ current_top_target ()->call_history (size, flags);
}
/* See target.h. */
void
target_call_history_from (ULONGEST begin, int size, record_print_flags flags)
{
- target_stack->call_history_from (begin, size, flags);
+ current_top_target ()->call_history_from (begin, size, flags);
}
/* See target.h. */
void
target_call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flags)
{
- target_stack->call_history_range (begin, end, flags);
+ current_top_target ()->call_history_range (begin, end, flags);
}
/* See target.h. */
const struct frame_unwind *
target_get_unwinder (void)
{
- return target_stack->get_unwinder ();
+ return current_top_target ()->get_unwinder ();
}
/* See target.h. */
const struct frame_unwind *
target_get_tailcall_unwinder (void)
{
- return target_stack->get_tailcall_unwinder ();
+ return current_top_target ()->get_tailcall_unwinder ();
}
/* See target.h. */
void
target_prepare_to_generate_core (void)
{
- target_stack->prepare_to_generate_core ();
+ current_top_target ()->prepare_to_generate_core ();
}
/* See target.h. */
void
target_done_generating_core (void)
{
- target_stack->done_generating_core ();
+ current_top_target ()->done_generating_core ();
}
\f
ui_out_emit_tuple tuple_emitter (current_uiout, "erased-regions");
current_uiout->message (_("Erasing flash memory region at address "));
- current_uiout->field_fmt ("address", "%s", paddress (gdbarch, m.lo));
+ current_uiout->field_core_addr ("address", gdbarch, m.lo);
current_uiout->message (", size = ");
- current_uiout->field_fmt ("size", "%s", hex_string (m.hi - m.lo));
+ current_uiout->field_string ("size", hex_string (m.hi - m.lo));
current_uiout->message ("\n");
}
}
static void
maintenance_print_target_stack (const char *cmd, int from_tty)
{
- struct target_ops *t;
-
printf_filtered (_("The current target stack is:\n"));
- for (t = target_stack; t != NULL; t = t->beneath)
+ for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
{
- if (t->to_stratum == debug_stratum)
+ if (t->stratum () == debug_stratum)
continue;
printf_filtered (" - %s (%s)\n", t->shortname (), t->longname ());
}
target_async (int enable)
{
infrun_async (enable);
- target_stack->async (enable);
+ current_top_target ()->async (enable);
}
/* See target.h. */
void
target_thread_events (int enable)
{
- target_stack->thread_events (enable);
+ current_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. */
-int target_async_permitted = 1;
+bool target_async_permitted = true;
/* The set command writes to this variable. If the inferior is
executing, target_async_permitted is *not* updated. */
-static int target_async_permitted_1 = 1;
+static bool target_async_permitted_1 = true;
static void
maint_set_target_async_command (const char *args, int from_tty,
static int
target_always_non_stop_p (void)
{
- return target_stack->always_non_stop_p ();
+ return current_top_target ()->always_non_stop_p ();
}
/* See target.h. */
/* Temporary copies of permission settings. */
-static int may_write_registers_1 = 1;
-static int may_write_memory_1 = 1;
-static int may_insert_breakpoints_1 = 1;
-static int may_insert_tracepoints_1 = 1;
-static int may_insert_fast_tracepoints_1 = 1;
-static int may_stop_1 = 1;
+static bool may_write_registers_1 = true;
+static bool may_write_memory_1 = true;
+static bool may_insert_breakpoints_1 = true;
+static bool may_insert_tracepoints_1 = true;
+static bool may_insert_fast_tracepoints_1 = true;
+static bool may_stop_1 = true;
/* Make the user-set values match the real values again. */
}
void
-initialize_targets (void)
+_initialize_target ()
{
- the_dummy_target = new dummy_target ();
- push_target (the_dummy_target);
-
the_debug_target = new debug_target ();
add_info ("target", info_target_command, targ_desc);