aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2017-09-22 14:02:38 +0100
committerYao Qi <yao.qi@linaro.org>2017-10-13 11:52:11 +0100
commit2d6f8f50b4d975bfebebb0990b423071f341a157 (patch)
tree9e9bae4d2393e866d5db94f5d7aa76e4951eb836
parent9fa4f9dd3d0f4e7f35436ba6244f19e49e648aec (diff)
downloadfsf-binutils-gdb-2d6f8f50b4d975bfebebb0990b423071f341a157.zip
fsf-binutils-gdb-2d6f8f50b4d975bfebebb0990b423071f341a157.tar.gz
fsf-binutils-gdb-2d6f8f50b4d975bfebebb0990b423071f341a157.tar.bz2
New class reg_buffer
This patch splits regcache, moves part of it to reg_buffer, which is a buffer to hold register contents, and also their status. reg_buffer may or may not hold pseudo registers. Class reg_buffer has methods supply and collect. gdb: 2017-09-22 Yao Qi <yao.qi@linaro.org> : * regcache.c (regcache_descr): (regcache_register_size): (get_regcache_aspace): (regcache::save): (regcache::save): (regcache::restore): (regcache_register_status): (regcache::get_register_status): (regcache::invalidate): (regcache::raw_update): (regcache::raw_read): (regcache::cooked_read): (regcache::cooked_read_value): (regcache_raw_set_cached_value): (regcache_raw_supply): (regcache::raw_supply): (regcache::raw_supply_integer): (regcache_raw_collect): (regcache::raw_collect): * regcache.h (typedef struct cached_reg): (public:): (public:): (protected:): (private:):
-rw-r--r--gdb/regcache.c142
-rw-r--r--gdb/regcache.h84
2 files changed, 139 insertions, 87 deletions
diff --git a/gdb/regcache.c b/gdb/regcache.c
index eb2f967..8978b14 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -152,6 +152,50 @@ regcache_descr (struct gdbarch *gdbarch)
regcache_descr_handle);
}
+reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo)
+ : m_has_pseudo (has_pseudo)
+{
+ gdb_assert (gdbarch != NULL);
+ m_descr = regcache_descr (gdbarch);
+
+ if (has_pseudo)
+ {
+ 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);
+ }
+}
+
+void reg_buffer::validate (int regnum) const
+{
+ gdb_assert (regnum >= 0);
+ if (m_has_pseudo)
+ gdb_assert (regnum < m_descr->nr_cooked_registers);
+ else
+ gdb_assert (regnum < m_descr->nr_raw_registers);
+}
+
+void
+reg_buffer::clear ()
+{
+ if (m_has_pseudo)
+ {
+ memset (m_registers, 0, m_descr->sizeof_cooked_registers);
+ memset (m_register_status, 0, m_descr->sizeof_cooked_register_status);
+ }
+ else
+ {
+ memset (m_registers, 0, m_descr->sizeof_raw_registers);
+ memset (m_register_status, 0, m_descr->sizeof_raw_register_status);
+ }
+}
+
/* Utility functions returning useful register attributes stored in
the regcache descr. */
@@ -190,23 +234,12 @@ regcache_register_size (const struct regcache *regcache, int n)
regcache::regcache (gdbarch *gdbarch, address_space *aspace_,
bool readonly_p_)
- : m_aspace (aspace_), m_readonly_p (readonly_p_)
+ /* The register buffers. A read-only register cache can hold the
+ full [0 .. gdbarch_num_regs + gdbarch_num_pseudo_regs) while a
+ read/write register cache can only hold [0 .. gdbarch_num_regs). */
+ : reg_buffer (gdbarch, readonly_p_),
+ m_aspace (aspace_), m_readonly_p (readonly_p_)
{
- gdb_assert (gdbarch != NULL);
- m_descr = regcache_descr (gdbarch);
-
- if (m_readonly_p)
- {
- 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);
- }
m_ptid = minus_one_ptid;
}
@@ -289,8 +322,9 @@ get_regcache_aspace (const struct regcache *regcache)
/* Return a pointer to register REGNUM's buffer cache. */
gdb_byte *
-regcache::register_buffer (int regnum) const
+reg_buffer::register_buffer (int regnum) const
{
+ validate (regnum);
return m_registers + m_descr->register_offset[regnum];
}
@@ -313,8 +347,7 @@ regcache::save (regcache_cooked_read_ftype *cooked_read,
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);
+ clear ();
/* Copy over any registers (identified by their membership in the
save_reggroup) and mark them as valid. The full [0 .. gdbarch_num_regs +
gdbarch_num_pseudo_regs) range is checked since some architectures need
@@ -331,7 +364,7 @@ regcache::save (regcache_cooked_read_ftype *cooked_read,
if (status != REG_VALID)
memset (dst_buf, 0, register_size (gdbarch, regnum));
- m_register_status[regnum] = status;
+ set_register_status (regnum, status);
}
}
}
@@ -354,7 +387,7 @@ regcache::restore (struct regcache *src)
{
if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
{
- if (src->m_register_status[regnum] == REG_VALID)
+ if (src->get_register_status (regnum) == REG_VALID)
cooked_write (regnum, src->register_buffer (regnum));
}
}
@@ -385,18 +418,20 @@ regcache_register_status (const struct regcache *regcache, int regnum)
}
enum register_status
-regcache::get_register_status (int regnum) const
+reg_buffer::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);
-
+ validate (regnum);
return (enum register_status) m_register_status[regnum];
}
void
+reg_buffer::set_register_status (int regnum, enum register_status status)
+{
+ validate (regnum);
+ m_register_status[regnum] = status;
+}
+
+void
regcache_invalidate (struct regcache *regcache, int regnum)
{
gdb_assert (regcache != NULL);
@@ -409,7 +444,7 @@ regcache::invalidate (int regnum)
gdb_assert (regnum >= 0);
gdb_assert (!m_readonly_p);
gdb_assert (regnum < m_descr->nr_raw_registers);
- m_register_status[regnum] = REG_UNKNOWN;
+ set_register_status (regnum, REG_UNKNOWN);
}
/* Global structure containing the current regcache. */
@@ -573,8 +608,8 @@ regcache::raw_update (int regnum)
/* A number of targets can't access the whole set of raw
registers (because the debug API provides no means to get at
them). */
- if (m_register_status[regnum] == REG_UNKNOWN)
- m_register_status[regnum] = REG_UNAVAILABLE;
+ if (get_register_status (regnum) == REG_UNKNOWN)
+ set_register_status (regnum, REG_UNAVAILABLE);
}
}
@@ -590,13 +625,13 @@ regcache::raw_read (int regnum, gdb_byte *buf)
gdb_assert (buf != NULL);
raw_update (regnum);
- if (m_register_status[regnum] != REG_VALID)
+ if (get_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 get_register_status (regnum);
}
enum register_status
@@ -688,17 +723,17 @@ regcache::cooked_read (int regnum, gdb_byte *buf)
if (regnum < m_descr->nr_raw_registers)
return raw_read (regnum, buf);
else if (m_readonly_p
- && m_register_status[regnum] != REG_UNKNOWN)
+ && get_register_status(regnum) != REG_UNKNOWN)
{
/* Read-only register cache, perhaps the cooked value was
cached? */
- if (m_register_status[regnum] == REG_VALID)
+ if (get_register_status (regnum) == REG_VALID)
memcpy (buf, register_buffer (regnum),
m_descr->sizeof_register[regnum]);
else
memset (buf, 0, m_descr->sizeof_register[regnum]);
- return (enum register_status) m_register_status[regnum];
+ return get_register_status(regnum);
}
else if (gdbarch_pseudo_register_read_value_p (m_descr->gdbarch))
{
@@ -740,7 +775,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_readonly_p && get_register_status (regnum) != REG_UNKNOWN)
|| !gdbarch_pseudo_register_read_value_p (m_descr->gdbarch))
{
struct value *result;
@@ -837,8 +872,10 @@ regcache_raw_set_cached_value (struct regcache *regcache, int regnum,
}
void
-regcache::raw_set_cached_value (int regnum, const gdb_byte *buf)
+reg_buffer::raw_set_cached_value (int regnum, const gdb_byte *buf)
{
+ validate (regnum);
+
memcpy (register_buffer (regnum), buf,
m_descr->sizeof_register[regnum]);
m_register_status[regnum] = REG_VALID;
@@ -1026,13 +1063,12 @@ regcache_raw_supply (struct regcache *regcache, int regnum, const void *buf)
}
void
-regcache::raw_supply (int regnum, const void *buf)
+reg_buffer::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);
+ validate (regnum);
regbuf = register_buffer (regnum);
size = m_descr->sizeof_register[regnum];
@@ -1059,15 +1095,14 @@ regcache::raw_supply (int regnum, const void *buf)
most significant bytes of the integer will be truncated. */
void
-regcache::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
- bool is_signed)
+reg_buffer::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
+ bool is_signed)
{
enum bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch);
gdb_byte *regbuf;
size_t regsize;
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
- gdb_assert (!m_readonly_p);
+ validate (regnum);
regbuf = register_buffer (regnum);
regsize = m_descr->sizeof_register[regnum];
@@ -1082,14 +1117,13 @@ regcache::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
unavailable). */
void
-regcache::raw_supply_zeroed (int regnum)
+reg_buffer::raw_supply_zeroed (int regnum)
{
void *regbuf;
size_t size;
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
- gdb_assert (!m_readonly_p);
-
+ validate (regnum);
+
regbuf = register_buffer (regnum);
size = m_descr->sizeof_register[regnum];
@@ -1107,13 +1141,13 @@ regcache_raw_collect (const struct regcache *regcache, int regnum, void *buf)
}
void
-regcache::raw_collect (int regnum, void *buf) const
+reg_buffer::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);
+ validate (regnum);
regbuf = register_buffer (regnum);
size = m_descr->sizeof_register[regnum];
@@ -1131,14 +1165,14 @@ regcache::raw_collect (int regnum, void *buf) const
most significant bytes of the integer will be truncated. */
void
-regcache::raw_collect_integer (int regnum, gdb_byte *addr, int addr_len,
- bool is_signed) const
+reg_buffer::raw_collect_integer (int regnum, gdb_byte *addr, int addr_len,
+ bool is_signed) const
{
enum bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch);
const gdb_byte *regbuf;
size_t regsize;
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+ validate (regnum);
regbuf = register_buffer (regnum);
regsize = m_descr->sizeof_register[regnum];
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 460d83f..d06c410 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -235,9 +235,59 @@ typedef struct cached_reg
gdb_byte *data;
} cached_reg_t;
+/* Buffer of registers. */
+
+class reg_buffer
+{
+public:
+ reg_buffer (gdbarch *gdbarch, bool has_pseudo);
+
+ DISABLE_COPY_AND_ASSIGN (reg_buffer);
+
+ gdbarch *arch () const;
+
+ virtual ~reg_buffer ()
+ {
+ xfree (m_registers);
+ xfree (m_register_status);
+ }
+
+ void clear ();
+
+ enum register_status get_register_status (int regnum) const;
+ void set_register_status (int regnum, enum register_status status);
+
+ void raw_collect (int regnum, void *buf) const;
+
+ void raw_collect_integer (int regnum, gdb_byte *addr, int addr_len,
+ bool is_signed) const;
+
+ void raw_supply (int regnum, const void *buf);
+
+ void raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
+ bool is_signed);
+
+ void raw_supply_zeroed (int regnum);
+
+ void raw_set_cached_value (int regnum, const gdb_byte *buf);
+
+protected:
+ gdb_byte *register_buffer (int regnum) const;
+ struct regcache_descr *m_descr;
+
+private:
+ void validate (int regnum) const;
+
+ bool m_has_pseudo;
+ /* The register buffers. */
+ gdb_byte *m_registers;
+ /* Register cache status. */
+ signed char *m_register_status;
+};
+
/* The register cache for storing raw register values. */
-class regcache
+class regcache : public reg_buffer
{
public:
regcache (gdbarch *gdbarch, address_space *aspace_)
@@ -252,12 +302,6 @@ public:
DISABLE_COPY_AND_ASSIGN (regcache);
- ~regcache ()
- {
- xfree (m_registers);
- xfree (m_register_status);
- }
-
gdbarch *arch () const;
address_space *aspace () const
@@ -290,22 +334,6 @@ public:
void raw_update (int regnum);
- void raw_collect (int regnum, void *buf) const;
-
- void raw_collect_integer (int regnum, gdb_byte *addr, int addr_len,
- bool is_signed) const;
-
- void raw_supply (int regnum, const void *buf);
-
- void raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
- bool is_signed);
-
- 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);
-
void invalidate (int regnum);
enum register_status raw_read_part (int regnum, int offset, int len,
@@ -349,8 +377,6 @@ protected:
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,
@@ -361,18 +387,10 @@ private:
int regnum, const void *in_buf,
void *out_buf, size_t size) const;
- struct regcache_descr *m_descr;
-
/* The address space of this register cache (for registers where it
makes sense, like PC or SP). */
struct address_space *m_aspace;
- /* The register buffers. A read-only register cache can hold the
- 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