Compare commits

...

7 Commits

Author SHA1 Message Date
Alan Hayward
8cc29a6ace [PATCH 7/7]: Regcache: Refactor raw_set_cached_value 2017-08-15 16:41:00 +01:00
Alan Hayward
a20c2452a4 [PATCH 6/7]: Regcache: jit should use a writable regcache 2017-08-15 16:40:35 +01:00
Alan Hayward
4ac8135dd8 [PATCH 5/7]: Regcache: Allow writable regcache 2017-08-15 16:40:09 +01:00
Alan Hayward
e9a5485336 [PATCH 4/7] Regcache: Refactor dup/cpy/save/restore 2017-08-15 16:39:47 +01:00
Alan Hayward
5c7af491c5 [PATCH 3/7]: Regcache: Remove xmalloc/xfree methods 2017-08-15 16:39:27 +01:00
Alan Hayward
c14731f7e9 [PATCH 2/7] Regcache: Only target_regcache reads/writes go to the target 2017-08-15 16:39:04 +01:00
Alan Hayward
15587be5bd [PATCH 1/7] Regcache: Subclass ptid functionality to target_regcache 2017-08-15 16:38:22 +01:00
11 changed files with 275 additions and 281 deletions

View File

@@ -1021,13 +1021,12 @@ struct regcache *
frame_save_as_regcache (struct frame_info *this_frame)
{
struct address_space *aspace = get_frame_address_space (this_frame);
struct regcache *regcache = regcache_xmalloc (get_frame_arch (this_frame),
aspace);
struct cleanup *cleanups = make_cleanup_regcache_xfree (regcache);
regcache *backup = new regcache (get_frame_arch (this_frame), aspace);
struct cleanup *cleanups = make_cleanup_regcache_delete (backup);
regcache_save (regcache, do_frame_register_read, this_frame);
backup->save (do_frame_register_read, this_frame);
discard_cleanups (cleanups);
return regcache;
return backup;
}
void
@@ -1063,7 +1062,7 @@ frame_pop (struct frame_info *this_frame)
trying to extract the old values from the current regcache while
at the same time writing new values into that same cache. */
scratch = frame_save_as_regcache (prev_frame);
cleanups = make_cleanup_regcache_xfree (scratch);
cleanups = make_cleanup_regcache_delete (scratch);
/* FIXME: cagney/2003-03-16: It should be possible to tell the
target's register cache that it is about to be hit with a burst
@@ -1073,9 +1072,8 @@ frame_pop (struct frame_info *this_frame)
Unfortunately, they don't implement it. Their lack of a formal
definition can lead to targets writing back bogus values
(arguably a bug in the target code mind). */
/* Now copy those saved registers into the current regcache.
Here, regcache_cpy() calls regcache_restore(). */
regcache_cpy (get_current_regcache (), scratch);
/* Now copy those saved registers into the current regcache. */
scratch->restore_to (get_current_regcache ());
do_cleanups (cleanups);
/* We've made right mess of GDB's local state, just discard

View File

@@ -27,11 +27,11 @@ namespace selftests {
/* A read-write regcache which doesn't write the target. */
class regcache_test : public regcache
class regcache_test : public target_regcache
{
public:
explicit regcache_test (struct gdbarch *gdbarch)
: regcache (gdbarch, NULL, false)
: target_regcache (gdbarch, NULL)
{
set_ptid (inferior_ptid);
@@ -40,7 +40,8 @@ public:
void raw_write (int regnum, const gdb_byte *buf) override
{
raw_set_cached_value (regnum, buf);
/* Bypass writing to the target. */
regcache::raw_write (regnum, buf);
}
};

View File

@@ -1602,8 +1602,8 @@ advance_command (char *arg, int from_tty)
struct value *
get_return_value (struct value *function, struct type *value_type)
{
regcache stop_regs (regcache::readonly, *get_current_regcache ());
struct gdbarch *gdbarch = stop_regs.arch ();
regcache *stop_regs = get_current_regcache ()->dup ();
struct gdbarch *gdbarch = stop_regs->arch ();
struct value *value;
value_type = check_typedef (value_type);
@@ -1623,7 +1623,7 @@ get_return_value (struct value *function, struct type *value_type)
case RETURN_VALUE_ABI_RETURNS_ADDRESS:
case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
value = allocate_value (value_type);
gdbarch_return_value (gdbarch, function, value_type, &stop_regs,
gdbarch_return_value (gdbarch, function, value_type, stop_regs,
value_contents_raw (value), NULL);
break;
case RETURN_VALUE_STRUCT_CONVENTION:
@@ -1633,6 +1633,7 @@ get_return_value (struct value *function, struct type *value_type)
internal_error (__FILE__, __LINE__, _("bad switch"));
}
delete stop_regs;
return value;
}

View File

@@ -8911,7 +8911,7 @@ save_infcall_suspend_state (void)
inf_state->stop_pc = stop_pc;
inf_state->registers = regcache_dup (regcache);
inf_state->registers = regcache->dup ();
return inf_state;
}
@@ -8922,7 +8922,7 @@ void
restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
{
struct thread_info *tp = inferior_thread ();
struct regcache *regcache = get_current_regcache ();
target_regcache *regcache = get_current_regcache ();
struct gdbarch *gdbarch = get_regcache_arch (regcache);
tp->suspend = inf_state->thread_suspend;
@@ -8942,7 +8942,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
(and perhaps other times). */
if (target_has_execution)
/* NB: The register write goes through to the target. */
regcache_cpy (regcache, inf_state->registers);
inf_state->registers->restore_to (regcache);
discard_infcall_suspend_state (inf_state);
}
@@ -8963,7 +8963,7 @@ make_cleanup_restore_infcall_suspend_state
void
discard_infcall_suspend_state (struct infcall_suspend_state *inf_state)
{
regcache_xfree (inf_state->registers);
delete inf_state->registers;
xfree (inf_state->siginfo_data);
xfree (inf_state);
}

View File

@@ -1125,7 +1125,7 @@ jit_unwind_reg_set_impl (struct gdb_unwind_callbacks *cb, int dwarf_regnum,
return;
}
regcache_raw_set_cached_value (priv->regcache, gdb_reg, value->value);
priv->regcache->raw_supply (gdb_reg, value->value);
value->free (value);
}
@@ -1168,7 +1168,7 @@ jit_dealloc_cache (struct frame_info *this_frame, void *cache)
struct jit_unwind_private *priv_data = (struct jit_unwind_private *) cache;
gdb_assert (priv_data->regcache != NULL);
regcache_xfree (priv_data->regcache);
delete priv_data->regcache;
xfree (priv_data);
}
@@ -1206,7 +1206,7 @@ jit_frame_sniffer (const struct frame_unwind *self,
*cache = XCNEW (struct jit_unwind_private);
priv_data = (struct jit_unwind_private *) *cache;
priv_data->regcache = regcache_xmalloc (gdbarch, aspace);
priv_data->regcache = new regcache (gdbarch, aspace, false);
priv_data->this_frame = this_frame;
callbacks.priv_data = priv_data;

View File

@@ -129,7 +129,7 @@ free_fork (struct fork_info *fp)
if (fp)
{
if (fp->savedregs)
regcache_xfree (fp->savedregs);
delete fp->savedregs;
if (fp->filepos)
xfree (fp->filepos);
xfree (fp);
@@ -264,7 +264,7 @@ fork_load_infrun_state (struct fork_info *fp)
linux_nat_switch_fork (fp->ptid);
if (fp->savedregs && fp->clobber_regs)
regcache_cpy (get_current_regcache (), fp->savedregs);
fp->savedregs->restore_to (get_current_regcache ());
registers_changed ();
reinit_frame_cache ();
@@ -295,9 +295,9 @@ fork_save_infrun_state (struct fork_info *fp, int clobber_regs)
DIR *d;
if (fp->savedregs)
regcache_xfree (fp->savedregs);
delete fp->savedregs;
fp->savedregs = regcache_dup (get_current_regcache ());
fp->savedregs = get_current_regcache ()->dup ();
fp->clobber_regs = clobber_regs;
if (clobber_regs)

View File

@@ -1051,7 +1051,7 @@ mi_cmd_data_list_changed_registers (const char *command, char **argv, int argc)
prev_regs = this_regs;
this_regs = frame_save_as_regcache (get_selected_frame (NULL));
cleanup = make_cleanup_regcache_xfree (prev_regs);
cleanup = make_cleanup_regcache_delete (prev_regs);
/* Note that the test for a valid register must include checking the
gdbarch_register_name because gdbarch_num_regs may be allocated

View File

@@ -1364,13 +1364,13 @@ ppu2spu_sniffer (const struct frame_unwind *self,
= FRAME_OBSTACK_CALLOC (1, struct ppu2spu_cache);
struct address_space *aspace = get_frame_address_space (this_frame);
struct regcache *regcache = regcache_xmalloc (data.gdbarch, aspace);
struct cleanup *cleanups = make_cleanup_regcache_xfree (regcache);
regcache_save (regcache, ppu2spu_unwind_register, &data);
regcache *backup = new regcache (data.gdbarch, aspace);
struct cleanup *cleanups = make_cleanup_regcache_delete (backup);
backup->save (ppu2spu_unwind_register, &data);
discard_cleanups (cleanups);
cache->frame_id = frame_id_build (base, func);
cache->regcache = regcache;
cache->regcache = backup;
*this_prologue_cache = cache;
return 1;
}
@@ -1383,7 +1383,7 @@ static void
ppu2spu_dealloc_cache (struct frame_info *self, void *this_cache)
{
struct ppu2spu_cache *cache = (struct ppu2spu_cache *) this_cache;
regcache_xfree (cache->regcache);
delete cache->regcache;
}
static const struct frame_unwind ppu2spu_unwind = {

View File

@@ -189,25 +189,36 @@ regcache_register_size (const struct regcache *regcache, int n)
}
regcache::regcache (gdbarch *gdbarch, address_space *aspace_,
bool readonly_p_)
bool readonly_p_, bool allocate_registers)
: m_aspace (aspace_), m_readonly_p (readonly_p_)
{
gdb_assert (gdbarch != NULL);
m_descr = regcache_descr (gdbarch);
if (m_readonly_p)
if (allocate_registers)
{
/* Need extra space to store the additional cooked registers for when
the detached regcache is used to save a regcache. */
m_registers = XCNEWVEC (gdb_byte, m_descr->sizeof_cooked_registers);
m_register_status = XCNEWVEC (signed char,
m_descr->sizeof_cooked_register_status);
}
else
{
m_registers = XCNEWVEC (gdb_byte, m_descr->sizeof_raw_registers);
m_register_status = XCNEWVEC (signed char,
m_descr->sizeof_raw_register_status);
}
/* All status' are initialised to REG_UNKNOWN. */
m_register_status = XCNEWVEC (signed char,
m_descr->sizeof_cooked_register_status);
}
target_regcache::target_regcache (gdbarch *gdbarch, address_space *aspace_)
: regcache (gdbarch, aspace_, false, false)
{
/* Only allocate the raw registers - cooked registers are not cached.
Note that the register status is still fully allocated, to allow the
checking of the state of any register. */
m_registers = XCNEWVEC (gdb_byte, m_descr->sizeof_raw_registers);
m_ptid = minus_one_ptid;
/* A target_regcache should never be readonly. */
gdb_assert (!m_readonly_p);
}
static enum register_status
@@ -218,13 +229,6 @@ do_cooked_read (void *src, int regnum, gdb_byte *buf)
return regcache_cooked_read (regcache, regnum, buf);
}
regcache::regcache (readonly_t, const regcache &src)
: regcache (src.arch (), src.aspace (), true)
{
gdb_assert (!src.m_readonly_p);
save (do_cooked_read, (void *) &src);
}
gdbarch *
regcache::arch () const
{
@@ -241,31 +245,18 @@ regcache_get_ptid (const struct regcache *regcache)
return regcache->ptid ();
}
struct regcache *
regcache_xmalloc (struct gdbarch *gdbarch, struct address_space *aspace)
{
return new regcache (gdbarch, aspace);
}
void
regcache_xfree (struct regcache *regcache)
{
if (regcache == NULL)
return;
delete regcache;
}
static void
do_regcache_xfree (void *data)
do_regcache_delete (void *data)
{
regcache_xfree ((struct regcache *) data);
if (data == NULL)
return;
delete (regcache *) data;
}
struct cleanup *
make_cleanup_regcache_xfree (struct regcache *regcache)
make_cleanup_regcache_delete (struct regcache *regcache)
{
return make_cleanup (do_regcache_xfree, regcache);
return make_cleanup (do_regcache_delete, regcache);
}
/* Cleanup routines for invalidating a register. */
@@ -317,23 +308,11 @@ regcache::register_buffer (int regnum) const
}
void
regcache_save (struct regcache *regcache,
regcache_cooked_read_ftype *cooked_read, void *src)
{
regcache->save (cooked_read, src);
}
void
regcache::save (regcache_cooked_read_ftype *cooked_read,
void *src)
regcache::save (regcache_cooked_read_ftype *cooked_read, void *src)
{
struct gdbarch *gdbarch = m_descr->gdbarch;
int regnum;
/* The DST should be `read-only', if it wasn't then the save would
end up trying to write the register values back out to the
target. */
gdb_assert (m_readonly_p);
/* Clear the dest. */
memset (m_registers, 0, m_descr->sizeof_cooked_registers);
memset (m_register_status, 0, m_descr->sizeof_cooked_register_status);
@@ -359,15 +338,14 @@ regcache::save (regcache_cooked_read_ftype *cooked_read,
}
void
regcache::restore (struct regcache *src)
regcache::restore_to (target_regcache *dst)
{
struct gdbarch *gdbarch = m_descr->gdbarch;
int regnum;
gdb_assert (dst != NULL);
gdb_assert (dst->m_descr->gdbarch == m_descr->gdbarch);
gdb_assert (dst != this);
/* The dst had better not be read-only. If it is, the `restore'
doesn't make much sense. */
gdb_assert (!m_readonly_p);
gdb_assert (src->m_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
@@ -376,27 +354,33 @@ regcache::restore (struct regcache *src)
{
if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
{
if (src->m_register_status[regnum] == REG_VALID)
cooked_write (regnum, src->register_buffer (regnum));
if (m_register_status[regnum] == REG_VALID)
dst->cooked_write (regnum, register_buffer (regnum));
}
}
}
void
regcache_cpy (struct regcache *dst, struct regcache *src)
/* Duplicate detached regcache to a detached regcache. */
regcache*
regcache::dup (bool readonly_p)
{
gdb_assert (src != NULL && dst != NULL);
gdb_assert (src->m_descr->gdbarch == dst->m_descr->gdbarch);
gdb_assert (src != dst);
gdb_assert (src->m_readonly_p && !dst->m_readonly_p);
regcache *new_regcache = new regcache (arch (), aspace (), readonly_p);
dst->restore (src);
memcpy (new_regcache->m_registers, m_registers,
m_descr->sizeof_cooked_registers);
memcpy (new_regcache->m_register_status, m_register_status,
m_descr->sizeof_cooked_register_status);
return new_regcache;
}
struct regcache *
regcache_dup (struct regcache *src)
/* Duplicate a target_regcache to a detached regcache. */
regcache*
target_regcache::dup (bool readonly_p)
{
return new regcache (regcache::readonly, *src);
regcache *new_regcache = new regcache (arch (), aspace (), readonly_p);
new_regcache->save (do_cooked_read, (void *) this);
return new_regcache;
}
enum register_status
@@ -410,14 +394,17 @@ enum register_status
regcache::get_register_status (int regnum) const
{
gdb_assert (regnum >= 0);
if (m_readonly_p)
gdb_assert (regnum < m_descr->nr_cooked_registers);
else
gdb_assert (regnum < m_descr->nr_raw_registers);
gdb_assert (regnum < m_descr->nr_cooked_registers);
return (enum register_status) m_register_status[regnum];
}
enum register_status
target_regcache::get_register_status (int regnum) const
{
gdb_assert (regnum < m_descr->nr_raw_registers);
return regcache::get_register_status (regnum);
}
void
regcache_invalidate (struct regcache *regcache, int regnum)
{
@@ -440,25 +427,25 @@ regcache::invalidate (int regnum)
recording if the register values have been changed (eg. by the
user). Therefore all registers must be written back to the
target when appropriate. */
std::forward_list<regcache *> regcache::current_regcache;
std::forward_list<target_regcache *> target_regcache::current_regcache;
struct regcache *
target_regcache *
get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
struct address_space *aspace)
{
for (const auto &regcache : regcache::current_regcache)
for (const auto &regcache : target_regcache::current_regcache)
if (ptid_equal (regcache->ptid (), ptid) && regcache->arch () == gdbarch)
return regcache;
regcache *new_regcache = new regcache (gdbarch, aspace, false);
target_regcache *new_regcache = new target_regcache (gdbarch, aspace);
regcache::current_regcache.push_front (new_regcache);
target_regcache::current_regcache.push_front (new_regcache);
new_regcache->set_ptid (ptid);
return new_regcache;
}
struct regcache *
target_regcache *
get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
{
struct address_space *aspace;
@@ -479,7 +466,7 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
static ptid_t current_thread_ptid;
static struct gdbarch *current_thread_arch;
struct regcache *
target_regcache *
get_thread_regcache (ptid_t ptid)
{
if (!current_thread_arch || !ptid_equal (current_thread_ptid, ptid))
@@ -491,7 +478,7 @@ get_thread_regcache (ptid_t ptid)
return get_thread_arch_regcache (ptid, current_thread_arch);
}
struct regcache *
target_regcache *
get_current_regcache (void)
{
return get_thread_regcache (inferior_ptid);
@@ -502,7 +489,7 @@ get_current_regcache (void)
struct regcache *
get_thread_regcache_for_ptid (ptid_t ptid)
{
return get_thread_regcache (ptid);
return (struct regcache*) get_thread_regcache (ptid);
}
/* Observer for the target_changed event. */
@@ -516,9 +503,9 @@ regcache_observer_target_changed (struct target_ops *target)
/* Update global variables old ptids to hold NEW_PTID if they were
holding OLD_PTID. */
void
regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
target_regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
{
for (auto &regcache : regcache::current_regcache)
for (auto &regcache : target_regcache::current_regcache)
{
if (ptid_equal (regcache->ptid (), old_ptid))
regcache->set_ptid (new_ptid);
@@ -539,15 +526,15 @@ regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
void
registers_changed_ptid (ptid_t ptid)
{
for (auto oit = regcache::current_regcache.before_begin (),
for (auto oit = target_regcache::current_regcache.before_begin (),
it = std::next (oit);
it != regcache::current_regcache.end ();
it != target_regcache::current_regcache.end ();
)
{
if (ptid_match ((*it)->ptid (), ptid))
{
delete *it;
it = regcache::current_regcache.erase_after (oit);
it = target_regcache::current_regcache.erase_after (oit);
}
else
oit = it++;
@@ -589,16 +576,14 @@ regcache_raw_update (struct regcache *regcache, int regnum)
}
void
regcache::raw_update (int regnum)
target_regcache::raw_update (int regnum)
{
gdb_assert (regnum >= 0 && regnum < m_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. */
to the current thread. */
if (!m_readonly_p && get_register_status (regnum) == REG_UNKNOWN)
if (get_register_status (regnum) == REG_UNKNOWN)
{
target_fetch_registers (this, regnum);
@@ -618,17 +603,19 @@ regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
enum register_status
regcache::raw_read (int regnum, gdb_byte *buf)
{
return raw_get_cached_reg (regnum, buf);
}
enum register_status
target_regcache::raw_read (int regnum, gdb_byte *buf)
{
gdb_assert (buf != NULL);
/* Read register value from the target into the regcache. */
raw_update (regnum);
if (m_register_status[regnum] != REG_VALID)
memset (buf, 0, m_descr->sizeof_register[regnum]);
else
memcpy (buf, register_buffer (regnum),
m_descr->sizeof_register[regnum]);
return (enum register_status) m_register_status[regnum];
return raw_get_cached_reg (regnum, buf);
}
enum register_status
@@ -719,8 +706,7 @@ regcache::cooked_read (int regnum, gdb_byte *buf)
gdb_assert (regnum < m_descr->nr_cooked_registers);
if (regnum < m_descr->nr_raw_registers)
return raw_read (regnum, buf);
else if (m_readonly_p
&& m_register_status[regnum] != REG_UNKNOWN)
else if (m_register_status[regnum] != REG_UNKNOWN)
{
/* Read-only register cache, perhaps the cooked value was
cached? */
@@ -772,7 +758,7 @@ regcache::cooked_read_value (int regnum)
gdb_assert (regnum < m_descr->nr_cooked_registers);
if (regnum < m_descr->nr_raw_registers
|| (m_readonly_p && m_register_status[regnum] != REG_UNKNOWN)
|| m_register_status[regnum] != REG_UNKNOWN
|| !gdbarch_pseudo_register_read_value_p (m_descr->gdbarch))
{
struct value *result;
@@ -859,21 +845,42 @@ regcache_cooked_write_unsigned (struct regcache *regcache, int regnum,
regcache->cooked_write (regnum, val);
}
/* See regcache.h. */
void
regcache_raw_set_cached_value (struct regcache *regcache, int regnum,
const gdb_byte *buf)
regcache::raw_set_cached_reg (int regnum, const gdb_byte *buf)
{
regcache->raw_set_cached_value (regnum, buf);
gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
gdb_assert (!m_readonly_p);
if (buf)
{
memcpy (register_buffer (regnum), buf, m_descr->sizeof_register[regnum]);
m_register_status[regnum] = REG_VALID;
}
else
{
/* This memset not strictly necessary, but better than garbage
in case the register value manages to escape somewhere (due
to a bug, no less). */
memset (register_buffer (regnum), 0, m_descr->sizeof_register[regnum]);
m_register_status[regnum] = REG_UNAVAILABLE;
}
gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
}
void
regcache::raw_set_cached_value (int regnum, const gdb_byte *buf)
enum register_status
regcache::raw_get_cached_reg (int regnum, gdb_byte *buf) const
{
memcpy (register_buffer (regnum), buf,
m_descr->sizeof_register[regnum]);
m_register_status[regnum] = REG_VALID;
gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
gdb_assert (buf != NULL);
if (m_register_status[regnum] != REG_VALID)
memset (buf, 0, m_descr->sizeof_register[regnum]);
else
memcpy (buf, register_buffer (regnum),
m_descr->sizeof_register[regnum]);
return (enum register_status) m_register_status[regnum];
}
void
@@ -886,12 +893,24 @@ regcache_raw_write (struct regcache *regcache, int regnum,
void
regcache::raw_write (int regnum, const gdb_byte *buf)
{
gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
/* On the sparc, writing %g0 is a no-op, so we don't even want to
change the registers array if something writes to this register. */
if (gdbarch_cannot_store_register (arch (), regnum))
return;
raw_set_cached_reg (regnum, buf);
}
void
target_regcache::raw_write (int regnum, const gdb_byte *buf)
{
struct cleanup *old_chain;
gdb_assert (buf != NULL);
gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
gdb_assert (!m_readonly_p);
/* On the sparc, writing %g0 is a no-op, so we don't even want to
change the registers array if something writes to this register. */
@@ -906,7 +925,7 @@ regcache::raw_write (int regnum, const gdb_byte *buf)
return;
target_prepare_to_store (this);
raw_set_cached_value (regnum, buf);
raw_set_cached_reg (regnum, buf);
/* Register a cleanup function for invalidating the register after it is
written, in case of a failure. */
@@ -1065,28 +1084,7 @@ regcache_raw_supply (struct regcache *regcache, int regnum, const void *buf)
void
regcache::raw_supply (int regnum, const void *buf)
{
void *regbuf;
size_t size;
gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
gdb_assert (!m_readonly_p);
regbuf = register_buffer (regnum);
size = m_descr->sizeof_register[regnum];
if (buf)
{
memcpy (regbuf, buf, size);
m_register_status[regnum] = REG_VALID;
}
else
{
/* This memset not strictly necessary, but better than garbage
in case the register value manages to escape somewhere (due
to a bug, no less). */
memset (regbuf, 0, size);
m_register_status[regnum] = REG_UNAVAILABLE;
}
raw_set_cached_reg (regnum, (const gdb_byte*) buf);
}
/* Supply register REGNUM to REGCACHE. Value to supply is an integer stored at
@@ -1146,15 +1144,7 @@ regcache_raw_collect (const struct regcache *regcache, int regnum, void *buf)
void
regcache::raw_collect (int regnum, void *buf) const
{
const void *regbuf;
size_t size;
gdb_assert (buf != NULL);
gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
regbuf = register_buffer (regnum);
size = m_descr->sizeof_register[regnum];
memcpy (buf, regbuf, size);
raw_get_cached_reg (regnum, (gdb_byte*) buf);
}
/* Transfer a single or all registers belonging to a certain register
@@ -1668,7 +1658,7 @@ maintenance_print_remote_registers (char *args, int from_tty)
namespace selftests {
class regcache_access : public regcache
class regcache_access : public target_regcache
{
public:
@@ -1677,8 +1667,8 @@ public:
static size_t
current_regcache_size ()
{
return std::distance (regcache::current_regcache.begin (),
regcache::current_regcache.end ());
return std::distance (target_regcache::current_regcache.begin (),
target_regcache::current_regcache.end ());
}
};
@@ -1692,7 +1682,7 @@ current_regcache_test (void)
/* Get regcache from ptid1, a new regcache is added to
current_regcache. */
regcache *regcache = get_thread_arch_aspace_regcache (ptid1,
target_regcache *regcache = get_thread_arch_aspace_regcache (ptid1,
target_gdbarch (),
NULL);
@@ -1745,7 +1735,8 @@ _initialize_regcache (void)
= gdbarch_data_register_post_init (init_regcache_descr);
observer_attach_target_changed (regcache_observer_target_changed);
observer_attach_thread_ptid_changed (regcache::regcache_thread_ptid_changed);
observer_attach_thread_ptid_changed
(target_regcache::regcache_thread_ptid_changed);
add_com ("flushregs", class_maintenance, reg_flush_command,
_("Force gdb to flush its register cache (maintainer command)"));

View File

@@ -24,21 +24,19 @@
#include <forward_list>
struct regcache;
class target_regcache;
struct regset;
struct gdbarch;
struct address_space;
extern struct regcache *get_current_regcache (void);
extern struct regcache *get_thread_regcache (ptid_t ptid);
extern struct regcache *get_thread_arch_regcache (ptid_t, struct gdbarch *);
extern struct regcache *get_thread_arch_aspace_regcache (ptid_t,
extern target_regcache *get_current_regcache (void);
extern target_regcache *get_thread_regcache (ptid_t ptid);
extern target_regcache *get_thread_arch_regcache (ptid_t, struct gdbarch *);
extern target_regcache *get_thread_arch_aspace_regcache (ptid_t,
struct gdbarch *,
struct address_space *);
void regcache_xfree (struct regcache *regcache);
struct cleanup *make_cleanup_regcache_xfree (struct regcache *regcache);
struct regcache *regcache_xmalloc (struct gdbarch *gdbarch,
struct address_space *aspace);
struct cleanup *make_cleanup_regcache_delete (regcache *regcache);
/* Return REGCACHE's ptid. */
@@ -81,14 +79,6 @@ extern void regcache_raw_write_unsigned (struct regcache *regcache,
extern LONGEST regcache_raw_get_signed (struct regcache *regcache,
int regnum);
/* Set a raw register's value in the regcache's buffer. Unlike
regcache_raw_write, this is not write-through. The intention is
allowing to change the buffer contents of a read-only regcache
allocated with regcache_xmalloc. */
extern void regcache_raw_set_cached_value
(struct regcache *regcache, int regnum, const gdb_byte *buf);
/* Partial transfer of raw registers. These perform read, modify,
write style operations. The read variant returns the status of the
register. */
@@ -211,20 +201,10 @@ extern struct type *register_type (struct gdbarch *gdbarch, int regnum);
extern int register_size (struct gdbarch *gdbarch, int regnum);
/* Save/restore a register cache. The set of registers saved /
restored into the DST regcache determined by the save_reggroup /
restore_reggroup respectively. COOKED_READ returns zero iff the
register's value can't be returned. */
typedef enum register_status (regcache_cooked_read_ftype) (void *src,
int regnum,
gdb_byte *buf);
extern void regcache_save (struct regcache *dst,
regcache_cooked_read_ftype *cooked_read,
void *cooked_read_context);
enum regcache_dump_what
{
regcache_dump_none, regcache_dump_raw,
@@ -240,30 +220,20 @@ typedef struct cached_reg
gdb_byte *data;
} cached_reg_t;
/* The register cache for storing raw register values. */
/* A register cache. This is not connected to a target - reads and writes will
not be passed through to a target and ptid is unset. */
class regcache
{
public:
regcache (gdbarch *gdbarch, address_space *aspace_)
: regcache (gdbarch, aspace_, true)
{}
struct readonly_t {};
static constexpr readonly_t readonly {};
/* Create a readonly regcache from a non-readonly regcache. */
regcache (readonly_t, const regcache &src);
regcache (gdbarch *gdbarch, address_space *aspace_, bool readonly_p_ = true,
bool allocate_registers = true);
regcache (const regcache &) = delete;
void operator= (const regcache &) = delete;
/* class regcache is only extended in unit test, so only mark it
virtual when selftest is enabled. */
#if GDB_SELF_TEST
virtual
#endif
~regcache ()
virtual ~regcache ()
{
xfree (m_registers);
xfree (m_register_status);
@@ -276,19 +246,22 @@ public:
return m_aspace;
}
/* Duplicate self into a new regcache. */
virtual regcache* dup (bool readonly_p = true);
/* Copy the register contents from a target_regcache to self.
All cooked registers are read and cached. */
void save (regcache_cooked_read_ftype *cooked_read, void *src);
/* Copy register contents to a target_regcache. All cached cooked registers
are also restored. */
void restore_to (target_regcache *dst);
enum register_status cooked_read (int regnum, gdb_byte *buf);
void cooked_write (int regnum, const gdb_byte *buf);
enum register_status raw_read (int regnum, gdb_byte *buf);
/* class regcache is only extended in unit test, so only mark it
virtual when selftest is enabled. */
#if GDB_SELF_TEST
virtual
#endif
void raw_write (int regnum, const gdb_byte *buf);
virtual enum register_status raw_read (int regnum, gdb_byte *buf);
virtual void raw_write (int regnum, const gdb_byte *buf);
template<typename T, typename = RequireLongest<T>>
enum register_status raw_read (int regnum, T *val);
@@ -304,7 +277,7 @@ public:
template<typename T, typename = RequireLongest<T>>
void cooked_write (int regnum, T val);
void raw_update (int regnum);
virtual void raw_update (int regnum) {}
void raw_collect (int regnum, void *buf) const;
@@ -318,9 +291,7 @@ public:
void raw_supply_zeroed (int regnum);
enum register_status get_register_status (int regnum) const;
void raw_set_cached_value (int regnum, const gdb_byte *buf);
virtual enum register_status get_register_status (int regnum) const;
void invalidate (int regnum);
@@ -344,40 +315,23 @@ public:
void dump (ui_file *file, enum regcache_dump_what what_to_dump);
ptid_t ptid () const
virtual ptid_t ptid () const
{
return m_ptid;
}
void set_ptid (const ptid_t ptid)
{
this->m_ptid = ptid;
/* Ptid of a non-target regcache is always -1. */
return (ptid_t) -1;
}
/* Dump the contents of a register from the register cache to the target
debug. */
void debug_print_register (const char *func, int regno);
static void regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid);
protected:
regcache (gdbarch *gdbarch, address_space *aspace_, bool readonly_p_);
static std::forward_list<regcache *> current_regcache;
private:
gdb_byte *register_buffer (int regnum) const;
void restore (struct regcache *src);
enum register_status xfer_part (int regnum, int offset, int len, void *in,
const void *out,
decltype (regcache_raw_read) read,
decltype (regcache_raw_write) write);
void transfer_regset (const struct regset *regset,
struct regcache *out_regcache,
int regnum, const void *in_buf,
void *out_buf, size_t size) const;
/* Get/Set the cached contents of the regcache. */
void raw_set_cached_reg (int regnum, const gdb_byte *buf);
enum register_status raw_get_cached_reg (int regnum, gdb_byte *buf) const;
struct regcache_descr *m_descr;
@@ -389,37 +343,86 @@ private:
full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) while a read/write
register cache can only hold [0 .. gdbarch_num_regs). */
gdb_byte *m_registers;
/* Register cache status. */
signed char *m_register_status;
/* Is this a read-only cache? A read-only cache is used for saving
the target's register state (e.g, across an inferior function
call or just before forcing a function return). A read-only
cache can only be updated via the methods regcache_dup() and
regcache_cpy(). The actual contents are determined by the
reggroup_save and reggroup_restore methods. */
/* A read-only cache can not change it's register contents, except from
an target_regcache via the save () method.
A target_regcache cache can never be read-only. */
bool m_readonly_p;
/* If this is a read-write cache, which thread's registers is
it connected to? */
ptid_t m_ptid;
friend struct regcache *
get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
struct address_space *aspace);
private:
friend void
registers_changed_ptid (ptid_t ptid);
enum register_status xfer_part (int regnum, int offset, int len, void *in,
const void *out,
decltype (regcache_raw_read) read,
decltype (regcache_raw_write) write);
void transfer_regset (const struct regset *regset,
struct regcache *out_regcache,
int regnum, const void *in_buf,
void *out_buf, size_t size) const;
private:
friend void
regcache_cpy (struct regcache *dst, struct regcache *src);
};
/* Duplicate the contents of a register cache to a read-only register
cache. The operation is pass-through. */
extern struct regcache *regcache_dup (struct regcache *regcache);
/* Writes to DEST will go through to the target. SRC is a read-only
register cache. */
extern void regcache_cpy (struct regcache *dest, struct regcache *src);
/* A register cache attached to a target. Reads and writes of register values
will be passed through to the target and ptid can be set. */
class target_regcache : public regcache
{
public:
target_regcache (const target_regcache &) = delete;
void operator= (const target_regcache &) = delete;
/* Cannot be called on a target_regcache. */
void save (regcache_cooked_read_ftype *cooked_read, void *src) = delete;
void restore_to (target_regcache *dst) = delete;
/* Duplicate self into a new regcache. Result is not a target_regcache. */
regcache* dup (bool readonly_p = true);
/* Overridden regcache methods. These versions will pass the read/write
through to the target. */
enum register_status raw_read (int regnum, gdb_byte *buf);
virtual void raw_write (int regnum, const gdb_byte *buf);
void raw_update (int regnum);
enum register_status get_register_status (int regnum) const;
ptid_t ptid () const
{
return m_ptid;
}
static void regcache_thread_ptid_changed (ptid_t old_ptid,
ptid_t new_ptid);
protected:
/* Constructor is only called via get_thread_arch_aspace_regcache. */
target_regcache (gdbarch *gdbarch, address_space *aspace_);
void set_ptid (const ptid_t ptid)
{
this->m_ptid = ptid;
}
static std::forward_list<target_regcache *> current_regcache;
private:
/* The thread the cache is connected to, or -1 if not attached. */
ptid_t m_ptid;
friend struct target_regcache * get_thread_arch_aspace_regcache
(ptid_t ptid, struct gdbarch *gdbarch, struct address_space *aspace);
friend void registers_changed_ptid (ptid_t ptid);
};
extern void registers_changed (void);
extern void registers_changed_ptid (ptid_t);

View File

@@ -1275,7 +1275,7 @@ spu2ppu_sniffer (const struct frame_unwind *self,
{
struct regcache *regcache;
regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
cache->regcache = regcache_dup (regcache);
cache->regcache = regcache->dup ();
*this_prologue_cache = cache;
return 1;
}
@@ -1288,7 +1288,7 @@ static void
spu2ppu_dealloc_cache (struct frame_info *self, void *this_cache)
{
struct spu2ppu_cache *cache = (struct spu2ppu_cache *) this_cache;
regcache_xfree (cache->regcache);
delete cache->regcache;
}
static const struct frame_unwind spu2ppu_unwind = {