mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
Compare commits
7 Commits
gdb-16.2-r
...
users/alah
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cc29a6ace | ||
|
|
a20c2452a4 | ||
|
|
4ac8135dd8 | ||
|
|
e9a5485336 | ||
|
|
5c7af491c5 | ||
|
|
c14731f7e9 | ||
|
|
15587be5bd |
16
gdb/frame.c
16
gdb/frame.c
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
287
gdb/regcache.c
287
gdb/regcache.c
@@ -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 ®cache : regcache::current_regcache)
|
||||
for (const auto ®cache : 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 ®cache : regcache::current_regcache)
|
||||
for (auto ®cache : 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)"));
|
||||
|
||||
201
gdb/regcache.h
201
gdb/regcache.h
@@ -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);
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user