Class readonly_detached_regcache

This patch adds a new class (type) for readonly regcache, which is
created via regcache::save.  readonly_detached_regcache inherits
readable_regcache.

gdb:

2018-02-21  Yao Qi  <yao.qi@linaro.org>

	* dummy-frame.c (dummy_frame_cache) <prev_regcache>: Use
	readonly_detached_regcache.
	(dummy_frame_prev_register): Use regcache->cooked_read.
	* frame.c (frame_save_as_regcache): Change return type.
	(frame_pop): Update.
	* frame.h (frame_save_as_regcache): Update declaration.
	* inferior.h (get_infcall_suspend_state_regcache): Update
	declaration.
	* infrun.c (infcall_suspend_state) <registers>: use
	readonly_detached_regcache.
	(save_infcall_suspend_state): Don't use regcache_dup.
	(get_infcall_suspend_state_regcache): Change return type.
	* linux-fork.c (struct fork_info) <savedregs>: Change to
	readonly_detached_regcache.
	<pc>: New field.
	(fork_save_infrun_state): Don't use regcache_dup.
	(info_checkpoints_command): Adjust.
	* mi/mi-main.c (register_changed_p): Update declaration.
	(mi_cmd_data_list_changed_registers): Use
	readonly_detached_regcache.
	(register_changed_p): Change parameter type to
	readonly_detached_regcache.
	* ppc-linux-tdep.c (ppu2spu_cache) <regcache>: Use
	readonly_detached_regcache.
	(ppu2spu_sniffer): Construct a new readonly_detached_regcache.
	* regcache.c (readonly_detached_regcache::readonly_detached_regcache):
	New.
	(regcache::save): Move it to reg_buffer.
	(regcache::restore): Change parameter type.
	(regcache_dup): Remove.
	* regcache.h (reg_buffer) <save>: New method.
	(readonly_detached_regcache): New class.
	* spu-tdep.c (spu2ppu_cache) <regcache>: Use
	readonly_detached_regcache.
	(spu2ppu_sniffer): Construct a new readonly_detached_regcache.
This commit is contained in:
Yao Qi 2018-02-21 11:20:03 +00:00
parent fc5b873615
commit daf6667d1f
12 changed files with 118 additions and 64 deletions

View file

@ -1,3 +1,41 @@
2018-02-21 Yao Qi <yao.qi@linaro.org>
* dummy-frame.c (dummy_frame_cache) <prev_regcache>: Use
readonly_detached_regcache.
(dummy_frame_prev_register): Use regcache->cooked_read.
* frame.c (frame_save_as_regcache): Change return type.
(frame_pop): Update.
* frame.h (frame_save_as_regcache): Update declaration.
* inferior.h (get_infcall_suspend_state_regcache): Update
declaration.
* infrun.c (infcall_suspend_state) <registers>: use
readonly_detached_regcache.
(save_infcall_suspend_state): Don't use regcache_dup.
(get_infcall_suspend_state_regcache): Change return type.
* linux-fork.c (struct fork_info) <savedregs>: Change to
readonly_detached_regcache.
<pc>: New field.
(fork_save_infrun_state): Don't use regcache_dup.
(info_checkpoints_command): Adjust.
* mi/mi-main.c (register_changed_p): Update declaration.
(mi_cmd_data_list_changed_registers): Use
readonly_detached_regcache.
(register_changed_p): Change parameter type to
readonly_detached_regcache.
* ppc-linux-tdep.c (ppu2spu_cache) <regcache>: Use
readonly_detached_regcache.
(ppu2spu_sniffer): Construct a new readonly_detached_regcache.
* regcache.c (readonly_detached_regcache::readonly_detached_regcache):
New.
(regcache::save): Move it to reg_buffer.
(regcache::restore): Change parameter type.
(regcache_dup): Remove.
* regcache.h (reg_buffer) <save>: New method.
(readonly_detached_regcache): New class.
* spu-tdep.c (spu2ppu_cache) <regcache>: Use
readonly_detached_regcache.
(spu2ppu_sniffer): Construct a new readonly_detached_regcache.
2018-02-21 Yao Qi <yao.qi@linaro.org> 2018-02-21 Yao Qi <yao.qi@linaro.org>
* frame.c (frame_save_as_regcache): Use regcache method save. * frame.c (frame_save_as_regcache): Use regcache method save.

View file

@ -282,7 +282,7 @@ cleanup_dummy_frames (struct target_ops *target, int from_tty)
struct dummy_frame_cache struct dummy_frame_cache
{ {
struct frame_id this_id; struct frame_id this_id;
struct regcache *prev_regcache; readonly_detached_regcache *prev_regcache;
}; };
static int static int
@ -352,7 +352,7 @@ dummy_frame_prev_register (struct frame_info *this_frame,
/* Use the regcache_cooked_read() method so that it, on the fly, /* Use the regcache_cooked_read() method so that it, on the fly,
constructs either a raw or pseudo register from the raw constructs either a raw or pseudo register from the raw
register cache. */ register cache. */
regcache_cooked_read (cache->prev_regcache, regnum, cache->prev_regcache->cooked_read (regnum,
value_contents_writeable (reg_val)); value_contents_writeable (reg_val));
return reg_val; return reg_val;
} }

View file

@ -1017,13 +1017,13 @@ do_frame_register_read (void *src, int regnum, gdb_byte *buf)
return REG_VALID; return REG_VALID;
} }
std::unique_ptr<struct regcache> std::unique_ptr<readonly_detached_regcache>
frame_save_as_regcache (struct frame_info *this_frame) frame_save_as_regcache (struct frame_info *this_frame)
{ {
std::unique_ptr<struct regcache> regcache std::unique_ptr<readonly_detached_regcache> regcache
(new struct regcache (get_frame_arch (this_frame))); (new readonly_detached_regcache (get_frame_arch (this_frame),
do_frame_register_read, this_frame));
regcache->save (do_frame_register_read, this_frame);
return regcache; return regcache;
} }
@ -1057,7 +1057,7 @@ frame_pop (struct frame_info *this_frame)
Save them in a scratch buffer so that there isn't a race between Save them in a scratch buffer so that there isn't a race between
trying to extract the old values from the current regcache while trying to extract the old values from the current regcache while
at the same time writing new values into that same cache. */ at the same time writing new values into that same cache. */
std::unique_ptr<struct regcache> scratch std::unique_ptr<readonly_detached_regcache> scratch
= frame_save_as_regcache (prev_frame); = frame_save_as_regcache (prev_frame);
/* FIXME: cagney/2003-03-16: It should be possible to tell the /* FIXME: cagney/2003-03-16: It should be possible to tell the

View file

@ -680,8 +680,9 @@ extern void *frame_obstack_zalloc (unsigned long size);
#define FRAME_OBSTACK_CALLOC(NUMBER,TYPE) \ #define FRAME_OBSTACK_CALLOC(NUMBER,TYPE) \
((TYPE *) frame_obstack_zalloc ((NUMBER) * sizeof (TYPE))) ((TYPE *) frame_obstack_zalloc ((NUMBER) * sizeof (TYPE)))
class readonly_detached_regcache;
/* Create a regcache, and copy the frame's registers into it. */ /* Create a regcache, and copy the frame's registers into it. */
std::unique_ptr<struct regcache> frame_save_as_regcache std::unique_ptr<readonly_detached_regcache> frame_save_as_regcache
(struct frame_info *this_frame); (struct frame_info *this_frame);
extern const struct block *get_frame_block (struct frame_info *, extern const struct block *get_frame_block (struct frame_info *,

View file

@ -70,7 +70,7 @@ extern struct cleanup *make_cleanup_restore_infcall_control_state
extern void discard_infcall_suspend_state (struct infcall_suspend_state *); extern void discard_infcall_suspend_state (struct infcall_suspend_state *);
extern void discard_infcall_control_state (struct infcall_control_state *); extern void discard_infcall_control_state (struct infcall_control_state *);
extern struct regcache * extern readonly_detached_regcache *
get_infcall_suspend_state_regcache (struct infcall_suspend_state *); get_infcall_suspend_state_regcache (struct infcall_suspend_state *);
extern void set_sigint_trap (void); extern void set_sigint_trap (void);

View file

@ -8805,7 +8805,7 @@ struct infcall_suspend_state
/* Other fields: */ /* Other fields: */
CORE_ADDR stop_pc; CORE_ADDR stop_pc;
struct regcache *registers; readonly_detached_regcache *registers;
/* Format of SIGINFO_DATA or NULL if it is not present. */ /* Format of SIGINFO_DATA or NULL if it is not present. */
struct gdbarch *siginfo_gdbarch; struct gdbarch *siginfo_gdbarch;
@ -8861,7 +8861,7 @@ save_infcall_suspend_state (void)
inf_state->stop_pc = stop_pc; inf_state->stop_pc = stop_pc;
inf_state->registers = regcache_dup (regcache); inf_state->registers = new readonly_detached_regcache (*regcache);
return inf_state; return inf_state;
} }
@ -8918,7 +8918,7 @@ discard_infcall_suspend_state (struct infcall_suspend_state *inf_state)
xfree (inf_state); xfree (inf_state);
} }
struct regcache * readonly_detached_regcache *
get_infcall_suspend_state_regcache (struct infcall_suspend_state *inf_state) get_infcall_suspend_state_regcache (struct infcall_suspend_state *inf_state)
{ {
return inf_state->registers; return inf_state->registers;

View file

@ -45,8 +45,9 @@ struct fork_info
ptid_t ptid; ptid_t ptid;
ptid_t parent_ptid; ptid_t parent_ptid;
int num; /* Convenient handle (GDB fork id). */ int num; /* Convenient handle (GDB fork id). */
struct regcache *savedregs; /* Convenient for info fork, saves readonly_detached_regcache *savedregs; /* Convenient for info fork, saves
having to actually switch contexts. */ having to actually switch contexts. */
CORE_ADDR pc;
int clobber_regs; /* True if we should restore saved regs. */ int clobber_regs; /* True if we should restore saved regs. */
off_t *filepos; /* Set of open file descriptors' offsets. */ off_t *filepos; /* Set of open file descriptors' offsets. */
int maxfd; int maxfd;
@ -294,7 +295,8 @@ fork_save_infrun_state (struct fork_info *fp, int clobber_regs)
if (fp->savedregs) if (fp->savedregs)
delete fp->savedregs; delete fp->savedregs;
fp->savedregs = regcache_dup (get_current_regcache ()); fp->savedregs = new readonly_detached_regcache (*get_current_regcache ());
fp->pc = regcache_read_pc (get_current_regcache ());
fp->clobber_regs = clobber_regs; fp->clobber_regs = clobber_regs;
if (clobber_regs) if (clobber_regs)
@ -590,15 +592,11 @@ info_checkpoints_command (const char *arg, int from_tty)
printed = fp; printed = fp;
if (ptid_equal (fp->ptid, inferior_ptid)) if (ptid_equal (fp->ptid, inferior_ptid))
{
printf_filtered ("* "); printf_filtered ("* ");
pc = regcache_read_pc (get_current_regcache ());
}
else else
{
printf_filtered (" "); printf_filtered (" ");
pc = regcache_read_pc (fp->savedregs);
} pc = fp->pc;
printf_filtered ("%d %s", fp->num, target_pid_to_str (fp->ptid)); printf_filtered ("%d %s", fp->num, target_pid_to_str (fp->ptid));
if (fp->num == 0) if (fp->num == 0)
printf_filtered (_(" (main process)")); printf_filtered (_(" (main process)"));

View file

@ -96,8 +96,8 @@ static void mi_execute_cli_command (const char *cmd, int args_p,
const char *args); const char *args);
static void mi_execute_async_cli_command (const char *cli_command, static void mi_execute_async_cli_command (const char *cli_command,
char **argv, int argc); char **argv, int argc);
static bool register_changed_p (int regnum, regcache *, static bool register_changed_p (int regnum, readonly_detached_regcache *,
regcache *); readonly_detached_regcache *);
static void output_register (struct frame_info *, int regnum, int format, static void output_register (struct frame_info *, int regnum, int format,
int skip_unavailable); int skip_unavailable);
@ -931,9 +931,9 @@ mi_cmd_data_list_register_names (const char *command, char **argv, int argc)
void void
mi_cmd_data_list_changed_registers (const char *command, char **argv, int argc) mi_cmd_data_list_changed_registers (const char *command, char **argv, int argc)
{ {
static std::unique_ptr<struct regcache> this_regs; static std::unique_ptr<readonly_detached_regcache> this_regs;
struct ui_out *uiout = current_uiout; struct ui_out *uiout = current_uiout;
std::unique_ptr<struct regcache> prev_regs; std::unique_ptr<readonly_detached_regcache> prev_regs;
struct gdbarch *gdbarch; struct gdbarch *gdbarch;
int regnum, numregs; int regnum, numregs;
int i; int i;
@ -995,8 +995,8 @@ mi_cmd_data_list_changed_registers (const char *command, char **argv, int argc)
} }
static bool static bool
register_changed_p (int regnum, struct regcache *prev_regs, register_changed_p (int regnum, readonly_detached_regcache *prev_regs,
struct regcache *this_regs) readonly_detached_regcache *this_regs)
{ {
struct gdbarch *gdbarch = this_regs->arch (); struct gdbarch *gdbarch = this_regs->arch ();
struct value *prev_value, *this_value; struct value *prev_value, *this_value;

View file

@ -1262,7 +1262,7 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order,
struct ppu2spu_cache struct ppu2spu_cache
{ {
struct frame_id frame_id; struct frame_id frame_id;
struct regcache *regcache; readonly_detached_regcache *regcache;
}; };
static struct gdbarch * static struct gdbarch *
@ -1369,10 +1369,10 @@ ppu2spu_sniffer (const struct frame_unwind *self,
{ {
struct ppu2spu_cache *cache struct ppu2spu_cache *cache
= FRAME_OBSTACK_CALLOC (1, struct ppu2spu_cache); = FRAME_OBSTACK_CALLOC (1, struct ppu2spu_cache);
std::unique_ptr<struct regcache> regcache std::unique_ptr<readonly_detached_regcache> regcache
(new struct regcache (data.gdbarch)); (new readonly_detached_regcache (data.gdbarch,
ppu2spu_unwind_register,
regcache->save (ppu2spu_unwind_register, &data); &data));
cache->frame_id = frame_id_build (base, func); cache->frame_id = frame_id_build (base, func);
cache->regcache = regcache.release (); cache->regcache = regcache.release ();

View file

@ -226,6 +226,11 @@ regcache::regcache (readonly_t, const regcache &src)
save (do_cooked_read, (void *) &src); save (do_cooked_read, (void *) &src);
} }
readonly_detached_regcache::readonly_detached_regcache (const regcache &src)
: readonly_detached_regcache (src.arch (), do_cooked_read, (void *) &src)
{
}
gdbarch * gdbarch *
reg_buffer::arch () const reg_buffer::arch () const
{ {
@ -282,16 +287,14 @@ reg_buffer::register_buffer (int regnum) const
} }
void void
regcache::save (regcache_cooked_read_ftype *cooked_read, reg_buffer::save (regcache_cooked_read_ftype *cooked_read,
void *src) void *src)
{ {
struct gdbarch *gdbarch = m_descr->gdbarch; struct gdbarch *gdbarch = m_descr->gdbarch;
int regnum; int regnum;
/* The DST should be `read-only', if it wasn't then the save would /* It should have pseudo registers. */
end up trying to write the register values back out to the gdb_assert (m_has_pseudo);
target. */
gdb_assert (m_readonly_p);
/* Clear the dest. */ /* Clear the dest. */
memset (m_registers, 0, m_descr->sizeof_cooked_registers); memset (m_registers, 0, m_descr->sizeof_cooked_registers);
memset (m_register_status, 0, m_descr->nr_cooked_registers); memset (m_register_status, 0, m_descr->nr_cooked_registers);
@ -317,16 +320,14 @@ regcache::save (regcache_cooked_read_ftype *cooked_read,
} }
void void
regcache::restore (struct regcache *src) regcache::restore (readonly_detached_regcache *src)
{ {
struct gdbarch *gdbarch = m_descr->gdbarch; struct gdbarch *gdbarch = m_descr->gdbarch;
int regnum; int regnum;
gdb_assert (src != NULL); gdb_assert (src != NULL);
/* 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 (!m_readonly_p);
gdb_assert (src->m_readonly_p); gdb_assert (src->m_has_pseudo);
gdb_assert (gdbarch == src->arch ()); gdb_assert (gdbarch == src->arch ());
@ -344,12 +345,6 @@ regcache::restore (struct regcache *src)
} }
} }
struct regcache *
regcache_dup (struct regcache *src)
{
return new regcache (regcache::readonly, *src);
}
enum register_status enum register_status
regcache_register_status (const struct regcache *regcache, int regnum) regcache_register_status (const struct regcache *regcache, int regnum)
{ {

View file

@ -243,6 +243,11 @@ protected:
gdb_byte *register_buffer (int regnum) const; gdb_byte *register_buffer (int regnum) const;
/* Save a register cache. The set of registers saved into the
regcache determined by the save_reggroup. COOKED_READ returns
zero iff the register's value can't be returned. */
void save (regcache_cooked_read_ftype *cooked_read, void *src);
struct regcache_descr *m_descr; struct regcache_descr *m_descr;
bool m_has_pseudo; bool m_has_pseudo;
@ -250,6 +255,8 @@ protected:
gdb_byte *m_registers; gdb_byte *m_registers;
/* Register cache status. */ /* Register cache status. */
signed char *m_register_status; signed char *m_register_status;
friend class regcache;
}; };
/* An abstract class which only has methods doing read. */ /* An abstract class which only has methods doing read. */
@ -284,6 +291,8 @@ protected:
bool is_raw); bool is_raw);
}; };
class readonly_detached_regcache;
/* The register cache for storing raw register values. */ /* The register cache for storing raw register values. */
class regcache : public readable_regcache class regcache : public readable_regcache
@ -307,15 +316,11 @@ public:
return m_aspace; return m_aspace;
} }
/* Save/restore 'this' regcache. The set of registers saved / /* Restore 'this' regcache. The set of registers restored into
restored into the regcache determined by the save_reggroup / the regcache determined by the restore_reggroup.
restore_reggroup respectively. COOKED_READ returns zero iff the Writes to regcache will go through to the target. SRC is a
register's value can't be returned. */
void save (regcache_cooked_read_ftype *cooked_read, void *src);
/* Writes to regcache will go through to the target. SRC is a
read-only register cache. */ read-only register cache. */
void restore (struct regcache *src); void restore (readonly_detached_regcache *src);
void cooked_write (int regnum, const gdb_byte *buf); void cooked_write (int regnum, const gdb_byte *buf);
@ -413,9 +418,26 @@ private:
registers_changed_ptid (ptid_t ptid); registers_changed_ptid (ptid_t ptid);
}; };
/* Duplicate the contents of a register cache to a read-only register class readonly_detached_regcache : public readable_regcache
cache. The operation is pass-through. */ {
extern struct regcache *regcache_dup (struct regcache *regcache); public:
readonly_detached_regcache (const regcache &src);
/* Create a readonly regcache by getting contents from COOKED_READ. */
readonly_detached_regcache (gdbarch *gdbarch,
regcache_cooked_read_ftype *cooked_read,
void *src)
: readable_regcache (gdbarch, true)
{
save (cooked_read, src);
}
DISABLE_COPY_AND_ASSIGN (readonly_detached_regcache);
void raw_update (int regnum) override
{}
};
extern void registers_changed (void); extern void registers_changed (void);
extern void registers_changed_ptid (ptid_t); extern void registers_changed_ptid (ptid_t);

View file

@ -1202,7 +1202,7 @@ spu_write_pc (struct regcache *regcache, CORE_ADDR pc)
struct spu2ppu_cache struct spu2ppu_cache
{ {
struct frame_id frame_id; struct frame_id frame_id;
struct regcache *regcache; readonly_detached_regcache *regcache;
}; };
static struct gdbarch * static struct gdbarch *
@ -1229,7 +1229,7 @@ spu2ppu_prev_register (struct frame_info *this_frame,
gdb_byte *buf; gdb_byte *buf;
buf = (gdb_byte *) alloca (register_size (gdbarch, regnum)); buf = (gdb_byte *) alloca (register_size (gdbarch, regnum));
regcache_cooked_read (cache->regcache, regnum, buf); cache->regcache->cooked_read (regnum, buf);
return frame_unwind_got_bytes (this_frame, regnum, buf); return frame_unwind_got_bytes (this_frame, regnum, buf);
} }
@ -1274,7 +1274,7 @@ spu2ppu_sniffer (const struct frame_unwind *self,
{ {
struct regcache *regcache; struct regcache *regcache;
regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
cache->regcache = regcache_dup (regcache); cache->regcache = new readonly_detached_regcache (*regcache);
*this_prologue_cache = cache; *this_prologue_cache = cache;
return 1; return 1;
} }