diff options
author | Alan Hayward <alan.hayward@arm.com> | 2017-08-15 16:39:47 +0100 |
---|---|---|
committer | Alan Hayward <alan.hayward@arm.com> | 2017-08-15 16:39:47 +0100 |
commit | e9a5485336dfecd40c69a35ab09f37203e2d8918 (patch) | |
tree | 38d9a081a0a1ac50ef40f5d42f81839dc9530cfc | |
parent | 5c7af491c58e50539fd472e348607d602e4dcbb1 (diff) | |
download | fsf-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.c | 7 | ||||
-rw-r--r-- | gdb/infcmd.c | 7 | ||||
-rw-r--r-- | gdb/infrun.c | 6 | ||||
-rw-r--r-- | gdb/linux-fork.c | 4 | ||||
-rw-r--r-- | gdb/ppc-linux-tdep.c | 2 | ||||
-rw-r--r-- | gdb/regcache.c | 60 | ||||
-rw-r--r-- | gdb/regcache.h | 57 | ||||
-rw-r--r-- | gdb/spu-tdep.c | 2 |
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; } |