X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ftarget.c;h=f6058451d654351781106283138dc42e6860a54e;hb=121b3efd49f98e4049281b3ba7a258e650e40b38;hp=022da5919a6fd463f75b64f382192cfec02034dc;hpb=f6ac5f3d63e03a81c4ff3749aba234961cc9090e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/target.c b/gdb/target.c index 022da5919a..f6058451d6 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1,6 +1,6 @@ /* 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. @@ -40,15 +40,16 @@ #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 -#include "byte-vector.h" +#include "gdbsupport/byte-vector.h" #include "terminal.h" -#include +#include +#include "target-connection.h" static void generic_tls_error (void) ATTRIBUTE_NORETURN; @@ -81,16 +82,10 @@ static int default_verify_memory (struct target_ops *self, 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); @@ -98,36 +93,42 @@ static int dummy_find_memory_regions (struct target_ops *self, 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 + 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. */ @@ -136,19 +137,19 @@ 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 - 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. */ @@ -179,66 +180,10 @@ target_command (const char *arg, int from_tty) 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; @@ -248,9 +193,7 @@ target_has_all_memory_1 (void) 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; @@ -260,9 +203,7 @@ target_has_memory_1 (void) 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; @@ -272,31 +213,29 @@ target_has_stack_1 (void) 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. */ @@ -304,30 +243,33 @@ target_has_execution_current (void) 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 (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, _("\ @@ -337,35 +279,27 @@ 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); - 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); } @@ -374,14 +308,14 @@ add_deprecated_target_alias (struct target_ops *t, const char *alias) 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. */ @@ -394,7 +328,7 @@ target_terminal_state target_terminal::m_terminal_state void target_terminal::init (void) { - target_stack->terminal_init (); + current_top_target ()->terminal_init (); m_terminal_state = target_terminal_state::is_ours; } @@ -425,7 +359,7 @@ target_terminal::inferior (void) 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; } @@ -454,14 +388,13 @@ target_terminal::restore_inferior (void) { 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; } } @@ -482,23 +415,22 @@ static void 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 @@ -509,9 +441,9 @@ target_terminal_is_ours_kind (target_terminal_state desired_state) { 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; @@ -560,22 +492,31 @@ target_terminal::ours_for_output () 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 @@ -599,7 +540,7 @@ default_terminal_info (struct target_ops *self, const char *args, int from_tty) 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 @@ -614,82 +555,107 @@ default_execution_direction (struct target_ops *self) 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. */ @@ -710,8 +676,8 @@ unpush_target_and_assert (struct target_ops *target) 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. */ @@ -719,8 +685,8 @@ pop_all_targets_above (enum strata above_stratum) 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 @@ -729,18 +695,13 @@ pop_all_targets (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. */ @@ -758,25 +719,30 @@ CORE_ADDR 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); @@ -800,35 +766,34 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset) " 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")); @@ -1033,7 +998,7 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf, if (ops->has_all_memory ()) break; - ops = ops->beneath; + ops = ops->beneath (); } while (ops != NULL); @@ -1043,7 +1008,7 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf, 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 ())) { @@ -1099,9 +1064,7 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, 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, @@ -1118,8 +1081,8 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object, ®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; @@ -1324,7 +1287,7 @@ target_xfer_partial (struct target_ops *ops, 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 @@ -1354,7 +1317,7 @@ target_read_uint32 (CORE_ADDR memaddr, uint32_t *result) 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 @@ -1367,7 +1330,7 @@ target_read_raw_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len) 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 @@ -1380,7 +1343,7 @@ target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len) 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 @@ -1396,7 +1359,7 @@ target_read_code (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len) 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 @@ -1412,7 +1375,7 @@ target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len) 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 @@ -1424,7 +1387,7 @@ target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len) std::vector target_memory_map (void) { - std::vector result = target_stack->memory_map (); + std::vector result = current_top_target ()->memory_map (); if (result.empty ()) return result; @@ -1454,13 +1417,13 @@ target_memory_map (void) 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 @@ -1860,7 +1823,7 @@ target_read_stralloc (struct target_ops *ops, enum target_object object, 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. */ @@ -1915,7 +1878,7 @@ target_insert_breakpoint (struct gdbarch *gdbarch, return 1; } - return target_stack->insert_breakpoint (gdbarch, bp_tgt); + return current_top_target ()->insert_breakpoint (gdbarch, bp_tgt); } /* See target.h. */ @@ -1935,25 +1898,24 @@ target_remove_breakpoint (struct gdbarch *gdbarch, 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, " @@ -2011,29 +1973,6 @@ target_pre_inferior (int from_tty) 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. */ @@ -2042,12 +1981,19 @@ target_preopen (int from_tty) { 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.")); } @@ -2066,6 +2012,11 @@ target_preopen (int from_tty) 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 @@ -2079,12 +2030,27 @@ target_detach (inferior *inf, int from_tty) ; 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 @@ -2095,7 +2061,7 @@ target_disconnect (const char *args, int from_tty) disconnecting. */ remove_breakpoints (); - target_stack->disconnect (args, from_tty); + current_top_target ()->disconnect (args, from_tty); } /* See target/target.h. */ @@ -2103,7 +2069,7 @@ target_disconnect (const char *args, int from_tty) 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. */ @@ -2117,16 +2083,18 @@ default_target_wait (struct target_ops *ops, 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 * @@ -2134,22 +2102,33 @@ target_thread_handle_to_thread_info (const gdb_byte *thread_handle, 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. */ @@ -2163,7 +2142,7 @@ target_commit_resume (void) if (defer_target_commit_resume) return; - target_stack->commit_resume (); + current_top_target ()->commit_resume (); } /* See target.h. */ @@ -2175,15 +2154,15 @@ make_scoped_defer_target_commit_resume () } void -target_pass_signals (int numsigs, unsigned char *pass_signals) +target_pass_signals (gdb::array_view 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 program_signals) { - target_stack->program_signals (numsigs, program_signals); + current_top_target ()->program_signals (program_signals); } static int @@ -2201,15 +2180,15 @@ default_follow_fork (struct target_ops *self, int follow_child, 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 @@ -2222,8 +2201,8 @@ default_mourn_inferior (struct target_ops *self) 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 @@ -2350,7 +2329,7 @@ default_search_memory (struct target_ops *self, 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); } @@ -2367,7 +2346,7 @@ target_search_memory (CORE_ADDR start_addr, ULONGEST search_space_len, 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); } @@ -2378,9 +2357,7 @@ target_search_memory (CORE_ADDR start_addr, ULONGEST search_space_len, 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 @@ -2392,7 +2369,7 @@ target_require_runnable (void) /* 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\". " @@ -2408,7 +2385,7 @@ target_require_runnable (void) /* 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, @@ -2420,6 +2397,32 @@ 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. @@ -2430,36 +2433,12 @@ show_auto_connect_native_target (struct ui_file *file, int from_tty, 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. */ @@ -2467,20 +2446,15 @@ find_default_run_target (const char *do_mesg) 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. */ @@ -2488,20 +2462,15 @@ find_attach_target (void) 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 @@ -2524,7 +2493,7 @@ target_info_proc (const char *args, enum info_proc_what what) 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)) { @@ -2553,7 +2522,7 @@ find_default_supports_disable_randomization (struct target_ops *self) int target_supports_disable_randomization (void) { - return target_stack->supports_disable_randomization (); + return current_top_target ()->supports_disable_randomization (); } /* See target/target.h. */ @@ -2561,7 +2530,7 @@ target_supports_disable_randomization (void) int target_supports_multi_process (void) { - return target_stack->supports_multi_process (); + return current_top_target ()->supports_multi_process (); } /* See target.h. */ @@ -2584,23 +2553,6 @@ target_get_osdata (const char *type) 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 * @@ -2608,16 +2560,18 @@ target_thread_address_space (ptid_t ptid) { 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 @@ -2650,18 +2604,16 @@ target_ops::create_inferior (const char *, const std::string &, 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; @@ -2843,9 +2795,7 @@ target_fileio_open_1 (struct inferior *inf, const char *filename, 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); @@ -3001,9 +2951,7 @@ int 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); @@ -3029,9 +2977,7 @@ gdb::optional 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 ret = t->fileio_readlink (inf, filename, target_errno); @@ -3170,7 +3116,7 @@ target_fileio_read_stralloc (struct inferior *inf, const char *filename) return gdb::unique_xmalloc_ptr (nullptr); if (transferred == 0) - return gdb::unique_xmalloc_ptr (xstrdup ("")); + return make_unique_xstrdup (""); bufstr[transferred] = 0; @@ -3203,22 +3149,17 @@ default_watchpoint_addr_within_range (struct target_ops *target, 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. */ @@ -3226,13 +3167,7 @@ find_target_beneath (struct target_ops *t) 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); } @@ -3252,10 +3187,9 @@ target_announce_detach (int from_tty) 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! */ @@ -3263,9 +3197,8 @@ target_announce_detach (int from_tty) 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 @@ -3273,11 +3206,8 @@ generic_mourn_inferior (void) 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 @@ -3296,16 +3226,13 @@ generic_mourn_inferior (void) /* 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); @@ -3331,51 +3258,47 @@ dummy_make_corefile_notes (struct target_ops *self, #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 (); } @@ -3396,13 +3319,13 @@ target_close (struct target_ops *targ) 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 @@ -3414,7 +3337,7 @@ target_stop (ptid_t ptid) return; } - target_stack->stop (ptid); + current_top_target ()->stop (ptid); } void @@ -3426,7 +3349,7 @@ target_interrupt () return; } - target_stack->interrupt (); + current_top_target ()->interrupt (); } /* See target.h. */ @@ -3434,7 +3357,33 @@ target_interrupt () 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. */ @@ -3451,9 +3400,9 @@ void 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)); @@ -3478,58 +3427,54 @@ target_continue (ptid_t ptid, enum gdb_signal signal) 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); } @@ -3540,7 +3485,7 @@ target_store_registers (struct regcache *regcache, int 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); @@ -3550,7 +3495,7 @@ target_store_registers (struct regcache *regcache, int 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 @@ -3588,14 +3533,14 @@ default_verify_memory (struct target_ops *self, 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 @@ -3605,7 +3550,7 @@ int 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 @@ -3615,7 +3560,7 @@ int 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 @@ -3624,7 +3569,7 @@ target_remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, 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 @@ -3633,7 +3578,7 @@ target_masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask) 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. */ @@ -3641,7 +3586,7 @@ target_ranged_break_num_registers (void) 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. */ @@ -3649,7 +3594,7 @@ target_enable_btrace (ptid_t ptid, const struct btrace_config *conf) void target_disable_btrace (struct btrace_target_info *btinfo) { - target_stack->disable_btrace (btinfo); + current_top_target ()->disable_btrace (btinfo); } /* See target.h. */ @@ -3657,7 +3602,7 @@ target_disable_btrace (struct btrace_target_info *btinfo) void target_teardown_btrace (struct btrace_target_info *btinfo) { - target_stack->teardown_btrace (btinfo); + current_top_target ()->teardown_btrace (btinfo); } /* See target.h. */ @@ -3667,7 +3612,7 @@ target_read_btrace (struct btrace_data *btrace, 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. */ @@ -3675,7 +3620,7 @@ target_read_btrace (struct btrace_data *btrace, 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. */ @@ -3683,7 +3628,7 @@ target_btrace_conf (const struct btrace_target_info *btinfo) void target_stop_recording (void) { - target_stack->stop_recording (); + current_top_target ()->stop_recording (); } /* See target.h. */ @@ -3691,7 +3636,7 @@ target_stop_recording (void) void target_save_record (const char *filename) { - target_stack->save_record (filename); + current_top_target ()->save_record (filename); } /* See target.h. */ @@ -3699,7 +3644,7 @@ target_save_record (const char *filename) int target_supports_delete_record () { - return target_stack->supports_delete_record (); + return current_top_target ()->supports_delete_record (); } /* See target.h. */ @@ -3707,7 +3652,7 @@ target_supports_delete_record () void target_delete_record (void) { - target_stack->delete_record (); + current_top_target ()->delete_record (); } /* See target.h. */ @@ -3715,7 +3660,7 @@ target_delete_record (void) 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. */ @@ -3723,7 +3668,7 @@ target_record_method (ptid_t ptid) 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. */ @@ -3731,7 +3676,7 @@ target_record_is_replaying (ptid_t ptid) 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. */ @@ -3739,7 +3684,7 @@ target_record_will_replay (ptid_t ptid, int dir) void target_record_stop_replaying (void) { - target_stack->record_stop_replaying (); + current_top_target ()->record_stop_replaying (); } /* See target.h. */ @@ -3747,7 +3692,7 @@ target_record_stop_replaying (void) void target_goto_record_begin (void) { - target_stack->goto_record_begin (); + current_top_target ()->goto_record_begin (); } /* See target.h. */ @@ -3755,7 +3700,7 @@ target_goto_record_begin (void) void target_goto_record_end (void) { - target_stack->goto_record_end (); + current_top_target ()->goto_record_end (); } /* See target.h. */ @@ -3763,7 +3708,7 @@ target_goto_record_end (void) void target_goto_record (ULONGEST insn) { - target_stack->goto_record (insn); + current_top_target ()->goto_record (insn); } /* See target.h. */ @@ -3771,7 +3716,7 @@ target_goto_record (ULONGEST insn) 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. */ @@ -3780,7 +3725,7 @@ void 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. */ @@ -3789,7 +3734,7 @@ void 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. */ @@ -3797,7 +3742,7 @@ target_insn_history_range (ULONGEST begin, ULONGEST end, 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. */ @@ -3805,7 +3750,7 @@ target_call_history (int size, record_print_flags flags) 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. */ @@ -3813,7 +3758,7 @@ target_call_history_from (ULONGEST begin, int size, record_print_flags flags) 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. */ @@ -3821,7 +3766,7 @@ target_call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flag const struct frame_unwind * target_get_unwinder (void) { - return target_stack->get_unwinder (); + return current_top_target ()->get_unwinder (); } /* See target.h. */ @@ -3829,7 +3774,7 @@ target_get_unwinder (void) 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. */ @@ -3837,7 +3782,7 @@ target_get_tailcall_unwinder (void) void target_prepare_to_generate_core (void) { - target_stack->prepare_to_generate_core (); + current_top_target ()->prepare_to_generate_core (); } /* See target.h. */ @@ -3845,7 +3790,7 @@ target_prepare_to_generate_core (void) void target_done_generating_core (void) { - target_stack->done_generating_core (); + current_top_target ()->done_generating_core (); } @@ -3892,9 +3837,9 @@ flash_erase_command (const char *cmd, int from_tty) 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"); } } @@ -3911,13 +3856,11 @@ flash_erase_command (const char *cmd, int from_tty) 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 ()); } @@ -3929,7 +3872,7 @@ void target_async (int enable) { infrun_async (enable); - target_stack->async (enable); + current_top_target ()->async (enable); } /* See target.h. */ @@ -3937,16 +3880,16 @@ target_async (int enable) 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, @@ -3977,7 +3920,7 @@ maint_show_target_async_command (struct ui_file *file, 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. */ @@ -4034,12 +3977,12 @@ maint_show_target_non_stop_command (struct ui_file *file, int from_tty, /* 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. */ @@ -4088,11 +4031,8 @@ set_write_memory_permission (const char *args, int from_tty, } 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);