/* Select target systems and architectures at runtime for GDB.
- Copyright (C) 1990-2016 Free Software Foundation, Inc.
+ Copyright (C) 1990-2017 Free Software Foundation, Inc.
Contributed by Cygnus Support.
#include "target-debug.h"
#include "top.h"
#include "event-top.h"
+#include <algorithm>
+#include "byte-vector.h"
-static void target_info (char *, int);
+static void info_target_command (char *, int);
static void generic_tls_error (void) ATTRIBUTE_NORETURN;
static int return_zero_has_execution (struct target_ops *, ptid_t);
-static void target_command (char *, int);
-
-static struct target_ops *find_default_run_target (char *);
+static struct target_ops *find_default_run_target (const char *);
static struct gdbarch *default_thread_architecture (struct target_ops *ops,
ptid_t ptid);
static char *dummy_make_corefile_notes (struct target_ops *self,
bfd *ignore1, int *ignore2);
-static char *default_pid_to_str (struct target_ops *ops, ptid_t ptid);
+static const char *default_pid_to_str (struct target_ops *ops, ptid_t ptid);
static enum exec_direction_kind default_execution_direction
(struct target_ops *self);
/* The user just typed 'target' without the name of a target. */
static void
-target_command (char *arg, int from_tty)
+target_command (const char *arg, int from_tty)
{
fputs_filtered ("Argument required (target name). Try `help target'\n",
gdb_stdout);
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->to_shortname, no_class, NULL, t->to_doc, &targetlist);
+ c = add_cmd (t->to_shortname, no_class, t->to_doc, &targetlist);
set_cmd_sfunc (c, open_target);
set_cmd_context (c, t);
if (completer != NULL)
/* See target.h. */
void
-add_deprecated_target_alias (struct target_ops *t, char *alias)
+add_deprecated_target_alias (struct target_ops *t, 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, NULL, t->to_doc, &targetlist);
+ c = add_cmd (alias, no_class, t->to_doc, &targetlist);
set_cmd_sfunc (c, open_target);
set_cmd_context (c, t);
alt = xstrprintf ("target %s", t->to_shortname);
(*current_target.to_load) (¤t_target, arg, from_tty);
}
-/* Possible terminal states. */
-
-enum terminal_state
- {
- /* The inferior's terminal settings are in effect. */
- terminal_is_inferior = 0,
-
- /* Some of our terminal settings are in effect, enough to get
- proper output. */
- terminal_is_ours_for_output = 1,
+/* Define it. */
- /* Our terminal settings are in effect, for output and input. */
- terminal_is_ours = 2
- };
+enum target_terminal::terminal_state target_terminal::terminal_state
+ = target_terminal::terminal_is_ours;
-static enum terminal_state terminal_state = terminal_is_ours;
-
-/* See target.h. */
+/* See target/target.h. */
void
-target_terminal_init (void)
+target_terminal::init (void)
{
(*current_target.to_terminal_init) (¤t_target);
terminal_state = terminal_is_ours;
}
-/* See target.h. */
-
-int
-target_terminal_is_inferior (void)
-{
- return (terminal_state == terminal_is_inferior);
-}
-
-/* See target.h. */
-
-int
-target_terminal_is_ours (void)
-{
- return (terminal_state == terminal_is_ours);
-}
-
-/* See target.h. */
+/* See target/target.h. */
void
-target_terminal_inferior (void)
+target_terminal::inferior (void)
{
struct ui *ui = current_ui;
if (ui->prompt_state != PROMPT_BLOCKED)
return;
- /* Always delete the current UI's input file handler, regardless of
- terminal_state, because terminal_state is only valid for the main
- UI. */
- delete_file_handler (ui->input_fd);
-
/* Since we always run the inferior in the main console (unless "set
inferior-tty" is in effect), when some UI other than the main one
- calls target_terminal_inferior/target_terminal_inferior, then we
- only register/unregister the UI's input from the event loop, but
- leave the main UI's terminal settings as is. */
+ calls target_terminal::inferior, then we leave the main UI's
+ terminal settings as is. */
if (ui != main_ui)
return;
target_pass_ctrlc ();
}
-/* See target.h. */
+/* See target/target.h. */
void
-target_terminal_ours (void)
+target_terminal::ours ()
{
struct ui *ui = current_ui;
- /* Always add the current UI's input file handler, regardless of
- terminal_state, because terminal_state is only valid for the main
- UI. */
- add_file_handler (ui->input_fd, stdin_event_handler, ui);
-
- /* See target_terminal_inferior. */
+ /* See target_terminal::inferior. */
if (ui != main_ui)
return;
terminal_state = terminal_is_ours;
}
-/* See target.h. */
+/* See target/target.h. */
void
-target_terminal_ours_for_output (void)
+target_terminal::ours_for_output ()
{
struct ui *ui = current_ui;
- /* See target_terminal_inferior. */
+ /* See target_terminal::inferior. */
if (ui != main_ui)
return;
terminal_state = terminal_is_ours_for_output;
}
+/* See target/target.h. */
+
+void
+target_terminal::info (const char *arg, int from_tty)
+{
+ (*current_target.to_terminal_info) (¤t_target, arg, from_tty);
+}
+
/* See target.h. */
int
return 0;
}
-/* Restore the terminal to its previous state (helper for
- make_cleanup_restore_target_terminal). */
-
-static void
-cleanup_restore_target_terminal (void *arg)
-{
- enum terminal_state *previous_state = (enum terminal_state *) arg;
-
- switch (*previous_state)
- {
- case terminal_is_ours:
- target_terminal_ours ();
- break;
- case terminal_is_ours_for_output:
- target_terminal_ours_for_output ();
- break;
- case terminal_is_inferior:
- target_terminal_inferior ();
- break;
- }
-}
-
-/* See target.h. */
-
-struct cleanup *
-make_cleanup_restore_target_terminal (void)
-{
- enum terminal_state *ts = XNEW (enum terminal_state);
-
- *ts = terminal_state;
-
- return make_cleanup_dtor (cleanup_restore_target_terminal, ts, xfree);
-}
-
static void
tcomplain (void)
{
}
else
{
- gdb_byte *buf;
- struct cleanup *old_chain;
-
/* A large write request is likely to be partially satisfied
by memory_xfer_partial_1. We will continually malloc
and free a copy of the entire write request for breakpoint
shadow handling even though we only end up writing a small
- subset of it. Cap writes to 4KB to mitigate this. */
- len = min (4096, len);
+ subset of it. Cap writes to a limit specified by the target
+ to mitigate this. */
+ len = std::min (ops->to_get_memory_xfer_limit (ops), len);
- buf = (gdb_byte *) xmalloc (len);
- old_chain = make_cleanup (xfree, buf);
- memcpy (buf, writebuf, len);
-
- breakpoint_xfer_memory (NULL, buf, writebuf, memaddr, len);
- res = memory_xfer_partial_1 (ops, object, NULL, buf, memaddr, len,
+ gdb::byte_vector buf (writebuf, writebuf + len);
+ breakpoint_xfer_memory (NULL, buf.data (), writebuf, memaddr, len);
+ res = memory_xfer_partial_1 (ops, object, NULL, buf.data (), memaddr, len,
xfered_len);
-
- do_cleanups (old_chain);
}
return res;
}
-static void
-restore_show_memory_breakpoints (void *arg)
+scoped_restore_tmpl<int>
+make_scoped_restore_show_memory_breakpoints (int show)
{
- show_memory_breakpoints = (uintptr_t) arg;
-}
-
-struct cleanup *
-make_show_memory_breakpoints_cleanup (int show)
-{
- int current = show_memory_breakpoints;
-
- show_memory_breakpoints = show;
- return make_cleanup (restore_show_memory_breakpoints,
- (void *) (uintptr_t) current);
+ return make_scoped_restore (&show_memory_breakpoints, show);
}
/* For docs see target.h, to_xfer_partial. */
read_whatever_is_readable (struct target_ops *ops,
const ULONGEST begin, const ULONGEST end,
int unit_size,
- VEC(memory_read_result_s) **result)
+ std::vector<memory_read_result> *result)
{
- gdb_byte *buf = (gdb_byte *) xmalloc (end - begin);
ULONGEST current_begin = begin;
ULONGEST current_end = end;
int forward;
- memory_read_result_s r;
ULONGEST xfered_len;
/* If we previously failed to read 1 byte, nothing can be done here. */
if (end - begin <= 1)
- {
- xfree (buf);
- return;
- }
+ return;
+
+ gdb::unique_xmalloc_ptr<gdb_byte> buf ((gdb_byte *) xmalloc (end - begin));
/* Check that either first or the last byte is readable, and give up
if not. This heuristic is meant to permit reading accessible memory
at the boundary of accessible region. */
if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
- buf, begin, 1, &xfered_len) == TARGET_XFER_OK)
+ buf.get (), begin, 1, &xfered_len) == TARGET_XFER_OK)
{
forward = 1;
++current_begin;
}
else if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
- buf + (end - begin) - 1, end - 1, 1,
+ buf.get () + (end - begin) - 1, end - 1, 1,
&xfered_len) == TARGET_XFER_OK)
{
forward = 0;
--current_end;
}
else
- {
- xfree (buf);
- return;
- }
+ return;
/* Loop invariant is that the [current_begin, current_end) was previously
found to be not readable as a whole.
}
xfer = target_read (ops, TARGET_OBJECT_MEMORY, NULL,
- buf + (first_half_begin - begin) * unit_size,
+ buf.get () + (first_half_begin - begin) * unit_size,
first_half_begin,
first_half_end - first_half_begin);
if (forward)
{
/* The [begin, current_begin) range has been read. */
- r.begin = begin;
- r.end = current_begin;
- r.data = buf;
+ result->emplace_back (begin, current_end, std::move (buf));
}
else
{
/* The [current_end, end) range has been read. */
LONGEST region_len = end - current_end;
- r.data = (gdb_byte *) xmalloc (region_len * unit_size);
- memcpy (r.data, buf + (current_end - begin) * unit_size,
+ gdb::unique_xmalloc_ptr<gdb_byte> data
+ ((gdb_byte *) xmalloc (region_len * unit_size));
+ memcpy (data.get (), buf.get () + (current_end - begin) * unit_size,
region_len * unit_size);
- r.begin = current_end;
- r.end = end;
- xfree (buf);
- }
- VEC_safe_push(memory_read_result_s, (*result), &r);
-}
-
-void
-free_memory_read_result_vector (void *x)
-{
- VEC(memory_read_result_s) **v = (VEC(memory_read_result_s) **) x;
- memory_read_result_s *current;
- int ix;
-
- for (ix = 0; VEC_iterate (memory_read_result_s, *v, ix, current); ++ix)
- {
- xfree (current->data);
+ result->emplace_back (current_end, end, std::move (data));
}
- VEC_free (memory_read_result_s, *v);
}
-VEC(memory_read_result_s) *
+std::vector<memory_read_result>
read_memory_robust (struct target_ops *ops,
const ULONGEST offset, const LONGEST len)
{
- VEC(memory_read_result_s) *result = 0;
+ std::vector<memory_read_result> result;
int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
- struct cleanup *cleanup = make_cleanup (free_memory_read_result_vector,
- &result);
LONGEST xfered_total = 0;
while (xfered_total < len)
}
else
{
- LONGEST to_read = min (len - xfered_total, region_len);
- gdb_byte *buffer = (gdb_byte *) xmalloc (to_read * unit_size);
- struct cleanup *inner_cleanup = make_cleanup (xfree, buffer);
+ LONGEST to_read = std::min (len - xfered_total, region_len);
+ gdb::unique_xmalloc_ptr<gdb_byte> buffer
+ ((gdb_byte *) xmalloc (to_read * unit_size));
LONGEST xfered_partial =
- target_read (ops, TARGET_OBJECT_MEMORY, NULL,
- (gdb_byte *) buffer,
+ target_read (ops, TARGET_OBJECT_MEMORY, NULL, buffer.get (),
offset + xfered_total, to_read);
/* Call an observer, notifying them of the xfer progress? */
if (xfered_partial <= 0)
{
/* Got an error reading full chunk. See if maybe we can read
some subrange. */
- do_cleanups (inner_cleanup);
read_whatever_is_readable (ops, offset + xfered_total,
offset + xfered_total + to_read,
unit_size, &result);
}
else
{
- struct memory_read_result r;
-
- discard_cleanups (inner_cleanup);
- r.data = buffer;
- r.begin = offset + xfered_total;
- r.end = r.begin + xfered_partial;
- VEC_safe_push (memory_read_result_s, result, &r);
+ result.emplace_back (offset + xfered_total,
+ offset + xfered_total + xfered_partial,
+ std::move (buffer));
xfered_total += xfered_partial;
}
QUIT;
}
}
- discard_cleanups (cleanup);
return result;
}
return target_read_alloc_1 (ops, object, annex, buf_p, 0);
}
-/* Read OBJECT/ANNEX using OPS. The result is NUL-terminated and
- returned as a string, allocated using xmalloc. If an error occurs
- or the transfer is unsupported, NULL is returned. Empty objects
- are returned as allocated but empty strings. A warning is issued
- if the result contains any embedded NUL bytes. */
+/* See target.h. */
-char *
+gdb::unique_xmalloc_ptr<char>
target_read_stralloc (struct target_ops *ops, enum target_object object,
const char *annex)
{
return NULL;
if (transferred == 0)
- return xstrdup ("");
+ return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
bufstr[transferred] = 0;
break;
}
- return bufstr;
+ return gdb::unique_xmalloc_ptr<char> (bufstr);
}
/* Memory transfer methods. */
int
target_remove_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
+ struct bp_target_info *bp_tgt,
+ enum remove_bp_reason reason)
{
/* This is kind of a weird case to handle, but the permission might
have been changed after breakpoints were inserted - in which case
}
return current_target.to_remove_breakpoint (¤t_target,
- gdbarch, bp_tgt);
+ gdbarch, bp_tgt, reason);
}
static void
-target_info (char *args, int from_tty)
+info_target_command (char *args, int from_tty)
{
struct target_ops *t;
int has_all_mem = 0;
current_target.to_disconnect (¤t_target, args, from_tty);
}
+/* See target/target.h. */
+
ptid_t
target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
{
return minus_one_ptid;
}
-char *
+const char *
target_pid_to_str (ptid_t ptid)
{
return (*current_target.to_pid_to_str) (¤t_target, ptid);
return current_target.to_thread_name (¤t_target, info);
}
+struct thread_info *
+target_thread_handle_to_thread_info (const gdb_byte *thread_handle,
+ int handle_len,
+ struct inferior *inf)
+{
+ return current_target.to_thread_handle_to_thread_info
+ (¤t_target, thread_handle, handle_len, inf);
+}
+
void
target_resume (ptid_t ptid, int step, enum gdb_signal signal)
{
clear_inline_frame_state (ptid);
}
+/* If true, target_commit_resume is a nop. */
+static int defer_target_commit_resume;
+
+/* See target.h. */
+
+void
+target_commit_resume (void)
+{
+ struct target_ops *t;
+
+ if (defer_target_commit_resume)
+ return;
+
+ current_target.to_commit_resume (¤t_target);
+}
+
+/* See target.h. */
+
+scoped_restore_tmpl<int>
+make_scoped_defer_target_commit_resume ()
+{
+ return make_scoped_restore (&defer_target_commit_resume, 1);
+}
+
void
target_pass_signals (int numsigs, unsigned char *pass_signals)
{
}
void
-target_mourn_inferior (void)
+target_mourn_inferior (ptid_t ptid)
{
+ gdb_assert (ptid_equal (ptid, inferior_ptid));
current_target.to_mourn_inferior (¤t_target);
/* We no longer need to keep handles on any of the object files.
#define SEARCH_CHUNK_SIZE 16000
const unsigned chunk_size = SEARCH_CHUNK_SIZE;
/* Buffer to hold memory contents for searching. */
- gdb_byte *search_buf;
unsigned search_buf_size;
- struct cleanup *old_cleanups;
search_buf_size = chunk_size + pattern_len - 1;
if (search_space_len < search_buf_size)
search_buf_size = search_space_len;
- search_buf = (gdb_byte *) malloc (search_buf_size);
- if (search_buf == NULL)
- error (_("Unable to allocate memory to perform the search."));
- old_cleanups = make_cleanup (free_current_contents, &search_buf);
+ gdb::byte_vector search_buf (search_buf_size);
/* Prime the search buffer. */
if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
- search_buf, start_addr, search_buf_size) != search_buf_size)
+ search_buf.data (), start_addr, search_buf_size)
+ != search_buf_size)
{
warning (_("Unable to access %s bytes of target "
"memory at %s, halting search."),
pulongest (search_buf_size), hex_string (start_addr));
- do_cleanups (old_cleanups);
return -1;
}
while (search_space_len >= pattern_len)
{
gdb_byte *found_ptr;
- unsigned nr_search_bytes = min (search_space_len, search_buf_size);
+ unsigned nr_search_bytes
+ = std::min (search_space_len, (ULONGEST) search_buf_size);
- found_ptr = (gdb_byte *) memmem (search_buf, nr_search_bytes,
+ found_ptr = (gdb_byte *) memmem (search_buf.data (), nr_search_bytes,
pattern, pattern_len);
if (found_ptr != NULL)
{
- CORE_ADDR found_addr = start_addr + (found_ptr - search_buf);
+ CORE_ADDR found_addr = start_addr + (found_ptr - search_buf.data ());
*found_addrp = found_addr;
- do_cleanups (old_cleanups);
return 1;
}
/* Copy the trailing part of the previous iteration to the front
of the buffer for the next iteration. */
gdb_assert (keep_len == pattern_len - 1);
- memcpy (search_buf, search_buf + chunk_size, keep_len);
+ memcpy (&search_buf[0], &search_buf[chunk_size], keep_len);
- nr_to_read = min (search_space_len - keep_len, chunk_size);
+ nr_to_read = std::min (search_space_len - keep_len,
+ (ULONGEST) chunk_size);
if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
- search_buf + keep_len, read_addr,
+ &search_buf[keep_len], read_addr,
nr_to_read) != nr_to_read)
{
warning (_("Unable to access %s bytes of target "
"memory at %s, halting search."),
plongest (nr_to_read),
hex_string (read_addr));
- do_cleanups (old_cleanups);
return -1;
}
/* Not found. */
- do_cleanups (old_cleanups);
return 0;
}
called for errors); else, return NULL on error. */
static struct target_ops *
-find_default_run_target (char *do_mesg)
+find_default_run_target (const char *do_mesg)
{
struct target_ops *runable = NULL;
return 0;
}
-char *
+/* See target/target.h. */
+
+int
+target_supports_multi_process (void)
+{
+ return (*current_target.to_supports_multi_process) (¤t_target);
+}
+
+/* See target.h. */
+
+gdb::unique_xmalloc_ptr<char>
target_get_osdata (const char *type)
{
struct target_ops *t;
release_fileio_fd (int fd, fileio_fh_t *fh)
{
fh->fd = -1;
- lowest_closed_fd = min (lowest_closed_fd, fd);
+ lowest_closed_fd = std::min (lowest_closed_fd, fd);
}
/* Return a pointer to the fileio_fhandle_t corresponding to FD. */
/* See target.h. */
-char *
+gdb::unique_xmalloc_ptr<char>
target_fileio_read_stralloc (struct inferior *inf, const char *filename)
{
gdb_byte *buffer;
bufstr = (char *) buffer;
if (transferred < 0)
- return NULL;
+ return gdb::unique_xmalloc_ptr<char> (nullptr);
if (transferred == 0)
- return xstrdup ("");
+ return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
bufstr[transferred] = 0;
break;
}
- return bufstr;
+ return gdb::unique_xmalloc_ptr<char> (bufstr);
}
static struct gdbarch *
default_thread_architecture (struct target_ops *ops, ptid_t ptid)
{
- return target_gdbarch ();
+ inferior *inf = find_inferior_ptid (ptid);
+ gdb_assert (inf != NULL);
+ return inf->gdbarch;
}
static int
}
\f
+
+/* See target.h */
+
+void
+target_announce_detach (int from_tty)
+{
+ pid_t pid;
+ const char *exec_file;
+
+ if (!from_tty)
+ return;
+
+ exec_file = get_exec_file (0);
+ if (exec_file == NULL)
+ exec_file = "";
+
+ pid = ptid_get_pid (inferior_ptid);
+ printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
+ target_pid_to_str (pid_to_ptid (pid)));
+ gdb_flush (gdb_stdout);
+}
+
/* The inferior process has died. Long live the inferior! */
void
/* Convert a normal process ID to a string. Returns the string in a
static buffer. */
-char *
+const char *
normal_pid_to_str (ptid_t ptid)
{
static char buf[32];
return buf;
}
-static char *
+static const char *
default_pid_to_str (struct target_ops *ops, ptid_t ptid)
{
return normal_pid_to_str (ptid);
target_resume (ptid, 0, GDB_SIGNAL_0);
}
+/* See target/target.h. */
+
+void
+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. */
static char *
do_option (int *target_options, char *ret,
- int opt, char *opt_str)
+ int opt, const char *opt_str)
{
if ((*target_options & opt) != 0)
{
return ret;
}
-static void
-debug_print_register (const char * func,
- struct regcache *regcache, int regno)
-{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
-
- fprintf_unfiltered (gdb_stdlog, "%s ", func);
- if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)
- && gdbarch_register_name (gdbarch, regno) != NULL
- && gdbarch_register_name (gdbarch, regno)[0] != '\0')
- fprintf_unfiltered (gdb_stdlog, "(%s)",
- gdbarch_register_name (gdbarch, regno));
- else
- fprintf_unfiltered (gdb_stdlog, "(%d)", regno);
- if (regno >= 0 && regno < gdbarch_num_regs (gdbarch))
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int i, size = register_size (gdbarch, regno);
- gdb_byte buf[MAX_REGISTER_SIZE];
-
- regcache_raw_collect (regcache, regno, buf);
- fprintf_unfiltered (gdb_stdlog, " = ");
- for (i = 0; i < size; i++)
- {
- fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
- }
- if (size <= sizeof (LONGEST))
- {
- ULONGEST val = extract_unsigned_integer (buf, size, byte_order);
-
- fprintf_unfiltered (gdb_stdlog, " %s %s",
- core_addr_to_string_nz (val), plongest (val));
- }
- }
- fprintf_unfiltered (gdb_stdlog, "\n");
-}
-
void
target_fetch_registers (struct regcache *regcache, int regno)
{
current_target.to_fetch_registers (¤t_target, regcache, regno);
if (targetdebug)
- debug_print_register ("target_fetch_registers", regcache, regno);
+ regcache->debug_print_register ("target_fetch_registers", regno);
}
void
current_target.to_store_registers (¤t_target, regcache, regno);
if (targetdebug)
{
- debug_print_register ("target_store_registers", regcache, regno);
+ regcache->debug_print_register ("target_store_registers", regno);
}
}
ULONGEST xfered_len;
enum target_xfer_status status;
gdb_byte buf[1024];
- ULONGEST howmuch = min (sizeof (buf), size - total_xfered);
+ ULONGEST howmuch = std::min<ULONGEST> (sizeof (buf), size - total_xfered);
status = target_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
buf, NULL, lma + total_xfered, howmuch,
/* See target.h. */
+enum record_method
+target_record_method (ptid_t ptid)
+{
+ return current_target.to_record_method (¤t_target, ptid);
+}
+
+/* See target.h. */
+
int
target_record_is_replaying (ptid_t ptid)
{
/* See target.h. */
void
-target_insn_history (int size, int flags)
+target_insn_history (int size, gdb_disassembly_flags flags)
{
current_target.to_insn_history (¤t_target, size, flags);
}
/* See target.h. */
void
-target_insn_history_from (ULONGEST from, int size, int flags)
+target_insn_history_from (ULONGEST from, int size,
+ gdb_disassembly_flags flags)
{
current_target.to_insn_history_from (¤t_target, from, size, flags);
}
/* See target.h. */
void
-target_insn_history_range (ULONGEST begin, ULONGEST end, int flags)
+target_insn_history_range (ULONGEST begin, ULONGEST end,
+ gdb_disassembly_flags flags)
{
current_target.to_insn_history_range (¤t_target, begin, end, flags);
}
target_rcmd (cmd, gdb_stdtarg);
}
+/* Erases all the memory regions marked as flash. CMD and FROM_TTY are
+ ignored. */
+
+void
+flash_erase_command (char *cmd, int from_tty)
+{
+ /* Used to communicate termination of flash operations to the target. */
+ bool found_flash_region = false;
+ struct mem_region *m;
+ struct gdbarch *gdbarch = target_gdbarch ();
+
+ VEC(mem_region_s) *mem_regions = target_memory_map ();
+
+ /* Iterate over all memory regions. */
+ for (int i = 0; VEC_iterate (mem_region_s, mem_regions, i, m); i++)
+ {
+ /* Fetch the memory attribute. */
+ struct mem_attrib *attrib = &m->attrib;
+
+ /* Is this a flash memory region? */
+ if (attrib->mode == MEM_FLASH)
+ {
+ found_flash_region = true;
+ target_flash_erase (m->lo, m->hi - m->lo);
+
+ ui_out_emit_tuple tuple_emitter (current_uiout, "erased-regions");
+
+ current_uiout->message (_("Erasing flash memory region at address "));
+ current_uiout->field_fmt ("address", "%s", paddress (gdbarch,
+ m->lo));
+ current_uiout->message (", size = ");
+ current_uiout->field_fmt ("size", "%s", hex_string (m->hi - m->lo));
+ current_uiout->message ("\n");
+ }
+ }
+
+ /* Did we do any flash operations? If so, we need to finalize them. */
+ if (found_flash_region)
+ target_flash_done ();
+ else
+ current_uiout->message (_("No flash memory regions found.\n"));
+}
+
/* Print the name of each layers of our target stack. */
static void
-maintenance_print_target_stack (char *cmd, int from_tty)
+maintenance_print_target_stack (const char *cmd, int from_tty)
{
struct target_ops *t;
init_dummy_target ();
push_target (&dummy_target);
- add_info ("target", target_info, targ_desc);
- add_info ("files", target_info, targ_desc);
+ add_info ("target", info_target_command, targ_desc);
+ add_info ("files", info_target_command, targ_desc);
add_setshow_zuinteger_cmd ("target", class_maintenance, &targetdebug, _("\
Set target debugging."), _("\
set_target_permissions, NULL,
&setlist, &showlist);
+ add_com ("flash-erase", no_class, flash_erase_command,
+ _("Erase all flash memory regions."));
+
add_setshow_boolean_cmd ("auto-connect-native-target", class_support,
&auto_connect_native_target, _("\
Set whether GDB may automatically connect to the native target."), _("\