[v2,04/10] Add regcache raw_compare method
Commit Message
raw_compare returns the same as a memcmp (0 for success,
the diff otherwise). Kept with tristate return as this
feels potentally more useful than a simple true/false return.
(Happy to change if not).
2018-06-06 Alan Hayward <alan.hayward@arm.com>
gdb/
* common/common-regcache.h (raw_compare): New function.
* regcache.c (regcache::raw_compare): Likewise.
* regcache.h (regcache::raw_compare): New declaration.
gdbserver/
* regcache.c (regcache::raw_compare): New function.
* regcache.h (regcache::raw_compare): New declaration.
---
gdb/common/common-regcache.h | 1 +
gdb/gdbserver/regcache.c | 10 ++++++++++
gdb/gdbserver/regcache.h | 5 +++++
gdb/regcache.c | 15 +++++++++++++++
gdb/regcache.h | 11 +++++++++++
5 files changed, 42 insertions(+)
Comments
On 2018-06-06 11:16 AM, Alan Hayward wrote:
> raw_compare returns the same as a memcmp (0 for success,
> the diff otherwise). Kept with tristate return as this
> feels potentally more useful than a simple true/false return.
> (Happy to change if not).
I would err on the bool side, but I don't really mind, the important is
that it's documented properly. We still use many ints as bool in GDB, so
someone seeing an int return value could easily think it's 0 -> not equal,
1 -> equal.
Speaking of doc, I would suggest (as in the previous patch) to centralize
the doc in the class/struct at the root, so we don't duplicate it.
> 2018-06-06 Alan Hayward <alan.hayward@arm.com>
>
> gdb/
> * common/common-regcache.h (raw_compare): New function.
> * regcache.c (regcache::raw_compare): Likewise.
> * regcache.h (regcache::raw_compare): New declaration.
>
> gdbserver/
> * regcache.c (regcache::raw_compare): New function.
> * regcache.h (regcache::raw_compare): New declaration.
> ---
> gdb/common/common-regcache.h | 1 +
> gdb/gdbserver/regcache.c | 10 ++++++++++
> gdb/gdbserver/regcache.h | 5 +++++
> gdb/regcache.c | 15 +++++++++++++++
> gdb/regcache.h | 11 +++++++++++
> 5 files changed, 42 insertions(+)
>
> diff --git a/gdb/common/common-regcache.h b/gdb/common/common-regcache.h
> index 487da0a7fb..e91439bec5 100644
> --- a/gdb/common/common-regcache.h
> +++ b/gdb/common/common-regcache.h
> @@ -67,6 +67,7 @@ struct reg_buffer_common
> virtual ~reg_buffer_common () = default;
> virtual void raw_supply (int regnum, const void *buf) = 0;
> virtual void raw_collect (int regnum, void *buf) const = 0;
> + virtual int raw_compare (int regnum, const void *buf, int offset) const = 0;
> virtual register_status get_register_status (int regnum) const = 0;
> };
>
> diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c
> index 857721ee3d..9648428349 100644
> --- a/gdb/gdbserver/regcache.c
> +++ b/gdb/gdbserver/regcache.c
> @@ -501,3 +501,13 @@ regcache::get_register_status (int regnum) const
> return REG_VALID;
> #endif
> }
> +
> +/* See gdbserver/regcache.h. */
> +
> +int
> +regcache::raw_compare (int regnum, const void *buf, int offset) const
> +{
> + gdb_assert (register_size (tdesc, regnum) > offset);
Should we check ">= offset"? I think it could be useful for some edge cases
where we could avoid an "if (offset < size)" in the caller, if we know offset
could be equal to size. memcmp would return 0 (equal), which is fine.
Maybe assign "register_size (tdesc, regnum)" to a variable (e.g. reg_size)
and use it in both places?
> + return memcmp (buf, register_data (this, regnum, 1) + offset,
> + register_size (tdesc, regnum) - offset);
> +}
> diff --git a/gdb/gdbserver/regcache.h b/gdb/gdbserver/regcache.h
> index 1842f1d9cf..b26f39a8ad 100644
> --- a/gdb/gdbserver/regcache.h
> +++ b/gdb/gdbserver/regcache.h
> @@ -50,6 +50,11 @@ struct regcache : public reg_buffer_common
>
> void raw_collect (int regnum, void *buf) const override;
>
> + /* Compare the contents of the register stored in the regcache (ignoring the
> + first OFFSET bytes) to the contents of BUF (without any offset). Returns
> + the same result as memcmp. */
> + int raw_compare (int regnum, const void *buf, int offset) const override;
> +
> enum register_status get_register_status (int regnum) const override;
> };
>
> diff --git a/gdb/regcache.c b/gdb/regcache.c
> index a914b548ca..383e355e9f 100644
> --- a/gdb/regcache.c
> +++ b/gdb/regcache.c
> @@ -1082,6 +1082,21 @@ regcache::collect_regset (const struct regset *regset,
> transfer_regset (regset, NULL, regnum, NULL, buf, size);
> }
>
> +/* See regcache.h. */
> +
> +int
> +regcache::raw_compare (int regnum, const void *buf, int offset) const
> +{
> + const char *regbuf;
> + size_t size;
> +
> + gdb_assert (buf != NULL);
> + assert_regnum (regnum);
Should we assert that offset is < or <= size here too?
Simon
@@ -67,6 +67,7 @@ struct reg_buffer_common
virtual ~reg_buffer_common () = default;
virtual void raw_supply (int regnum, const void *buf) = 0;
virtual void raw_collect (int regnum, void *buf) const = 0;
+ virtual int raw_compare (int regnum, const void *buf, int offset) const = 0;
virtual register_status get_register_status (int regnum) const = 0;
};
@@ -501,3 +501,13 @@ regcache::get_register_status (int regnum) const
return REG_VALID;
#endif
}
+
+/* See gdbserver/regcache.h. */
+
+int
+regcache::raw_compare (int regnum, const void *buf, int offset) const
+{
+ gdb_assert (register_size (tdesc, regnum) > offset);
+ return memcmp (buf, register_data (this, regnum, 1) + offset,
+ register_size (tdesc, regnum) - offset);
+}
@@ -50,6 +50,11 @@ struct regcache : public reg_buffer_common
void raw_collect (int regnum, void *buf) const override;
+ /* Compare the contents of the register stored in the regcache (ignoring the
+ first OFFSET bytes) to the contents of BUF (without any offset). Returns
+ the same result as memcmp. */
+ int raw_compare (int regnum, const void *buf, int offset) const override;
+
enum register_status get_register_status (int regnum) const override;
};
@@ -1082,6 +1082,21 @@ regcache::collect_regset (const struct regset *regset,
transfer_regset (regset, NULL, regnum, NULL, buf, size);
}
+/* See regcache.h. */
+
+int
+regcache::raw_compare (int regnum, const void *buf, int offset) const
+{
+ const char *regbuf;
+ size_t size;
+
+ gdb_assert (buf != NULL);
+ assert_regnum (regnum);
+
+ regbuf = (const char *) register_buffer (regnum);
+ size = m_descr->sizeof_register[regnum];
+ return memcmp (buf, regbuf + offset, size - offset);
+}
/* Special handling for register PC. */
@@ -169,6 +169,12 @@ public:
gdb_assert (false);
}
+ virtual int raw_compare (int regnum, const void *buf,
+ int offset) const override
+ {
+ gdb_assert (false);
+ }
+
protected:
/* Assert on the range of REGNUM. */
void assert_regnum (int regnum) const;
@@ -325,6 +331,11 @@ public:
void collect_regset (const struct regset *regset, int regnum,
void *buf, size_t size) const;
+ /* Compare the contents of the register stored in the regcache (ignoring the
+ first OFFSET bytes) to the contents of BUF (without any offset). Returns
+ the same result as memcmp. */
+ int raw_compare (int regnum, const void *buf, int offset) const override;
+
/* Return REGCACHE's ptid. */
ptid_t ptid () const