Re: [PATCH v2 03/10] Add reg_buffer_common

Simon Marchi
2018-06-07T20:19:02Z

Hi Alan,

Just some quick comments.

I get this when building on x86-64 with --enable-targets=all:

CXX aarch64-tdep.o
In file included from /home/emaisin/src/binutils-gdb/gdb/nat/aarch64-sve-linux-ptrace.h:29:0,
from /home/emaisin/src/binutils-gdb/gdb/aarch64-tdep.c:61:
/home/emaisin/src/binutils-gdb/gdb/nat/aarch64-linux-sigcontext.h:19:22: error: field ‘head’ has incomplete type ‘_aarch64_ctx’
struct _aarch64_ctx head;
^
/home/emaisin/src/binutils-gdb/gdb/nat/aarch64-linux-sigcontext.h:19:9: note: forward declaration of ‘struct _aarch64_ctx’
struct _aarch64_ctx head;
^

First, we should not include "nat/aarch64-sve-linux-ptrace.h" (a file that only makes
sense when building on AArch64) in aarch64-tdep.c, a file built on all architecture
when including the support for AArch64 debugging. It looks like aarch64-tdep.c
needs sve_vq_from_vl. Maybe that definition could be moved to arch/, which can be
included in aarch64-tdep.c.

Then, is the _aarch64_ctx structure guaranteed to be defined on older AArch64 kernels
or should we include it too?

On 2018-06-06 11:16 AM, Alan Hayward wrote:
> A purely virtual class containing functions from gdb/regcache.h
>
> Both the gdb regcache structures and gdbserver regcache inherit
> directly from reg_buffer_common. This will allow for common
> functions which require the use of a regcache.
>
> 2018-06-06 Alan Hayward <alan.hayward@arm.com>
>
> gdb/
> * common/common-regcache.h (reg_buffer_common): New structure.
> * regcache.h (reg_buffer_common:get_register_status) Add override.
> (reg_buffer_common:raw_supply): Add dummy function.
> reg_buffer_common:raw_collect): Likewise
> (readable_regcache:raw_supply) Add override.
> (detached_regcache:raw_collect) Likewise.
>
> gdbserver/
> * regcache.c (new_register_cache): Use new.
> (free_register_cache): Use delete.
> register_data): Use const.
> (supply_register): Call member function.
> (regcache::raw_supply): Replacement for supply_register.
> (collect_register): Call member function.
> (regcache::raw_collect): Replacement for collect_register.
> (regcache::get_register_status): New function.
> * regcache.h (regcache:raw_supply): Add dummy function.
> (regcache:raw_collect): Likewise
> (regcache:get_register_status) Likewise.
> ---
> gdb/common/common-regcache.h | 8 ++++++++
> gdb/gdbserver/regcache.c | 47 ++++++++++++++++++++++++++++++++------------
> gdb/gdbserver/regcache.h | 18 +++++++++++------
> gdb/regcache.h | 19 ++++++++++++++----
> 4 files changed, 69 insertions(+), 23 deletions(-)
>
> diff --git a/gdb/common/common-regcache.h b/gdb/common/common-regcache.h
> index 696ba00955..487da0a7fb 100644
> --- a/gdb/common/common-regcache.h
> +++ b/gdb/common/common-regcache.h
> @@ -62,4 +62,12 @@ extern enum register_status regcache_raw_read_unsigned
>
> ULONGEST regcache_raw_get_unsigned (struct regcache *regcache, int regnum);
>
> +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 register_status get_register_status (int regnum) const = 0;
> +};

Ideally, we would gather the documentation for these methods here. Where they
are implemented/overriden, we can maybe add a reference such as

/* See struct reg_buffer_common. */

?

> diff --git a/gdb/regcache.h b/gdb/regcache.h
> index 3edddf47e1..b559a10752 100644
> --- a/gdb/regcache.h
> +++ b/gdb/regcache.h
> @@ -139,7 +139,7 @@ typedef struct cached_reg
>
> /* Buffer of registers. */
>
> -class reg_buffer
> +class reg_buffer : public reg_buffer_common
> {
> public:
> reg_buffer (gdbarch *gdbarch, bool has_pseudo);
> @@ -151,13 +151,24 @@ public:
>
> /* Get the availability status of the value of register REGNUM in this
> buffer. */
> - enum register_status get_register_status (int regnum) const;
> + enum register_status get_register_status (int regnum) const override;
>
> virtual ~reg_buffer ()
> {
> xfree (m_registers);
> xfree (m_register_status);
> }
> +
> + virtual void raw_supply (int regnum, const void *buf) override
> + {
> + gdb_assert (false);
> + }
> +
> + virtual void raw_collect (int regnum, void *buf) const override
> + {
> + gdb_assert (false);
> + }

Hmm, I understand why you need to do this right now. But what do you think of the
idea of moving the supply and collect implementations up to reg_buffer? I think
that the supply/collect operations are a good fit to go in reg_buffer. Essentially
they just peek/poke in the buffer. The regcache layer's responsibility is then to
use that register buffer to implement a cache in front of the target registers,
and offer the API to properly read/write registers (including pseudo ones).

For reference here's the patch in the regcache-for-alan branch that did this:
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=0e04bb35765d2717818dddd88328cb975f417b2c;hp=ca9f66e37913be55abaea44813a768b40673a39a

Simon