Message ID | 20180606151629.36602-4-alan.hayward@arm.com |
---|---|
State | New |
Headers | show |
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
On 2018-06-07 04:18 PM, Simon Marchi wrote: > 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? Sorry, I mixed things up, this feedback is about patch 2/10 actually. The other comments apply to this patch (3/10). Simon
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; +}; + #endif /* COMMON_REGCACHE_H */ diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c index 0718b9f9a0..857721ee3d 100644 --- a/gdb/gdbserver/regcache.c +++ b/gdb/gdbserver/regcache.c @@ -159,7 +159,7 @@ init_register_cache (struct regcache *regcache, struct regcache * new_register_cache (const struct target_desc *tdesc) { - struct regcache *regcache = XCNEW (struct regcache); + struct regcache *regcache = new struct regcache; gdb_assert (tdesc->registers_size != 0); @@ -174,7 +174,7 @@ free_register_cache (struct regcache *regcache) if (regcache->registers_owned) free (regcache->registers); free (regcache->register_status); - free (regcache); + delete regcache; } } @@ -300,7 +300,7 @@ regcache_register_size (const struct regcache *regcache, int n) } static unsigned char * -register_data (struct regcache *regcache, int n, int fetch) +register_data (const struct regcache *regcache, int n, int fetch) { return (regcache->registers + find_register_by_number (regcache->tdesc, n).offset / 8); @@ -312,23 +312,27 @@ register_data (struct regcache *regcache, int n, int fetch) void supply_register (struct regcache *regcache, int n, const void *buf) +{ + return regcache->raw_supply (n, buf); +} + +void +regcache::raw_supply (int n, const void *buf) { if (buf) { - memcpy (register_data (regcache, n, 0), buf, - register_size (regcache->tdesc, n)); + memcpy (register_data (this, n, 0), buf, register_size (tdesc, n)); #ifndef IN_PROCESS_AGENT - if (regcache->register_status != NULL) - regcache->register_status[n] = REG_VALID; + if (register_status != NULL) + register_status[n] = REG_VALID; #endif } else { - memset (register_data (regcache, n, 0), 0, - register_size (regcache->tdesc, n)); + memset (register_data (this, n, 0), 0, register_size (tdesc, n)); #ifndef IN_PROCESS_AGENT - if (regcache->register_status != NULL) - regcache->register_status[n] = REG_UNAVAILABLE; + if (register_status != NULL) + register_status[n] = REG_UNAVAILABLE; #endif } } @@ -410,10 +414,16 @@ supply_register_by_name (struct regcache *regcache, void collect_register (struct regcache *regcache, int n, void *buf) { - memcpy (buf, register_data (regcache, n, 1), - register_size (regcache->tdesc, n)); + regcache->raw_collect (n, buf); +} + +void +regcache::raw_collect (int n, void *buf) const +{ + memcpy (buf, register_data (this, n, 1), register_size (tdesc, n)); } + enum register_status regcache_raw_read_unsigned (struct regcache *regcache, int regnum, ULONGEST *val) @@ -480,3 +490,14 @@ regcache_write_pc (struct regcache *regcache, CORE_ADDR pc) } #endif + +enum register_status +regcache::get_register_status (int regnum) const +{ +#ifndef IN_PROCESS_AGENT + gdb_assert (regnum >= 0 && regnum < tdesc->reg_defs.size ()); + return (enum register_status) (register_status[regnum]); +#else + return REG_VALID; +#endif +} diff --git a/gdb/gdbserver/regcache.h b/gdb/gdbserver/regcache.h index 2c0df648f6..1842f1d9cf 100644 --- a/gdb/gdbserver/regcache.h +++ b/gdb/gdbserver/regcache.h @@ -28,23 +28,29 @@ struct target_desc; inferior; this is primarily for simplicity, as the performance benefit is minimal. */ -struct regcache +struct regcache : public reg_buffer_common { /* The regcache's target description. */ - const struct target_desc *tdesc; + const struct target_desc *tdesc = nullptr; /* Whether the REGISTERS buffer's contents are valid. If false, we haven't fetched the registers from the target yet. Not that this register cache is _not_ pass-through, unlike GDB's. Note that "valid" here is unrelated to whether the registers are available in a traceframe. For that, check REGISTER_STATUS below. */ - int registers_valid; - int registers_owned; - unsigned char *registers; + int registers_valid = 0; + int registers_owned = 0; + unsigned char *registers = nullptr; #ifndef IN_PROCESS_AGENT /* One of REG_UNAVAILBLE or REG_VALID. */ - unsigned char *register_status; + unsigned char *register_status = nullptr; #endif + + void raw_supply (int regnum, const void *buf) override; + + void raw_collect (int regnum, void *buf) const override; + + enum register_status get_register_status (int regnum) const override; }; struct regcache *init_register_cache (struct regcache *regcache, 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); + } + protected: /* Assert on the range of REGNUM. */ void assert_regnum (int regnum) const; @@ -235,7 +246,7 @@ public: {} /* Supply register REGNUM, whose contents are stored in BUF, to REGCACHE. */ - void raw_supply (int regnum, const void *buf); + void raw_supply (int regnum, const void *buf) override; void raw_supply (int regnum, const reg_buffer &src) { @@ -293,7 +304,7 @@ public: void raw_update (int regnum) override; /* Collect register REGNUM from REGCACHE and store its contents in BUF. */ - void raw_collect (int regnum, void *buf) const; + void raw_collect (int regnum, void *buf) const override; void raw_collect_integer (int regnum, gdb_byte *addr, int addr_len, bool is_signed) const;