/* Select target systems and architectures at runtime for GDB.
- Copyright (C) 1990-2018 Free Software Foundation, Inc.
+ Copyright (C) 1990-2019 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>
static void generic_tls_error (void) ATTRIBUTE_NORETURN;
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);
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;
/* The target stack. */
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. */
strata stratum = t->stratum ();
if (m_stack[stratum] != NULL)
- {
- target_ops *prev = m_stack[stratum];
- m_stack[stratum] = NULL;
- target_close (prev);
- }
+ unpush (m_stack[stratum]);
/* Now add the new one. */
m_stack[stratum] = t;
g_target_stack.push (t);
}
+/* See target.h */
+
+void
+push_target (target_ops_up &&t)
+{
+ g_target_stack.push (t.get ());
+ t.release ();
+}
+
/* See target.h. */
int
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"));
- gdb_assert (t != NULL);
-
/* Look for the specified target. Note that a target can only occur
once in the target stack. */
{
volatile CORE_ADDR addr = 0;
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"));
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,
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
prepare_for_detach ();
current_top_target ()->detach (inf, from_tty);
+
+ registers_changed_ptid (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
return minus_one_ptid;
}
-const char *
+std::string
target_pid_to_str (ptid_t ptid)
{
return current_top_target ()->pid_to_str (ptid);
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)
{
}
void
-target_pass_signals (int numsigs, unsigned char *pass_signals)
+target_pass_signals (gdb::array_view<const unsigned char> pass_signals)
{
- current_top_target ()->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)
{
- current_top_target ()->program_signals (numsigs, program_signals);
+ current_top_target ()->program_signals (program_signals);
}
static int
/* 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)
{
current_top_target ()->follow_exec (inf, execd_pathname);
}
/* 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,
return gdb::unique_xmalloc_ptr<char> (nullptr);
if (transferred == 0)
- return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
+ return make_unique_xstrdup ("");
bufstr[transferred] = 0;
pid = inferior_ptid.pid ();
printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
- target_pid_to_str (ptid_t (pid)));
- gdb_flush (gdb_stdout);
+ target_pid_to_str (ptid_t (pid)).c_str ());
}
/* The inferior process has died. Long live the inferior! */
/* 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.pid ());
- 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. */
+
+static dummy_target the_dummy_target;
static const target_info dummy_target_info = {
"None",
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));
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");
}
}
/* 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,
/* 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)
{
- the_dummy_target = new dummy_target ();
- push_target (the_dummy_target);
+ push_target (&the_dummy_target);
the_debug_target = new debug_target ();