/* Cache and manage the values of registers for GDB, the GNU debugger.
- Copyright (C) 1986-2015 Free Software Foundation, Inc.
+ Copyright (C) 1986-2017 Free Software Foundation, Inc.
This file is part of GDB.
ptid_t ptid;
};
+/* See regcache.h. */
+
+ptid_t
+regcache_get_ptid (const struct regcache *regcache)
+{
+ gdb_assert (!ptid_equal (regcache->ptid, minus_one_ptid));
+
+ return regcache->ptid;
+}
+
static struct regcache *
regcache_xmalloc_1 (struct gdbarch *gdbarch, struct address_space *aspace,
int readonly_p)
}
static void
-regcache_restore (struct regcache *dst,
- regcache_cooked_read_ftype *cooked_read,
- void *cooked_read_context)
+regcache_restore (struct regcache *dst, struct regcache *src)
{
struct gdbarch *gdbarch = dst->descr->gdbarch;
- gdb_byte buf[MAX_REGISTER_SIZE];
int regnum;
/* The dst had better not be read-only. If it is, the `restore'
doesn't make much sense. */
gdb_assert (!dst->readonly_p);
+ gdb_assert (src->readonly_p);
/* Copy over any registers, being careful to only restore those that
were both saved and need to be restored. The full [0 .. gdbarch_num_regs
+ gdbarch_num_pseudo_regs) range is checked since some architectures need
{
if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
{
- enum register_status status;
-
- status = cooked_read (cooked_read_context, regnum, buf);
- if (status == REG_VALID)
- regcache_cooked_write (dst, regnum, buf);
+ if (src->register_status[regnum] == REG_VALID)
+ regcache_cooked_write (dst, regnum, register_buffer (src, regnum));
}
}
}
if (!src->readonly_p)
regcache_save (dst, do_cooked_read, src);
else if (!dst->readonly_p)
- regcache_restore (dst, do_cooked_read, src);
+ regcache_restore (dst, src);
else
regcache_cpy_no_passthrough (dst, src);
}
alloca (0);
}
-enum register_status
-regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
+void
+regcache_raw_update (struct regcache *regcache, int regnum)
{
- gdb_assert (regcache != NULL && buf != NULL);
+ gdb_assert (regcache != NULL);
gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+
/* Make certain that the register cache is up-to-date with respect
to the current thread. This switching shouldn't be necessary
only there is still only one target side register cache. Sigh!
On the bright side, at least there is a regcache object. */
+
if (!regcache->readonly_p
&& regcache_register_status (regcache, regnum) == REG_UNKNOWN)
{
- struct cleanup *old_chain = save_inferior_ptid ();
-
- inferior_ptid = regcache->ptid;
target_fetch_registers (regcache, regnum);
- do_cleanups (old_chain);
/* A number of targets can't access the whole set of raw
registers (because the debug API provides no means to get at
if (regcache->register_status[regnum] == REG_UNKNOWN)
regcache->register_status[regnum] = REG_UNAVAILABLE;
}
+}
+
+enum register_status
+regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
+{
+ gdb_assert (buf != NULL);
+ regcache_raw_update (regcache, regnum);
if (regcache->register_status[regnum] != REG_VALID)
memset (buf, 0, regcache->descr->sizeof_register[regnum]);
regcache_raw_write (regcache, regnum, buf);
}
+LONGEST
+regcache_raw_get_signed (struct regcache *regcache, int regnum)
+{
+ LONGEST value;
+ enum register_status status;
+
+ status = regcache_raw_read_signed (regcache, regnum, &value);
+ if (status == REG_UNAVAILABLE)
+ throw_error (NOT_AVAILABLE_ERROR,
+ _("Register %d is not available"), regnum);
+ return value;
+}
+
enum register_status
regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
{
regcache_cooked_write (regcache, regnum, buf);
}
+/* See regcache.h. */
+
+void
+regcache_raw_set_cached_value (struct regcache *regcache, int regnum,
+ const gdb_byte *buf)
+{
+ memcpy (register_buffer (regcache, regnum), buf,
+ regcache->descr->sizeof_register[regnum]);
+ regcache->register_status[regnum] = REG_VALID;
+}
+
void
regcache_raw_write (struct regcache *regcache, int regnum,
const gdb_byte *buf)
{
- struct cleanup *chain_before_save_inferior;
- struct cleanup *chain_before_invalidate_register;
+ struct cleanup *old_chain;
gdb_assert (regcache != NULL && buf != NULL);
gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
regcache->descr->sizeof_register[regnum]) == 0))
return;
- chain_before_save_inferior = save_inferior_ptid ();
- inferior_ptid = regcache->ptid;
-
target_prepare_to_store (regcache);
- memcpy (register_buffer (regcache, regnum), buf,
- regcache->descr->sizeof_register[regnum]);
- regcache->register_status[regnum] = REG_VALID;
+ regcache_raw_set_cached_value (regcache, regnum, buf);
/* Register a cleanup function for invalidating the register after it is
written, in case of a failure. */
- chain_before_invalidate_register
- = make_cleanup_regcache_invalidate (regcache, regnum);
+ old_chain = make_cleanup_regcache_invalidate (regcache, regnum);
target_store_registers (regcache, regnum);
/* The target did not throw an error so we can discard invalidating the
register and restore the cleanup chain to what it was. */
- discard_cleanups (chain_before_invalidate_register);
-
- do_cleanups (chain_before_save_inferior);
+ discard_cleanups (old_chain);
}
void
const gdb_byte *buf))
{
struct regcache_descr *descr = regcache->descr;
- gdb_byte reg[MAX_REGISTER_SIZE];
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ gdb_byte *reg = (gdb_byte *) alloca (register_size (gdbarch, regnum));
gdb_assert (offset >= 0 && offset <= descr->sizeof_register[regnum]);
gdb_assert (len >= 0 && offset + len <= descr->sizeof_register[regnum]);
reinit_frame_cache ();
}
+void
+regcache_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 size = register_size (gdbarch, regno);
+ gdb_byte *buf = register_buffer (regcache, regno);
+
+ fprintf_unfiltered (gdb_stdlog, " = ");
+ for (int 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");
+}
static void
reg_flush_command (char *command, int from_tty)
regcache_dump (get_current_regcache (), gdb_stdout, what_to_dump);
else
{
- struct cleanup *cleanups;
- struct ui_file *file = gdb_fopen (args, "w");
+ stdio_file file;
- if (file == NULL)
+ if (!file.open (args, "w"))
perror_with_name (_("maintenance print architecture"));
- cleanups = make_cleanup_ui_file_delete (file);
- regcache_dump (get_current_regcache (), file, what_to_dump);
- do_cleanups (cleanups);
+ regcache_dump (get_current_regcache (), &file, what_to_dump);
}
}