aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Hayward <alan.hayward@arm.com>2017-08-15 16:39:47 +0100
committerAlan Hayward <alan.hayward@arm.com>2017-08-15 16:39:47 +0100
commite9a5485336dfecd40c69a35ab09f37203e2d8918 (patch)
tree38d9a081a0a1ac50ef40f5d42f81839dc9530cfc
parent5c7af491c58e50539fd472e348607d602e4dcbb1 (diff)
downloadfsf-binutils-gdb-e9a5485336dfecd40c69a35ab09f37203e2d8918.zip
fsf-binutils-gdb-e9a5485336dfecd40c69a35ab09f37203e2d8918.tar.gz
fsf-binutils-gdb-e9a5485336dfecd40c69a35ab09f37203e2d8918.tar.bz2
[PATCH 4/7] Regcache: Refactor dup/cpy/save/restore
-rw-r--r--gdb/frame.c7
-rw-r--r--gdb/infcmd.c7
-rw-r--r--gdb/infrun.c6
-rw-r--r--gdb/linux-fork.c4
-rw-r--r--gdb/ppc-linux-tdep.c2
-rw-r--r--gdb/regcache.c60
-rw-r--r--gdb/regcache.h57
-rw-r--r--gdb/spu-tdep.c2
8 files changed, 60 insertions, 85 deletions
diff --git a/gdb/frame.c b/gdb/frame.c
index 7fd4b07..30cd853 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -1024,7 +1024,7 @@ frame_save_as_regcache (struct frame_info *this_frame)
regcache *backup = new regcache (get_frame_arch (this_frame), aspace);
struct cleanup *cleanups = make_cleanup_regcache_delete (backup);
- regcache_save (backup, do_frame_register_read, this_frame);
+ backup->save (do_frame_register_read, this_frame);
discard_cleanups (cleanups);
return backup;
}
@@ -1072,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
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index defa7b0..52da4ba 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -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;
}
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 6510aec..485cdcc 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -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);
}
diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c
index 032ff62..d307aa7 100644
--- a/gdb/linux-fork.c
+++ b/gdb/linux-fork.c
@@ -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 ();
@@ -297,7 +297,7 @@ fork_save_infrun_state (struct fork_info *fp, int clobber_regs)
if (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)
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 42aff2c..285ab74 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1366,7 +1366,7 @@ ppu2spu_sniffer (const struct frame_unwind *self,
struct address_space *aspace = get_frame_address_space (this_frame);
regcache *backup = new regcache (data.gdbarch, aspace);
struct cleanup *cleanups = make_cleanup_regcache_delete (backup);
- regcache_save (backup, ppu2spu_unwind_register, &data);
+ backup->save (ppu2spu_unwind_register, &data);
discard_cleanups (cleanups);
cache->frame_id = frame_id_build (base, func);
diff --git a/gdb/regcache.c b/gdb/regcache.c
index e7da5a6..5405dba 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -226,13 +226,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
{
@@ -312,23 +305,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);
@@ -354,15 +335,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
@@ -371,27 +351,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 ()
{
- 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 ());
+
+ 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);
- dst->restore (src);
+ return new_regcache;
}
-struct regcache *
-regcache_dup (struct regcache *src)
+/* Duplicate a target_regcache to a detached regcache. */
+regcache*
+target_regcache::dup ()
{
- return new regcache (regcache::readonly, *src);
+ regcache *new_regcache = new regcache (arch (), aspace ());
+ new_regcache->save (do_cooked_read, (void *) this);
+ return new_regcache;
}
enum register_status
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 00b87db..1437dac 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -209,20 +209,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,
@@ -249,12 +239,6 @@ public:
: 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 (const regcache &) = delete;
void operator= (const regcache &) = delete;
@@ -271,8 +255,17 @@ public:
return m_aspace;
}
+ /* Duplicate self into a new regcache. */
+ virtual regcache* dup ();
+
+ /* 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);
@@ -348,8 +341,6 @@ protected:
gdb_byte *register_buffer (int regnum) const;
- void restore (struct regcache *src);
-
struct regcache_descr *m_descr;
/* The address space of this register cache (for registers where it
@@ -363,12 +354,10 @@ protected:
/* 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;
private:
@@ -385,8 +374,6 @@ private:
private:
- friend void
- regcache_cpy (struct regcache *dst, struct regcache *src);
};
@@ -397,6 +384,16 @@ 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 ();
+
/* Overridden regcache methods. These versions will pass the read/write
through to the target. */
enum register_status raw_read (int regnum, gdb_byte *buf);
@@ -434,14 +431,6 @@ private:
friend void registers_changed_ptid (ptid_t ptid);
};
-/* 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);
-
extern void registers_changed (void);
extern void registers_changed_ptid (ptid_t);
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index 1ac763d..59ed385 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -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;
}