public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v3 2/3] Detect SVE when reading aarch64 core files
  2018-08-10 16:09 [PATCH v3 0/3] Detect SVE when reading aarch64 core files Alan Hayward
  2018-08-10 16:09 ` [PATCH v3 3/3] Parse SVE registers in aarch64 core file reading/writing Alan Hayward
@ 2018-08-10 16:09 ` Alan Hayward
  2018-08-10 19:08   ` Simon Marchi
  2018-08-10 16:09 ` [PATCH v3 1/3] Split size in regset section iterators Alan Hayward
  2 siblings, 1 reply; 7+ messages in thread
From: Alan Hayward @ 2018-08-10 16:09 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Add a function which reads the vector length from the SVE section within an
aarch64 core file.

The SVE section in a core file contains a header followed by the registers.
Add defines to easily access the header fields within a buffer.

2018-08-10  Alan Hayward  <alan.hayward@arm.com>

	* aarch64-linux-tdep.c (SVE_HEADER_SIZE_LENGTH): Add define.
	(SVE_HEADER_MAX_SIZE_LENGTH): Likewise.
	(SVE_HEADER_VL_LENGTH): Likewise.
	(SVE_HEADER_MAX_VL_LENGTH): Likewise.
	(SVE_HEADER_FLAGS_LENGTH): Likewise.
	(SVE_HEADER_RESERVED_LENGTH): Likewise.
	(SVE_HEADER_SIZE_OFFSET): Likewise.
	(SVE_HEADER_MAX_SIZE_OFFSET): Likewise.
	(SVE_HEADER_VL_OFFSET): Likewise.
	(SVE_HEADER_MAX_VL_OFFSET): Likewise.
	(SVE_HEADER_FLAGS_OFFSET): Likewise.
	(SVE_HEADER_RESERVED_OFFSET): Likewise.
	(SVE_HEADER_SIZE): Likewise.
	(aarch64_linux_core_read_vq): Add function.
	(aarch64_linux_core_read_description): Check for SVE section.
---
 gdb/aarch64-linux-tdep.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 70 insertions(+), 3 deletions(-)

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 7b63cddbe6..73cb9ea714 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -219,6 +219,74 @@ const struct regset aarch64_linux_fpregset =
     regcache_supply_regset, regcache_collect_regset
   };
 
+/* The fields in an SVE header at the start of a SVE regset.  */
+
+#define SVE_HEADER_SIZE_LENGTH		4
+#define SVE_HEADER_MAX_SIZE_LENGTH	4
+#define SVE_HEADER_VL_LENGTH		2
+#define SVE_HEADER_MAX_VL_LENGTH	2
+#define SVE_HEADER_FLAGS_LENGTH		2
+#define SVE_HEADER_RESERVED_LENGTH	2
+
+#define SVE_HEADER_SIZE_OFFSET		0
+#define SVE_HEADER_MAX_SIZE_OFFSET	\
+  (SVE_HEADER_SIZE_OFFSET + SVE_HEADER_SIZE_LENGTH)
+#define SVE_HEADER_VL_OFFSET		\
+  (SVE_HEADER_MAX_SIZE_OFFSET + SVE_HEADER_MAX_SIZE_LENGTH)
+#define SVE_HEADER_MAX_VL_OFFSET	\
+  (SVE_HEADER_VL_OFFSET + SVE_HEADER_VL_LENGTH)
+#define SVE_HEADER_FLAGS_OFFSET		\
+  (SVE_HEADER_MAX_VL_OFFSET + SVE_HEADER_MAX_VL_LENGTH)
+#define SVE_HEADER_RESERVED_OFFSET	\
+  (SVE_HEADER_FLAGS_OFFSET + SVE_HEADER_FLAGS_LENGTH)
+#define SVE_HEADER_SIZE			\
+  (SVE_HEADER_RESERVED_OFFSET + SVE_HEADER_RESERVED_LENGTH)
+
+/* Get VQ value from SVE section in the core dump.  */
+
+static uint64_t
+aarch64_linux_core_read_vq (struct gdbarch *gdbarch, bfd *abfd)
+{
+  gdb_byte header[SVE_HEADER_SIZE];
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  asection *sve_section = bfd_get_section_by_name (abfd, ".reg-aarch-sve");
+
+  if (sve_section == nullptr)
+    {
+      /* No SVE state.  */
+      return 0;
+    }
+
+  size_t size = bfd_section_size (abfd, sve_section);
+
+  /* Check extended state size.  */
+  if (size < SVE_HEADER_SIZE)
+    {
+      warning (_("'.reg-aarch-sve' section in core file too small."));
+      return 0;
+    }
+
+  if (!bfd_get_section_contents (abfd, sve_section, header, 0, SVE_HEADER_SIZE))
+    {
+      warning (_("Couldn't read sve header from "
+		 "'.reg-aarch-sve' section in core file."));
+      return 0;
+    }
+
+  uint64_t vl = extract_unsigned_integer (header + SVE_HEADER_VL_OFFSET,
+					  SVE_HEADER_VL_LENGTH, byte_order);
+  uint64_t vq = sve_vq_from_vl (vl);
+
+  if (vq > AARCH64_MAX_SVE_VQ || vq == 0)
+    {
+      warning (_("sve header invalid in "
+		 "'.reg-aarch-sve' section in core file."));
+      return 0;
+    }
+
+  return vq;
+}
+
 /* Implement the "regset_from_core_section" gdbarch method.  */
 
 static void
@@ -233,8 +301,7 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
       &aarch64_linux_fpregset, NULL, cb_data);
 }
 
-/* Implement the "core_read_description" gdbarch method.  SVE not yet
-   supported.  */
+/* Implement the "core_read_description" gdbarch method.  */
 
 static const struct target_desc *
 aarch64_linux_core_read_description (struct gdbarch *gdbarch,
@@ -245,7 +312,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
   if (target_auxv_search (target, AT_HWCAP, &aarch64_hwcap) != 1)
     return NULL;
 
-  return aarch64_read_description (0);
+  return aarch64_read_description (aarch64_linux_core_read_vq (gdbarch, abfd));
 }
 
 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
-- 
2.15.2 (Apple Git-101.1)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 0/3] Detect SVE when reading aarch64 core files
@ 2018-08-10 16:09 Alan Hayward
  2018-08-10 16:09 ` [PATCH v3 3/3] Parse SVE registers in aarch64 core file reading/writing Alan Hayward
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Alan Hayward @ 2018-08-10 16:09 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

Reworked previous version based on review comments.

Support both the reading and writing of core files on aarch64 SVE.

SVE core files are doumented here:
https://github.com/torvalds/linux/blob/master/Documentation/arm64/sve.txt
* A NT_ARM_SVE note will be added to each coredump for each thread of the
  dumped process.  The contents will be equivalent to the data that would have
  been read if a PTRACE_GETREGSET of NT_ARM_SVE were executed for each thread
  when the coredump was generated.

The first patch adds support allowing writing of core files for targets with
variable length core files. Currently all targets with variable length core
files do not allow the creation of core files.

The second patch detects SVE state in a core file.
The final patch adds the supply/collect functions for core file parsing.

Checked with make check on x86 (all targets) and aarch64.
Generated core files on SVE emulator both from gdb "generate-core-file"
command and a segfault. Loaded these back into gdb.

Alan Hayward (3):
  Split size in regset section iterators
  Detect SVE when reading aarch64 core files
  Parse SVE registers in aarch64 core file reading/writing

 gdb/aarch64-fbsd-tdep.c  |   8 +-
 gdb/aarch64-linux-tdep.c | 207 +++++++++++++++++++++++++++++++++++++++++++++--
 gdb/alpha-linux-tdep.c   |   4 +-
 gdb/alpha-nbsd-tdep.c    |   6 +-
 gdb/amd64-fbsd-tdep.c    |   8 +-
 gdb/amd64-linux-tdep.c   |   6 +-
 gdb/arm-bsd-tdep.c       |   6 +-
 gdb/arm-fbsd-tdep.c      |   7 +-
 gdb/arm-linux-tdep.c     |  11 +--
 gdb/corelow.c            |  10 ++-
 gdb/fbsd-tdep.c          |  10 +--
 gdb/frv-linux-tdep.c     |   8 +-
 gdb/gdbarch.h            |  12 +--
 gdb/gdbarch.sh           |  12 +--
 gdb/hppa-linux-tdep.c    |   6 +-
 gdb/hppa-nbsd-tdep.c     |   3 +-
 gdb/hppa-obsd-tdep.c     |   6 +-
 gdb/i386-fbsd-tdep.c     |  11 ++-
 gdb/i386-linux-tdep.c    |   9 ++-
 gdb/i386-tdep.c          |   6 +-
 gdb/ia64-linux-tdep.c    |   6 +-
 gdb/linux-tdep.c         |  15 ++--
 gdb/m32r-linux-tdep.c    |   3 +-
 gdb/m68k-bsd-tdep.c      |   6 +-
 gdb/m68k-linux-tdep.c    |   6 +-
 gdb/mips-fbsd-tdep.c     |   8 +-
 gdb/mips-linux-tdep.c    |  14 ++--
 gdb/mips-nbsd-tdep.c     |   8 +-
 gdb/mips64-obsd-tdep.c   |   3 +-
 gdb/mn10300-linux-tdep.c |   8 +-
 gdb/nios2-linux-tdep.c   |   3 +-
 gdb/ppc-fbsd-tdep.c      |   6 +-
 gdb/ppc-linux-tdep.c     |  12 +--
 gdb/ppc-nbsd-tdep.c      |   4 +-
 gdb/ppc-obsd-tdep.c      |   2 +-
 gdb/regcache.h           |   8 ++
 gdb/rs6000-aix-tdep.c    |   4 +-
 gdb/s390-linux-tdep.c    |  23 +++---
 gdb/score-tdep.c         |   4 +-
 gdb/sh-tdep.c            |   6 +-
 gdb/sparc-tdep.c         |   6 +-
 gdb/tilegx-linux-tdep.c  |   4 +-
 gdb/vax-tdep.c           |   2 +-
 gdb/xtensa-tdep.c        |   4 +-
 44 files changed, 385 insertions(+), 136 deletions(-)

-- 
2.15.2 (Apple Git-101.1)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/3] Split size in regset section iterators
  2018-08-10 16:09 [PATCH v3 0/3] Detect SVE when reading aarch64 core files Alan Hayward
  2018-08-10 16:09 ` [PATCH v3 3/3] Parse SVE registers in aarch64 core file reading/writing Alan Hayward
  2018-08-10 16:09 ` [PATCH v3 2/3] Detect SVE when reading aarch64 core files Alan Hayward
@ 2018-08-10 16:09 ` Alan Hayward
  2018-08-10 18:57   ` Simon Marchi
  2 siblings, 1 reply; 7+ messages in thread
From: Alan Hayward @ 2018-08-10 16:09 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

In the existing code, when using the regset section iteration functions, the
size parameter is used in different ways.

With collect, size is used to create the buffer in which to write the regset.
(see linux-tdep.c::linux_collect_regset_section_cb).

With supply, size is used to confirm the existing regset is the correct size.
If REGSET_VARIABLE_SIZE is set then the regset can be bigger than size.
Effectively, size is the minimum possible size of the regset.
(see corelow.c::get_core_register_section).

There are currently no targets with both REGSET_VARIABLE_SIZE and a collect
function.
In SVE, a corefile can contain one of two formats after the header, both of
which are different sizes. However, when writing a core file, we always want
to write out the full bigger size.

To allow support of collects for REGSET_VARIABLE_SIZE we need two sizes.
This is done by adding supply_size and collect_size.

2018-08-10  Alan Hayward  <alan.hayward@arm.com>

	* aarch64-fbsd-tdep.c
	(aarch64_fbsd_iterate_over_regset_sections): Add supply_size and
	collect_size.
	* aarch64-linux-tdep.c
	(aarch64_linux_iterate_over_regset_sections): Likewise.
	* alpha-linux-tdep.c
	(alpha_linux_iterate_over_regset_sections):
	* alpha-nbsd-tdep.c
	(alphanbsd_iterate_over_regset_sections): Likewise.
	* amd64-fbsd-tdep.c
	(amd64fbsd_iterate_over_regset_sections): Likewise.
	* amd64-linux-tdep.c
	(amd64_linux_iterate_over_regset_sections): Likewise.
	* arm-bsd-tdep.c
	(armbsd_iterate_over_regset_sections): Likewise.
	* arm-fbsd-tdep.c
	(arm_fbsd_iterate_over_regset_sections): Likewise.
	* arm-linux-tdep.c
	(arm_linux_iterate_over_regset_sections): Likewise.
	* corelow.c (get_core_registers_cb): Likewise.
	(core_target::fetch_registers): Likewise.
	* fbsd-tdep.c (fbsd_collect_regset_section_cb): Likewise.
	* frv-linux-tdep.c (frv_linux_iterate_over_regset_sections): Likewise.
	* gdbarch.h (void): Regenerate.
	* gdbarch.sh: Add supply_size and collect_size.
	* hppa-linux-tdep.c (hppa_linux_iterate_over_regset_sections): Likewise.
	* hppa-nbsd-tdep.c (hppanbsd_iterate_over_regset_sections): Likewise.
	* hppa-obsd-tdep.c (hppaobsd_iterate_over_regset_sections): Likewise.
	* i386-fbsd-tdep.c (i386fbsd_iterate_over_regset_sections): Likewise.
	* i386-linux-tdep.c (i386_linux_iterate_over_regset_sections): Likewise.
	* i386-tdep.c (i386_iterate_over_regset_sections): Likewise.
	* ia64-linux-tdep.c (ia64_linux_iterate_over_regset_sections): Likewise.
	* linux-tdep.c (linux_collect_regset_section_cb): Likewise.
	* m32r-linux-tdep.c (m32r_linux_iterate_over_regset_sections): Likewise.
	* m68k-bsd-tdep.c (m68kbsd_iterate_over_regset_sections): Likewise.
	* m68k-linux-tdep.c (m68k_linux_iterate_over_regset_sections): Likewise.
	* mips-fbsd-tdep.c (mips_fbsd_iterate_over_regset_sections): Likewise.
	* mips-linux-tdep.c (mips_linux_iterate_over_regset_sections): Likewise.
	* mips-nbsd-tdep.c (mipsnbsd_iterate_over_regset_sections): Likewise.
	* mips64-obsd-tdep.c (mips64obsd_iterate_over_regset_sections): Likewise.
	* mn10300-linux-tdep.c (am33_iterate_over_regset_sections): Likewise.
	* nios2-linux-tdep.c (nios2_iterate_over_regset_sections): Likewise.
	* ppc-fbsd-tdep.c (ppcfbsd_iterate_over_regset_sections): Likewise.
	* ppc-linux-tdep.c (ppc_linux_iterate_over_regset_sections): Likewise.
	* ppc-nbsd-tdep.c (ppcnbsd_iterate_over_regset_sections): Likewise.
	* ppc-obsd-tdep.c (ppcobsd_iterate_over_regset_sections): Likewise.
	* rs6000-aix-tdep.c (rs6000_aix_iterate_over_regset_sections): Likewise.
	* s390-linux-tdep.c (s390_iterate_over_regset_sections): Likewise.
	* score-tdep.c (score7_linux_iterate_over_regset_sections): Likewise.
	* sh-tdep.c (sh_iterate_over_regset_sections): Likewise.
	* sparc-tdep.c (sparc_iterate_over_regset_sections): Likewise.
	* tilegx-linux-tdep.c (tilegx_iterate_over_regset_sections): Likewise.
	* vax-tdep.c (vax_iterate_over_regset_sections): Likewise.
	* xtensa-tdep.c (xtensa_iterate_over_regset_sections): Likewise.
---
 gdb/aarch64-fbsd-tdep.c  |  8 ++++----
 gdb/aarch64-linux-tdep.c |  8 ++++----
 gdb/alpha-linux-tdep.c   |  4 ++--
 gdb/alpha-nbsd-tdep.c    |  6 ++++--
 gdb/amd64-fbsd-tdep.c    |  8 +++++---
 gdb/amd64-linux-tdep.c   |  6 +++---
 gdb/arm-bsd-tdep.c       |  6 ++++--
 gdb/arm-fbsd-tdep.c      |  7 ++++---
 gdb/arm-linux-tdep.c     | 11 ++++++-----
 gdb/corelow.c            | 10 ++++++++--
 gdb/fbsd-tdep.c          | 10 +++++-----
 gdb/frv-linux-tdep.c     |  8 ++++----
 gdb/gdbarch.h            | 12 +++++++-----
 gdb/gdbarch.sh           | 12 +++++++-----
 gdb/hppa-linux-tdep.c    |  6 +++---
 gdb/hppa-nbsd-tdep.c     |  3 ++-
 gdb/hppa-obsd-tdep.c     |  6 ++++--
 gdb/i386-fbsd-tdep.c     | 11 +++++++----
 gdb/i386-linux-tdep.c    |  9 +++++----
 gdb/i386-tdep.c          |  6 ++++--
 gdb/ia64-linux-tdep.c    |  6 ++++--
 gdb/linux-tdep.c         | 15 ++++++++++-----
 gdb/m32r-linux-tdep.c    |  3 ++-
 gdb/m68k-bsd-tdep.c      |  6 ++++--
 gdb/m68k-linux-tdep.c    |  6 ++++--
 gdb/mips-fbsd-tdep.c     |  8 ++++----
 gdb/mips-linux-tdep.c    | 14 ++++++++------
 gdb/mips-nbsd-tdep.c     |  8 ++++----
 gdb/mips64-obsd-tdep.c   |  3 ++-
 gdb/mn10300-linux-tdep.c |  8 ++++----
 gdb/nios2-linux-tdep.c   |  3 ++-
 gdb/ppc-fbsd-tdep.c      |  6 +++---
 gdb/ppc-linux-tdep.c     | 12 ++++++------
 gdb/ppc-nbsd-tdep.c      |  4 ++--
 gdb/ppc-obsd-tdep.c      |  2 +-
 gdb/rs6000-aix-tdep.c    |  4 ++--
 gdb/s390-linux-tdep.c    | 23 ++++++++++++-----------
 gdb/score-tdep.c         |  4 ++--
 gdb/sh-tdep.c            |  6 ++++--
 gdb/sparc-tdep.c         |  6 ++++--
 gdb/tilegx-linux-tdep.c  |  4 ++--
 gdb/vax-tdep.c           |  2 +-
 gdb/xtensa-tdep.c        |  4 ++--
 43 files changed, 181 insertions(+), 133 deletions(-)

diff --git a/gdb/aarch64-fbsd-tdep.c b/gdb/aarch64-fbsd-tdep.c
index 21beb5b77c..9f8b1366ce 100644
--- a/gdb/aarch64-fbsd-tdep.c
+++ b/gdb/aarch64-fbsd-tdep.c
@@ -169,10 +169,10 @@ aarch64_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					   void *cb_data,
 					   const struct regcache *regcache)
 {
-  cb (".reg", AARCH64_FBSD_SIZEOF_GREGSET, &aarch64_fbsd_gregset,
-      NULL, cb_data);
-  cb (".reg2", AARCH64_FBSD_SIZEOF_FPREGSET, &aarch64_fbsd_fpregset,
-      NULL, cb_data);
+  cb (".reg", AARCH64_FBSD_SIZEOF_GREGSET, AARCH64_FBSD_SIZEOF_GREGSET,
+      &aarch64_fbsd_gregset, NULL, cb_data);
+  cb (".reg2", AARCH64_FBSD_SIZEOF_FPREGSET, AARCH64_FBSD_SIZEOF_FPREGSET,
+      &aarch64_fbsd_fpregset, NULL, cb_data);
 }
 
 /* Implement the 'init_osabi' method of struct gdb_osabi_handler.  */
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 93b6d416a3..7b63cddbe6 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -227,10 +227,10 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					    void *cb_data,
 					    const struct regcache *regcache)
 {
-  cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET, &aarch64_linux_gregset,
-      NULL, cb_data);
-  cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, &aarch64_linux_fpregset,
-      NULL, cb_data);
+  cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET, AARCH64_LINUX_SIZEOF_GREGSET,
+      &aarch64_linux_gregset, NULL, cb_data);
+  cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, AARCH64_LINUX_SIZEOF_FPREGSET,
+      &aarch64_linux_fpregset, NULL, cb_data);
 }
 
 /* Implement the "core_read_description" gdbarch method.  SVE not yet
diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c
index 8bacb10aa1..913a420401 100644
--- a/gdb/alpha-linux-tdep.c
+++ b/gdb/alpha-linux-tdep.c
@@ -238,8 +238,8 @@ alpha_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					  void *cb_data,
 					  const struct regcache *regcache)
 {
-  cb (".reg", 32 * 8, &alpha_linux_gregset, NULL, cb_data);
-  cb (".reg2", 32 * 8, &alpha_linux_fpregset, NULL, cb_data);
+  cb (".reg", 32 * 8, 32 * 8, &alpha_linux_gregset, NULL, cb_data);
+  cb (".reg2", 32 * 8, 32 * 8, &alpha_linux_fpregset, NULL, cb_data);
 }
 
 /* Implementation of `gdbarch_gdb_signal_from_target', as defined in
diff --git a/gdb/alpha-nbsd-tdep.c b/gdb/alpha-nbsd-tdep.c
index dffab3fb37..694e3d3555 100644
--- a/gdb/alpha-nbsd-tdep.c
+++ b/gdb/alpha-nbsd-tdep.c
@@ -161,8 +161,10 @@ alphanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					void *cb_data,
 					const struct regcache *regcache)
 {
-  cb (".reg", ALPHANBSD_SIZEOF_GREGS, &alphanbsd_gregset, NULL, cb_data);
-  cb (".reg2", ALPHANBSD_SIZEOF_FPREGS, &alphanbsd_fpregset, NULL, cb_data);
+  cb (".reg", ALPHANBSD_SIZEOF_GREGS, ALPHANBSD_SIZEOF_GREGS,
+      &alphanbsd_gregset, NULL, cb_data);
+  cb (".reg2", ALPHANBSD_SIZEOF_FPREGS, ALPHANBSD_SIZEOF_FPREGS,
+      &alphanbsd_fpregset, NULL, cb_data);
 }
 \f
 
diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c
index f5bf1985b6..7f7ecfcf11 100644
--- a/gdb/amd64-fbsd-tdep.c
+++ b/gdb/amd64-fbsd-tdep.c
@@ -196,9 +196,11 @@ amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data);
-  cb (".reg2", tdep->sizeof_fpregset, &amd64_fpregset, NULL, cb_data);
-  cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0),
+  cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, &i386_gregset, NULL,
+      cb_data);
+  cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, &amd64_fpregset,
+      NULL, cb_data);
+  cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
       &amd64fbsd_xstateregset, "XSAVE extended state", cb_data);
 }
 
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index 7fe37d83f6..7ab43897ab 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -1651,9 +1651,9 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", 27 * 8, &i386_gregset, NULL, cb_data);
-  cb (".reg2", 512, &amd64_fpregset, NULL, cb_data);
-  cb (".reg-xstate",  X86_XSTATE_SIZE (tdep->xcr0),
+  cb (".reg", 27 * 8, 27 * 8, &i386_gregset, NULL, cb_data);
+  cb (".reg2", 512, 512, &amd64_fpregset, NULL, cb_data);
+  cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
       &amd64_linux_xstateregset, "XSAVE extended state", cb_data);
 }
 
diff --git a/gdb/arm-bsd-tdep.c b/gdb/arm-bsd-tdep.c
index a2719caa4c..8025ab3dee 100644
--- a/gdb/arm-bsd-tdep.c
+++ b/gdb/arm-bsd-tdep.c
@@ -117,6 +117,8 @@ armbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				     void *cb_data,
 				     const struct regcache *regcache)
 {
-  cb (".reg", ARMBSD_SIZEOF_GREGS, &armbsd_gregset, NULL, cb_data);
-  cb (".reg2", ARMBSD_SIZEOF_FPREGS, &armbsd_fpregset, NULL, cb_data);
+  cb (".reg", ARMBSD_SIZEOF_GREGS, ARMBSD_SIZEOF_GREGS, &armbsd_gregset, NULL,
+      cb_data);
+  cb (".reg2", ARMBSD_SIZEOF_FPREGS, ARMBSD_SIZEOF_FPREGS, &armbsd_fpregset,
+      NULL, cb_data);
 }
diff --git a/gdb/arm-fbsd-tdep.c b/gdb/arm-fbsd-tdep.c
index 4ad3abdffa..d2af21bf2c 100644
--- a/gdb/arm-fbsd-tdep.c
+++ b/gdb/arm-fbsd-tdep.c
@@ -175,14 +175,15 @@ arm_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", ARM_FBSD_SIZEOF_GREGSET, &arm_fbsd_gregset, NULL, cb_data);
+  cb (".reg", ARM_FBSD_SIZEOF_GREGSET, ARM_FBSD_SIZEOF_GREGSET,
+      &arm_fbsd_gregset, NULL, cb_data);
 
   /* While FreeBSD/arm cores do contain a NT_FPREGSET / ".reg2"
      register set, it is not populated with register values by the
      kernel but just contains all zeroes.  */
   if (tdep->vfp_register_count > 0)
-    cb (".reg-arm-vfp", ARM_FBSD_SIZEOF_VFPREGSET, &arm_fbsd_vfpregset,
-	"VFP floating-point", cb_data);
+    cb (".reg-arm-vfp", ARM_FBSD_SIZEOF_VFPREGSET, ARM_FBSD_SIZEOF_VFPREGSET,
+	&arm_fbsd_vfpregset, "VFP floating-point", cb_data);
 }
 
 /* Lookup a target description from a target's AT_HWCAP auxiliary
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 264e8ca42b..36198b7cdc 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -712,14 +712,15 @@ arm_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", ARM_LINUX_SIZEOF_GREGSET, &arm_linux_gregset, NULL, cb_data);
+  cb (".reg", ARM_LINUX_SIZEOF_GREGSET, ARM_LINUX_SIZEOF_GREGSET,
+      &arm_linux_gregset, NULL, cb_data);
 
   if (tdep->vfp_register_count > 0)
-    cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, &arm_linux_vfpregset,
-	"VFP floating-point", cb_data);
+    cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, ARM_LINUX_SIZEOF_VFP,
+	&arm_linux_vfpregset, "VFP floating-point", cb_data);
   else if (tdep->have_fpa_registers)
-    cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, &arm_linux_fpregset,
-	"FPA floating-point", cb_data);
+    cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, ARM_LINUX_SIZEOF_NWFPE,
+    	&arm_linux_fpregset, "FPA floating-point", cb_data);
 }
 
 /* Determine target description from core file.  */
diff --git a/gdb/corelow.c b/gdb/corelow.c
index d3336cf785..8e9ac9a328 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -636,12 +636,17 @@ struct get_core_registers_cb_data
    register note section. */
 
 static void
-get_core_registers_cb (const char *sect_name, int size,
+get_core_registers_cb (const char *sect_name, int supply_size, int collect_size,
 		       const struct regset *regset,
 		       const char *human_name, void *cb_data)
 {
   auto *data = (get_core_registers_cb_data *) cb_data;
   bool required = false;
+  bool variable_size_section = (regset != NULL
+				&& regset->flags & REGSET_VARIABLE_SIZE);
+
+  if (!variable_size_section)
+    gdb_assert (supply_size == collect_size);
 
   if (strcmp (sect_name, ".reg") == 0)
     {
@@ -658,7 +663,8 @@ get_core_registers_cb (const char *sect_name, int size,
   /* The 'which' parameter is only used when no regset is provided.
      Thus we just set it to -1. */
   data->target->get_core_register_section (data->regcache, regset, sect_name,
-					   size, -1, human_name, required);
+					   supply_size, -1, human_name,
+					   required);
 }
 
 /* Get the registers out of a core file.  This is the machine-
diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
index ac5b3bfa12..78d0c3d830 100644
--- a/gdb/fbsd-tdep.c
+++ b/gdb/fbsd-tdep.c
@@ -428,8 +428,8 @@ struct fbsd_collect_regset_section_cb_data
 };
 
 static void
-fbsd_collect_regset_section_cb (const char *sect_name, int size,
-				const struct regset *regset,
+fbsd_collect_regset_section_cb (const char *sect_name, int supply_size,
+				int collect_size, const struct regset *regset,
 				const char *human_name, void *cb_data)
 {
   char *buf;
@@ -441,8 +441,8 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size,
 
   gdb_assert (regset->collect_regset);
 
-  buf = (char *) xmalloc (size);
-  regset->collect_regset (regset, data->regcache, -1, buf, size);
+  buf = (char *) xmalloc (collect_size);
+  regset->collect_regset (regset, data->regcache, -1, buf, collect_size);
 
   /* PRSTATUS still needs to be treated specially.  */
   if (strcmp (sect_name, ".reg") == 0)
@@ -452,7 +452,7 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size,
   else
     data->note_data = (char *) elfcore_write_register_note
       (data->obfd, data->note_data, data->note_size,
-       sect_name, buf, size);
+       sect_name, buf, collect_size);
   xfree (buf);
 
   if (data->note_data == NULL)
diff --git a/gdb/frv-linux-tdep.c b/gdb/frv-linux-tdep.c
index c47f1f24f0..655c48d787 100644
--- a/gdb/frv-linux-tdep.c
+++ b/gdb/frv-linux-tdep.c
@@ -445,10 +445,10 @@ frv_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					void *cb_data,
 					const struct regcache *regcache)
 {
-  cb (".reg", sizeof (frv_elf_gregset_t), &frv_linux_gregset,
-      NULL, cb_data);
-  cb (".reg2", sizeof (frv_elf_fpregset_t), &frv_linux_fpregset,
-      NULL, cb_data);
+  cb (".reg", sizeof (frv_elf_gregset_t), sizeof (frv_elf_gregset_t),
+      &frv_linux_gregset, NULL, cb_data);
+  cb (".reg2", sizeof (frv_elf_fpregset_t), sizeof (frv_elf_fpregset_t),
+      &frv_linux_fpregset, NULL, cb_data);
 }
 
 \f
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 0df1fd1692..3f62bf79a8 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -92,13 +92,15 @@ typedef int (iterate_over_objfiles_in_search_order_cb_ftype)
 
 /* Callback type for regset section iterators.  The callback usually
    invokes the REGSET's supply or collect method, to which it must
-   pass a buffer with at least the given SIZE.  SECT_NAME is a BFD
-   section name, and HUMAN_NAME is used for diagnostic messages.
-   CB_DATA should have been passed unchanged through the iterator.  */
+   pass a buffer - for collects this buffer will need to created using
+   COLLECT_SIZE, for supply the existing buffer being read from should
+   be at least SUPPLY_SIZE.  SECT_NAME is a BFD section name, and HUMAN_NAME
+   is used for diagnostic messages.  CB_DATA should have been passed
+   unchanged through the iterator.  */
 
 typedef void (iterate_over_regset_sections_cb)
-  (const char *sect_name, int size, const struct regset *regset,
-   const char *human_name, void *cb_data);
+  (const char *sect_name, int supply_size, int collect_size,
+   const struct regset *regset, const char *human_name, void *cb_data);
 
 
 /* The following are pre-initialized by GDBARCH.  */
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 447394381e..f8e03461ae 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1316,13 +1316,15 @@ typedef int (iterate_over_objfiles_in_search_order_cb_ftype)
 
 /* Callback type for regset section iterators.  The callback usually
    invokes the REGSET's supply or collect method, to which it must
-   pass a buffer with at least the given SIZE.  SECT_NAME is a BFD
-   section name, and HUMAN_NAME is used for diagnostic messages.
-   CB_DATA should have been passed unchanged through the iterator.  */
+   pass a buffer - for collects this buffer will need to created using
+   COLLECT_SIZE, for supply the existing buffer being read from should
+   be at least SUPPLY_SIZE.  SECT_NAME is a BFD section name, and HUMAN_NAME
+   is used for diagnostic messages.  CB_DATA should have been passed
+   unchanged through the iterator.  */
 
 typedef void (iterate_over_regset_sections_cb)
-  (const char *sect_name, int size, const struct regset *regset,
-   const char *human_name, void *cb_data);
+  (const char *sect_name, int supply_size, int collect_size,
+   const struct regset *regset, const char *human_name, void *cb_data);
 EOF
 
 # function typedef's
diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c
index 080fc0449b..c4c169fe98 100644
--- a/gdb/hppa-linux-tdep.c
+++ b/gdb/hppa-linux-tdep.c
@@ -479,9 +479,9 @@ hppa_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", 80 * tdep->bytes_per_address, &hppa_linux_regset,
-      NULL, cb_data);
-  cb (".reg2", 64 * 4, &hppa_linux_fpregset, NULL, cb_data);
+  cb (".reg", 80 * tdep->bytes_per_address, 80 * tdep->bytes_per_address,
+      &hppa_linux_regset, NULL, cb_data);
+  cb (".reg2", 64 * 4, 64 * 4, &hppa_linux_fpregset, NULL, cb_data);
 }
 
 static void
diff --git a/gdb/hppa-nbsd-tdep.c b/gdb/hppa-nbsd-tdep.c
index f9932b5b80..49bf17b1cc 100644
--- a/gdb/hppa-nbsd-tdep.c
+++ b/gdb/hppa-nbsd-tdep.c
@@ -190,7 +190,8 @@ hppanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				       void *cb_data,
 				       const struct regcache *regcache)
 {
-  cb (".reg", HPPANBSD_SIZEOF_GREGS, &hppanbsd_gregset, NULL, cb_data);
+  cb (".reg", HPPANBSD_SIZEOF_GREGS, HPPANBSD_SIZEOF_GREGS, &hppanbsd_gregset,
+      NULL, cb_data);
 }
 \f
 static void
diff --git a/gdb/hppa-obsd-tdep.c b/gdb/hppa-obsd-tdep.c
index 403e9ddc82..97d5a2bf01 100644
--- a/gdb/hppa-obsd-tdep.c
+++ b/gdb/hppa-obsd-tdep.c
@@ -149,8 +149,10 @@ hppaobsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				       void *cb_data,
 				       const struct regcache *regcache)
 {
-  cb (".reg", HPPAOBSD_SIZEOF_GREGS, &hppaobsd_gregset, NULL, cb_data);
-  cb (".reg2", HPPAOBSD_SIZEOF_FPREGS, &hppaobsd_fpregset, NULL, cb_data);
+  cb (".reg", HPPAOBSD_SIZEOF_GREGS, HPPAOBSD_SIZEOF_GREGS, &hppaobsd_gregset,
+      NULL, cb_data);
+  cb (".reg2", HPPAOBSD_SIZEOF_FPREGS, HPPAOBSD_SIZEOF_FPREGS,
+      &hppaobsd_fpregset, NULL, cb_data);
 }
 \f
 
diff --git a/gdb/i386-fbsd-tdep.c b/gdb/i386-fbsd-tdep.c
index ebc75a8d58..22c8d4506b 100644
--- a/gdb/i386-fbsd-tdep.c
+++ b/gdb/i386-fbsd-tdep.c
@@ -309,12 +309,15 @@ i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data);
-  cb (".reg2", tdep->sizeof_fpregset, &i386_fpregset, NULL, cb_data);
+  cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, &i386_gregset, NULL,
+      cb_data);
+  cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, &i386_fpregset,
+      NULL, cb_data);
 
   if (tdep->xcr0 & X86_XSTATE_AVX)
-    cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0),
-	&i386fbsd_xstateregset, "XSAVE extended state", cb_data);
+    cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
+	X86_XSTATE_SIZE (tdep->xcr0), &i386fbsd_xstateregset,
+	"XSAVE extended state", cb_data);
 }
 
 static void
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index f5b039b794..802c41fe72 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -764,16 +764,17 @@ i386_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", 68, &i386_gregset, NULL, cb_data);
+  cb (".reg", 68, 68, &i386_gregset, NULL, cb_data);
 
   if (tdep->xcr0 & X86_XSTATE_AVX)
     cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
-	&i386_linux_xstateregset, "XSAVE extended state", cb_data);
+	X86_XSTATE_SIZE (tdep->xcr0), &i386_linux_xstateregset,
+	"XSAVE extended state", cb_data);
   else if (tdep->xcr0 & X86_XSTATE_SSE)
-    cb (".reg-xfp", 512, &i386_fpregset, "extended floating-point",
+    cb (".reg-xfp", 512, 512, &i386_fpregset, "extended floating-point",
 	cb_data);
   else
-    cb (".reg2", 108, &i386_fpregset, NULL, cb_data);
+    cb (".reg2", 108, 108, &i386_fpregset, NULL, cb_data);
 }
 
 /* Linux kernel shows PC value after the 'int $0x80' instruction even if
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index b1d502f482..a6994aaf12 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -3910,9 +3910,11 @@ i386_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data);
+  cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, &i386_gregset, NULL,
+      cb_data);
   if (tdep->sizeof_fpregset)
-    cb (".reg2", tdep->sizeof_fpregset, tdep->fpregset, NULL, cb_data);
+    cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, tdep->fpregset,
+	NULL, cb_data);
 }
 \f
 
diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c
index 19d0cf2deb..0054f5a514 100644
--- a/gdb/ia64-linux-tdep.c
+++ b/gdb/ia64-linux-tdep.c
@@ -207,8 +207,10 @@ ia64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					 void *cb_data,
 					 const struct regcache *regcache)
 {
-  cb (".reg", IA64_LINUX_GREGS_SIZE, &ia64_linux_gregset, NULL, cb_data);
-  cb (".reg2", IA64_LINUX_FPREGS_SIZE, &ia64_linux_fpregset, NULL, cb_data);
+  cb (".reg", IA64_LINUX_GREGS_SIZE, IA64_LINUX_GREGS_SIZE, &ia64_linux_gregset,
+      NULL, cb_data);
+  cb (".reg2", IA64_LINUX_FPREGS_SIZE, IA64_LINUX_FPREGS_SIZE,
+      &ia64_linux_fpregset, NULL, cb_data);
 }
 
 static void
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 3cfa2a5aa4..5801ab5222 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -1579,21 +1579,26 @@ struct linux_collect_regset_section_cb_data
    regset in the corefile note section.  */
 
 static void
-linux_collect_regset_section_cb (const char *sect_name, int size,
-				 const struct regset *regset,
+linux_collect_regset_section_cb (const char *sect_name, int supply_size,
+				 int collect_size, const struct regset *regset,
 				 const char *human_name, void *cb_data)
 {
   char *buf;
   struct linux_collect_regset_section_cb_data *data
     = (struct linux_collect_regset_section_cb_data *) cb_data;
+  bool variable_size_section = (regset != NULL
+				&& regset->flags & REGSET_VARIABLE_SIZE);
+
+  if (!variable_size_section)
+    gdb_assert (supply_size == collect_size);
 
   if (data->abort_iteration)
     return;
 
   gdb_assert (regset && regset->collect_regset);
 
-  buf = (char *) xmalloc (size);
-  regset->collect_regset (regset, data->regcache, -1, buf, size);
+  buf = (char *) xmalloc (collect_size);
+  regset->collect_regset (regset, data->regcache, -1, buf, collect_size);
 
   /* PRSTATUS still needs to be treated specially.  */
   if (strcmp (sect_name, ".reg") == 0)
@@ -1603,7 +1608,7 @@ linux_collect_regset_section_cb (const char *sect_name, int size,
   else
     data->note_data = (char *) elfcore_write_register_note
       (data->obfd, data->note_data, data->note_size,
-       sect_name, buf, size);
+       sect_name, buf, collect_size);
   xfree (buf);
 
   if (data->note_data == NULL)
diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c
index be35b699c2..aa441592a6 100644
--- a/gdb/m32r-linux-tdep.c
+++ b/gdb/m32r-linux-tdep.c
@@ -440,7 +440,8 @@ m32r_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					 void *cb_data,
 					 const struct regcache *regcache)
 {
-  cb (".reg", M32R_LINUX_GREGS_SIZE, &m32r_linux_gregset, NULL, cb_data);
+  cb (".reg", M32R_LINUX_GREGS_SIZE, M32R_LINUX_GREGS_SIZE, &m32r_linux_gregset,
+      NULL, cb_data);
 }
 
 static void
diff --git a/gdb/m68k-bsd-tdep.c b/gdb/m68k-bsd-tdep.c
index 2f53870b98..0991407557 100644
--- a/gdb/m68k-bsd-tdep.c
+++ b/gdb/m68k-bsd-tdep.c
@@ -123,8 +123,10 @@ m68kbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				      void *cb_data,
 				      const struct regcache *regcache)
 {
-  cb (".reg", M68KBSD_SIZEOF_GREGS, &m68kbsd_gregset, NULL, cb_data);
-  cb (".reg2", M68KBSD_SIZEOF_FPREGS, &m68kbsd_fpregset, NULL, cb_data);
+  cb (".reg", M68KBSD_SIZEOF_GREGS, M68KBSD_SIZEOF_GREGS, &m68kbsd_gregset,
+      NULL, cb_data);
+  cb (".reg2", M68KBSD_SIZEOF_FPREGS, M68KBSD_SIZEOF_FPREGS, &m68kbsd_fpregset,
+      NULL, cb_data);
 }
 \f
 
diff --git a/gdb/m68k-linux-tdep.c b/gdb/m68k-linux-tdep.c
index 11cde0b09f..8ebf7913e5 100644
--- a/gdb/m68k-linux-tdep.c
+++ b/gdb/m68k-linux-tdep.c
@@ -374,8 +374,10 @@ m68k_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					 void *cb_data,
 					 const struct regcache *regcache)
 {
-  cb (".reg", M68K_LINUX_GREGS_SIZE, &m68k_linux_gregset, NULL, cb_data);
-  cb (".reg2", M68K_LINUX_FPREGS_SIZE, &m68k_linux_fpregset, NULL, cb_data);
+  cb (".reg", M68K_LINUX_GREGS_SIZE, M68K_LINUX_GREGS_SIZE, &m68k_linux_gregset,
+      NULL, cb_data);
+  cb (".reg2", M68K_LINUX_FPREGS_SIZE, M68K_LINUX_FPREGS_SIZE,
+      &m68k_linux_fpregset, NULL, cb_data);
 }
 
 static void
diff --git a/gdb/mips-fbsd-tdep.c b/gdb/mips-fbsd-tdep.c
index c3075b23fc..e341088702 100644
--- a/gdb/mips-fbsd-tdep.c
+++ b/gdb/mips-fbsd-tdep.c
@@ -245,10 +245,10 @@ mips_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   size_t regsize = mips_abi_regsize (gdbarch);
 
-  cb (".reg", MIPS_FBSD_NUM_GREGS * regsize, &mips_fbsd_gregset,
-      NULL, cb_data);
-  cb (".reg2", MIPS_FBSD_NUM_FPREGS * regsize, &mips_fbsd_fpregset,
-      NULL, cb_data);
+  cb (".reg", MIPS_FBSD_NUM_GREGS * regsize, MIPS_FBSD_NUM_GREGS * regsize,
+      &mips_fbsd_gregset, NULL, cb_data);
+  cb (".reg2", MIPS_FBSD_NUM_FPREGS * regsize, MIPS_FBSD_NUM_FPREGS * regsize,
+      &mips_fbsd_fpregset, NULL, cb_data);
 }
 
 /* Signal trampoline support.  */
diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index 71183d7325..44b2b2e29b 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -537,16 +537,18 @@ mips_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   if (register_size (gdbarch, MIPS_ZERO_REGNUM) == 4)
     {
-      cb (".reg", sizeof (mips_elf_gregset_t), &mips_linux_gregset,
-	  NULL, cb_data);
-      cb (".reg2", sizeof (mips64_elf_fpregset_t), &mips64_linux_fpregset,
+      cb (".reg", sizeof (mips_elf_gregset_t), sizeof (mips_elf_gregset_t),
+	  &mips_linux_gregset, NULL, cb_data);
+      cb (".reg2", sizeof (mips64_elf_fpregset_t),
+	  sizeof (mips64_elf_fpregset_t), &mips64_linux_fpregset,
 	  NULL, cb_data);
     }
   else
     {
-      cb (".reg", sizeof (mips64_elf_gregset_t), &mips64_linux_gregset,
-	  NULL, cb_data);
-      cb (".reg2", sizeof (mips64_elf_fpregset_t), &mips64_linux_fpregset,
+      cb (".reg", sizeof (mips64_elf_gregset_t), sizeof (mips64_elf_gregset_t),
+	  &mips64_linux_gregset, NULL, cb_data);
+      cb (".reg2", sizeof (mips64_elf_fpregset_t),
+	  sizeof (mips64_elf_fpregset_t), &mips64_linux_fpregset,
 	  NULL, cb_data);
     }
 }
diff --git a/gdb/mips-nbsd-tdep.c b/gdb/mips-nbsd-tdep.c
index 5f4db87498..5005a176b5 100644
--- a/gdb/mips-nbsd-tdep.c
+++ b/gdb/mips-nbsd-tdep.c
@@ -123,10 +123,10 @@ mipsnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   size_t regsize = mips_isa_regsize (gdbarch);
 
-  cb (".reg", MIPSNBSD_NUM_GREGS * regsize, &mipsnbsd_gregset,
-      NULL, cb_data);
-  cb (".reg2", MIPSNBSD_NUM_FPREGS * regsize, &mipsnbsd_fpregset,
-      NULL, cb_data);
+  cb (".reg", MIPSNBSD_NUM_GREGS * regsize, MIPSNBSD_NUM_GREGS * regsize,
+      &mipsnbsd_gregset, NULL, cb_data);
+  cb (".reg2", MIPSNBSD_NUM_FPREGS * regsize, MIPSNBSD_NUM_FPREGS * regsize,
+      &mipsnbsd_fpregset, NULL, cb_data);
 }
 \f
 
diff --git a/gdb/mips64-obsd-tdep.c b/gdb/mips64-obsd-tdep.c
index ab910edfc4..cbebe053f5 100644
--- a/gdb/mips64-obsd-tdep.c
+++ b/gdb/mips64-obsd-tdep.c
@@ -72,7 +72,8 @@ mips64obsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					 void *cb_data,
 					 const struct regcache *regcache)
 {
-  cb (".reg", MIPS64OBSD_NUM_REGS * 8, &mips64obsd_gregset, NULL, cb_data);
+  cb (".reg", MIPS64OBSD_NUM_REGS * 8, MIPS64OBSD_NUM_REGS * 8,
+      &mips64obsd_gregset, NULL, cb_data);
 }
 \f
 
diff --git a/gdb/mn10300-linux-tdep.c b/gdb/mn10300-linux-tdep.c
index 070fb205fc..76e9c6f15f 100644
--- a/gdb/mn10300-linux-tdep.c
+++ b/gdb/mn10300-linux-tdep.c
@@ -455,10 +455,10 @@ am33_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				   void *cb_data,
 				   const struct regcache *regcache)
 {
-  cb (".reg", sizeof (mn10300_elf_gregset_t), &am33_gregset,
-      NULL, cb_data);
-  cb (".reg2", sizeof(mn10300_elf_fpregset_t), &am33_fpregset,
-      NULL, cb_data);
+  cb (".reg", sizeof (mn10300_elf_gregset_t), sizeof (mn10300_elf_gregset_t),
+      &am33_gregset, NULL, cb_data);
+  cb (".reg2", sizeof (mn10300_elf_fpregset_t), sizeof (mn10300_elf_fpregset_t),
+      &am33_fpregset, NULL, cb_data);
 }
 \f
 static void
diff --git a/gdb/nios2-linux-tdep.c b/gdb/nios2-linux-tdep.c
index e7f4ecf16e..d7e97abf09 100644
--- a/gdb/nios2-linux-tdep.c
+++ b/gdb/nios2-linux-tdep.c
@@ -106,7 +106,8 @@ nios2_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				    void *cb_data,
 				    const struct regcache *regcache)
 {
-  cb (".reg", NIOS2_GREGS_SIZE, &nios2_core_regset, NULL, cb_data);
+  cb (".reg", NIOS2_GREGS_SIZE, NIOS2_GREGS_SIZE, &nios2_core_regset, NULL,
+      cb_data);
 }
 
 /* Initialize a trad-frame cache corresponding to the tramp-frame.
diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c
index 495ccca8f1..e709c36d58 100644
--- a/gdb/ppc-fbsd-tdep.c
+++ b/gdb/ppc-fbsd-tdep.c
@@ -128,10 +128,10 @@ ppcfbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (tdep->wordsize == 4)
-    cb (".reg", 148, &ppc32_fbsd_gregset, NULL, cb_data);
+    cb (".reg", 148, 148, &ppc32_fbsd_gregset, NULL, cb_data);
   else
-    cb (".reg", 296, &ppc64_fbsd_gregset, NULL, cb_data);
-  cb (".reg2", 264, &ppc32_fbsd_fpregset, NULL, cb_data);
+    cb (".reg", 296, 296, &ppc64_fbsd_gregset, NULL, cb_data);
+  cb (".reg2", 264, 264, &ppc32_fbsd_fpregset, NULL, cb_data);
 }
 
 /* Default page size.  */
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 33a0b5a83b..1c0fb7a741 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -605,21 +605,21 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   int have_vsx = tdep->ppc_vsr0_upper_regnum != -1;
 
   if (tdep->wordsize == 4)
-    cb (".reg", 48 * 4, &ppc32_linux_gregset, NULL, cb_data);
+    cb (".reg", 48 * 4, 48 * 4, &ppc32_linux_gregset, NULL, cb_data);
   else
-    cb (".reg", 48 * 8, &ppc64_linux_gregset, NULL, cb_data);
+    cb (".reg", 48 * 8, 48 * 8, &ppc64_linux_gregset, NULL, cb_data);
 
-  cb (".reg2", 264, &ppc32_linux_fpregset, NULL, cb_data);
+  cb (".reg2", 264, 264, &ppc32_linux_fpregset, NULL, cb_data);
 
   if (have_altivec)
     {
       const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
-      cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, vrregset,
-	  "ppc Altivec", cb_data);
+      cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, PPC_LINUX_SIZEOF_VRREGSET,
+	  vrregset, "ppc Altivec", cb_data);
     }
 
   if (have_vsx)
-    cb (".reg-ppc-vsx", PPC_LINUX_SIZEOF_VSXREGSET,
+    cb (".reg-ppc-vsx", PPC_LINUX_SIZEOF_VSXREGSET, PPC_LINUX_SIZEOF_VSXREGSET,
 	&ppc32_linux_vsxregset, "POWER7 VSX", cb_data);
 }
 
diff --git a/gdb/ppc-nbsd-tdep.c b/gdb/ppc-nbsd-tdep.c
index c86aeb8a29..053ec49e6e 100644
--- a/gdb/ppc-nbsd-tdep.c
+++ b/gdb/ppc-nbsd-tdep.c
@@ -59,8 +59,8 @@ ppcnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				      void *cb_data,
 				      const struct regcache *regcache)
 {
-  cb (".reg", 148, &ppcnbsd_gregset, NULL, cb_data);
-  cb (".reg2", 264, &ppcnbsd_fpregset, NULL, cb_data);
+  cb (".reg", 148, 148, &ppcnbsd_gregset, NULL, cb_data);
+  cb (".reg2", 264, 264, &ppcnbsd_fpregset, NULL, cb_data);
 }
 \f
 
diff --git a/gdb/ppc-obsd-tdep.c b/gdb/ppc-obsd-tdep.c
index 838783111a..c478324d38 100644
--- a/gdb/ppc-obsd-tdep.c
+++ b/gdb/ppc-obsd-tdep.c
@@ -88,7 +88,7 @@ ppcobsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				      void *cb_data,
 				      const struct regcache *regcache)
 {
-  cb (".reg", 412, &ppcobsd_gregset, NULL, cb_data);
+  cb (".reg", 412, 412, &ppcobsd_gregset, NULL, cb_data);
 }
 \f
 
diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
index 8e69c465fa..50a146a4f0 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -146,9 +146,9 @@ rs6000_aix_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					 const struct regcache *regcache)
 {
   if (gdbarch_tdep (gdbarch)->wordsize == 4)
-    cb (".reg", 592, &rs6000_aix32_regset, NULL, cb_data);
+    cb (".reg", 592, 592, &rs6000_aix32_regset, NULL, cb_data);
   else
-    cb (".reg", 576, &rs6000_aix64_regset, NULL, cb_data);
+    cb (".reg", 576, 576, &rs6000_aix64_regset, NULL, cb_data);
 }
 
 
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index 4561559a85..ee8fb01109 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -273,21 +273,22 @@ s390_iterate_over_regset_sections (struct gdbarch *gdbarch,
   const int gregset_size = (tdep->abi == ABI_LINUX_S390 ?
 			    s390_sizeof_gregset : s390x_sizeof_gregset);
 
-  cb (".reg", gregset_size, &s390_gregset, NULL, cb_data);
-  cb (".reg2", s390_sizeof_fpregset, &s390_fpregset, NULL, cb_data);
+  cb (".reg", gregset_size, gregset_size, &s390_gregset, NULL, cb_data);
+  cb (".reg2", s390_sizeof_fpregset, s390_sizeof_fpregset, &s390_fpregset, NULL,
+      cb_data);
 
   if (tdep->abi == ABI_LINUX_S390 && tdep->gpr_full_regnum != -1)
-    cb (".reg-s390-high-gprs", 16 * 4, &s390_upper_regset,
+    cb (".reg-s390-high-gprs", 16 * 4, 16 * 4, &s390_upper_regset,
 	"s390 GPR upper halves", cb_data);
 
   if (tdep->have_linux_v1)
-    cb (".reg-s390-last-break", 8,
+    cb (".reg-s390-last-break", 8, 8,
 	(gdbarch_ptr_bit (gdbarch) == 32
 	 ? &s390_last_break_regset : &s390x_last_break_regset),
 	"s390 last-break address", cb_data);
 
   if (tdep->have_linux_v2)
-    cb (".reg-s390-system-call", 4, &s390_system_call_regset,
+    cb (".reg-s390-system-call", 4, 4, &s390_system_call_regset,
 	"s390 system-call", cb_data);
 
   /* If regcache is set, we are in "write" (gcore) mode.  In this
@@ -297,14 +298,14 @@ s390_iterate_over_regset_sections (struct gdbarch *gdbarch,
       && (regcache == NULL
 	  || (REG_VALID
 	      == regcache->get_register_status (S390_TDB_DWORD0_REGNUM))))
-    cb (".reg-s390-tdb", s390_sizeof_tdbregset, &s390_tdb_regset,
-	"s390 TDB", cb_data);
+    cb (".reg-s390-tdb", s390_sizeof_tdbregset, s390_sizeof_tdbregset,
+	&s390_tdb_regset, "s390 TDB", cb_data);
 
   if (tdep->v0_full_regnum != -1)
     {
-      cb (".reg-s390-vxrs-low", 16 * 8, &s390_vxrs_low_regset,
+      cb (".reg-s390-vxrs-low", 16 * 8, 16 * 8, &s390_vxrs_low_regset,
 	  "s390 vector registers 0-15 lower half", cb_data);
-      cb (".reg-s390-vxrs-high", 16 * 16, &s390_vxrs_high_regset,
+      cb (".reg-s390-vxrs-high", 16 * 16, 16 * 16, &s390_vxrs_high_regset,
 	  "s390 vector registers 16-31", cb_data);
     }
 
@@ -314,12 +315,12 @@ s390_iterate_over_regset_sections (struct gdbarch *gdbarch,
     {
       if (regcache == NULL
 	  || REG_VALID == regcache->get_register_status (S390_GSD_REGNUM))
-	cb (".reg-s390-gs-cb", 4 * 8, &s390_gs_regset,
+	cb (".reg-s390-gs-cb", 4 * 8, 4 * 8, &s390_gs_regset,
 	    "s390 guarded-storage registers", cb_data);
 
       if (regcache == NULL
 	  || REG_VALID == regcache->get_register_status (S390_BC_GSD_REGNUM))
-	cb (".reg-s390-gs-bc", 4 * 8, &s390_gsbc_regset,
+	cb (".reg-s390-gs-bc", 4 * 8, 4 * 8, &s390_gsbc_regset,
 	    "s390 guarded-storage broadcast control", cb_data);
     }
 }
diff --git a/gdb/score-tdep.c b/gdb/score-tdep.c
index 16bf00ea02..b2887c5eae 100644
--- a/gdb/score-tdep.c
+++ b/gdb/score-tdep.c
@@ -1447,8 +1447,8 @@ score7_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					   void *cb_data,
 					   const struct regcache *regcache)
 {
-  cb (".reg", SCORE7_LINUX_SIZEOF_GREGSET, &score7_linux_gregset,
-      NULL, cb_data);
+  cb (".reg", SCORE7_LINUX_SIZEOF_GREGSET, SCORE7_LINUX_SIZEOF_GREGSET,
+      &score7_linux_gregset, NULL, cb_data);
 }
 
 static struct gdbarch *
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index d1a143414d..fe64cf979a 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -2232,10 +2232,12 @@ sh_iterate_over_regset_sections (struct gdbarch *gdbarch,
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (tdep->core_gregmap != NULL)
-    cb (".reg", tdep->sizeof_gregset, &sh_corefile_gregset, NULL, cb_data);
+    cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset,
+	&sh_corefile_gregset, NULL, cb_data);
 
   if (tdep->core_fpregmap != NULL)
-    cb (".reg2", tdep->sizeof_fpregset, &sh_corefile_fpregset, NULL, cb_data);
+    cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset,
+	&sh_corefile_fpregset, NULL, cb_data);
 }
 
 /* This is the implementation of gdbarch method
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index c638a6d20c..7a50a8d4a9 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -1777,8 +1777,10 @@ sparc_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  cb (".reg", tdep->sizeof_gregset, tdep->gregset, NULL, cb_data);
-  cb (".reg2", tdep->sizeof_fpregset, tdep->fpregset, NULL, cb_data);
+  cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, tdep->gregset, NULL,
+      cb_data);
+  cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, tdep->fpregset,
+      NULL, cb_data);
 }
 \f
 
diff --git a/gdb/tilegx-linux-tdep.c b/gdb/tilegx-linux-tdep.c
index d5280f3e17..c44bbd15f3 100644
--- a/gdb/tilegx-linux-tdep.c
+++ b/gdb/tilegx-linux-tdep.c
@@ -99,8 +99,8 @@ tilegx_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				     void *cb_data,
 				     const struct regcache *regcache)
 {
-  cb (".reg", TILEGX_LINUX_SIZEOF_GREGSET, &tilegx_linux_regset,
-      NULL, cb_data);
+  cb (".reg", TILEGX_LINUX_SIZEOF_GREGSET, TILEGX_LINUX_SIZEOF_GREGSET,
+      &tilegx_linux_regset, NULL, cb_data);
 }
 
 /* OS specific initialization of gdbarch.  */
diff --git a/gdb/vax-tdep.c b/gdb/vax-tdep.c
index d07a477907..21f2066da2 100644
--- a/gdb/vax-tdep.c
+++ b/gdb/vax-tdep.c
@@ -96,7 +96,7 @@ vax_iterate_over_regset_sections (struct gdbarch *gdbarch,
 				  void *cb_data,
 				  const struct regcache *regcache)
 {
-  cb (".reg", VAX_NUM_REGS * 4, &vax_gregset, NULL, cb_data);
+  cb (".reg", VAX_NUM_REGS * 4, VAX_NUM_REGS * 4, &vax_gregset, NULL, cb_data);
 }
 \f
 /* The VAX UNIX calling convention uses R1 to pass a structure return
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index 7c0d8c15a7..49a7f023e7 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -902,8 +902,8 @@ xtensa_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   DEBUGTRACE ("xtensa_iterate_over_regset_sections\n");
 
-  cb (".reg", sizeof (xtensa_elf_gregset_t), &xtensa_gregset,
-      NULL, cb_data);
+  cb (".reg", sizeof (xtensa_elf_gregset_t), sizeof (xtensa_elf_gregset_t),
+      &xtensa_gregset, NULL, cb_data);
 }
 
 
-- 
2.15.2 (Apple Git-101.1)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 3/3] Parse SVE registers in aarch64 core file reading/writing
  2018-08-10 16:09 [PATCH v3 0/3] Detect SVE when reading aarch64 core files Alan Hayward
@ 2018-08-10 16:09 ` Alan Hayward
  2018-08-10 19:25   ` Simon Marchi
  2018-08-10 16:09 ` [PATCH v3 2/3] Detect SVE when reading aarch64 core files Alan Hayward
  2018-08-10 16:09 ` [PATCH v3 1/3] Split size in regset section iterators Alan Hayward
  2 siblings, 1 reply; 7+ messages in thread
From: Alan Hayward @ 2018-08-10 16:09 UTC (permalink / raw)
  To: gdb-patches; +Cc: nd, Alan Hayward

sve_regmap cannot be global static as the size is dependant on the current
vector length.

2018-08-10  Alan Hayward  <alan.hayward@arm.com>

	* aarch64-linux-tdep.c (aarch64_linux_supply_sve_regset): New function.
	(aarch64_linux_collect_sve_regset): Likewise.
	(aarch64_linux_iterate_over_regset_sections): Check for SVE.
	* regcache.h (regcache_map_entry_size): New function.
---
 gdb/aarch64-linux-tdep.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++-
 gdb/regcache.h           |   8 +++
 2 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 73cb9ea714..bfcee8564c 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -287,6 +287,103 @@ aarch64_linux_core_read_vq (struct gdbarch *gdbarch, bfd *abfd)
   return vq;
 }
 
+/* Supply register REGNUM from BUF to REGCACHE, using the register map
+   in REGSET.  If REGNUM is -1, do this for all registers in REGSET.
+   If BUF is NULL, set the registers to "unavailable" status.  */
+
+static void
+aarch64_linux_supply_sve_regset (const struct regset *regset,
+				 struct regcache *regcache,
+				 int regnum, const void *buf, size_t size)
+{
+  gdb_byte *header = (gdb_byte *) buf;
+  struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+  if (buf == nullptr)
+    return regcache->supply_regset (regset, regnum, nullptr, size);
+  gdb_assert (size > SVE_HEADER_SIZE);
+
+  /* BUF contains an SVE header followed by a register dump of either the
+     passed in SVE regset or a NEON fpregset.  */
+
+  /* Extract required fields from the header.  */
+  uint64_t vl = extract_unsigned_integer (header + SVE_HEADER_VL_OFFSET,
+					  SVE_HEADER_VL_LENGTH, byte_order);
+  uint16_t flags = extract_unsigned_integer (header + SVE_HEADER_FLAGS_OFFSET,
+					     SVE_HEADER_FLAGS_LENGTH,
+					     byte_order);
+
+  if (regnum == -1 || regnum == AARCH64_SVE_VG_REGNUM)
+    {
+      uint64_t vg_target;
+      store_integer ((gdb_byte *)&vg_target, sizeof (uint64_t), byte_order,
+		     sve_vg_from_vl (vl));
+      regcache->raw_supply (AARCH64_SVE_VG_REGNUM, &vg_target);
+    }
+
+  if (flags & 1)
+    {
+      /* Register dump is a SVE structure.  */
+      regcache->supply_regset (regset, regnum,
+			       (gdb_byte *) buf + SVE_HEADER_SIZE,
+			       size - SVE_HEADER_SIZE);
+    }
+  else
+    {
+      /* Register dump is a fpsimd structure.  First clear the SVE
+	 registers.  */
+      for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
+	regcache->raw_supply_zeroed (AARCH64_SVE_Z0_REGNUM + i);
+      for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
+	regcache->raw_supply_zeroed (AARCH64_SVE_P0_REGNUM + i);
+      regcache->raw_supply_zeroed (AARCH64_SVE_FFR_REGNUM);
+
+      /* Then supply the fpsimd registers.  */
+      regcache->supply_regset (&aarch64_linux_fpregset, regnum,
+			       (gdb_byte *) buf + SVE_HEADER_SIZE,
+			       size - SVE_HEADER_SIZE);
+    }
+}
+
+/* Collect register REGNUM from REGCACHE to BUF, using the register
+   map in REGSET.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+static void
+aarch64_linux_collect_sve_regset (const struct regset *regset,
+				  const struct regcache *regcache,
+				  int regnum, void *buf, size_t size)
+{
+  gdb_byte *header = (gdb_byte *) buf;
+  struct gdbarch *gdbarch = regcache->arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  uint64_t vq = gdbarch_tdep (gdbarch)->vq;
+
+  gdb_assert (buf != NULL);
+  gdb_assert (size > SVE_HEADER_SIZE);
+
+  /* BUF starts with a SVE header prior to the register dump.  */
+
+  store_unsigned_integer (header + SVE_HEADER_SIZE_OFFSET,
+			  SVE_HEADER_SIZE_LENGTH, byte_order, size);
+  store_unsigned_integer (header + SVE_HEADER_MAX_SIZE_OFFSET,
+			  SVE_HEADER_MAX_SIZE_LENGTH, byte_order, size);
+  store_unsigned_integer (header + SVE_HEADER_VL_OFFSET, SVE_HEADER_VL_LENGTH,
+			  byte_order, sve_vl_from_vq (vq));
+  store_unsigned_integer (header + SVE_HEADER_MAX_VL_OFFSET,
+			  SVE_HEADER_MAX_VL_LENGTH, byte_order,
+			  sve_vl_from_vq (vq));
+  store_unsigned_integer (header + SVE_HEADER_FLAGS_OFFSET,
+			  SVE_HEADER_FLAGS_LENGTH, byte_order, 1);
+  store_unsigned_integer (header + SVE_HEADER_RESERVED_OFFSET,
+			  SVE_HEADER_RESERVED_LENGTH, byte_order, 0);
+
+  /* The SVE register dump follows.  */
+  regcache->collect_regset (regset, regnum, (gdb_byte *) buf + SVE_HEADER_SIZE,
+			    size - SVE_HEADER_SIZE);
+}
+
 /* Implement the "regset_from_core_section" gdbarch method.  */
 
 static void
@@ -295,10 +392,39 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 					    void *cb_data,
 					    const struct regcache *regcache)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET, AARCH64_LINUX_SIZEOF_GREGSET,
       &aarch64_linux_gregset, NULL, cb_data);
-  cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, AARCH64_LINUX_SIZEOF_FPREGSET,
-      &aarch64_linux_fpregset, NULL, cb_data);
+
+  if (tdep->has_sve ())
+    {
+      /* Create this on the fly in order to handle vector register sizes.  */
+      const struct regcache_map_entry sve_regmap[] =
+	{
+	  { 32, AARCH64_SVE_Z0_REGNUM, tdep->vq * 16 },
+	  { 16, AARCH64_SVE_P0_REGNUM, tdep->vq * 16 / 8 },
+	  { 1, AARCH64_SVE_FFR_REGNUM, 4 },
+	  { 1, AARCH64_FPSR_REGNUM, 4 },
+	  { 1, AARCH64_FPCR_REGNUM, 4 },
+	  { 0 }
+	};
+
+      const struct regset aarch64_linux_sve_regset =
+	{
+	  sve_regmap,
+	  aarch64_linux_supply_sve_regset, aarch64_linux_collect_sve_regset,
+	  REGSET_VARIABLE_SIZE
+	};
+
+      cb (".reg-aarch-sve",
+	  SVE_HEADER_SIZE + regcache_map_entry_size (aarch64_linux_fpregmap),
+	  SVE_HEADER_SIZE + regcache_map_entry_size (sve_regmap),
+	  &aarch64_linux_sve_regset, "SVE registers", cb_data);
+    }
+  else
+    cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, AARCH64_LINUX_SIZEOF_FPREGSET,
+    	&aarch64_linux_fpregset, NULL, cb_data);
 }
 
 /* Implement the "core_read_description" gdbarch method.  */
diff --git a/gdb/regcache.h b/gdb/regcache.h
index ea692f38b8..ef2cc478e2 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -92,6 +92,14 @@ struct regcache_map_entry
   int size;
 };
 
+static inline int regcache_map_entry_size (const struct regcache_map_entry *map)
+{
+  int size = 0;
+  for (int i = 0; map[i].count != 0; i++)
+    size += (map[i].count * map[i].size);
+  return size;
+}
+
 /* Special value for the 'regno' field in the struct above.  */
 
 enum
-- 
2.15.2 (Apple Git-101.1)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/3] Split size in regset section iterators
  2018-08-10 16:09 ` [PATCH v3 1/3] Split size in regset section iterators Alan Hayward
@ 2018-08-10 18:57   ` Simon Marchi
  0 siblings, 0 replies; 7+ messages in thread
From: Simon Marchi @ 2018-08-10 18:57 UTC (permalink / raw)
  To: Alan Hayward, gdb-patches; +Cc: nd

Hi Alan,

Just a nit, otherwise it LGTM.

On 2018-08-10 12:08 PM, Alan Hayward wrote:
> diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
> index 447394381e..f8e03461ae 100755
> --- a/gdb/gdbarch.sh
> +++ b/gdb/gdbarch.sh
> @@ -1316,13 +1316,15 @@ typedef int (iterate_over_objfiles_in_search_order_cb_ftype)
>  
>  /* Callback type for regset section iterators.  The callback usually
>     invokes the REGSET's supply or collect method, to which it must
> -   pass a buffer with at least the given SIZE.  SECT_NAME is a BFD
> -   section name, and HUMAN_NAME is used for diagnostic messages.
> -   CB_DATA should have been passed unchanged through the iterator.  */
> +   pass a buffer - for collects this buffer will need to created using

Missing a word?

Simon

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/3] Detect SVE when reading aarch64 core files
  2018-08-10 16:09 ` [PATCH v3 2/3] Detect SVE when reading aarch64 core files Alan Hayward
@ 2018-08-10 19:08   ` Simon Marchi
  0 siblings, 0 replies; 7+ messages in thread
From: Simon Marchi @ 2018-08-10 19:08 UTC (permalink / raw)
  To: Alan Hayward, gdb-patches; +Cc: nd

Hi Alan,

LGTM with a nit/suggestion.

> +  uint64_t vl = extract_unsigned_integer (header + SVE_HEADER_VL_OFFSET,
> +					  SVE_HEADER_VL_LENGTH, byte_order);
> +  uint64_t vq = sve_vq_from_vl (vl);
> +
> +  if (vq > AARCH64_MAX_SVE_VQ || vq == 0)
> +    {
> +      warning (_("sve header invalid in "
> +		 "'.reg-aarch-sve' section in core file."));
> +      return 0;
> +    }

If higher vq/vl values are expected to be supported in the future (the definition
of AARCH64_MAX_SVE_VQ says "Increase if required"), it might be good to provide a
more specific error message in that case.  Something that says "this value of vq/vl
(32) is not supported by this GDB" (but in user-friendly).  Otherwise, a user might
think that the core file is corrupted, when actually they have an old GDB that did
not support that vector size.

It's just a suggestion, I leave that up to you.  The patch is good either way.

Simon

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 3/3] Parse SVE registers in aarch64 core file reading/writing
  2018-08-10 16:09 ` [PATCH v3 3/3] Parse SVE registers in aarch64 core file reading/writing Alan Hayward
@ 2018-08-10 19:25   ` Simon Marchi
  0 siblings, 0 replies; 7+ messages in thread
From: Simon Marchi @ 2018-08-10 19:25 UTC (permalink / raw)
  To: Alan Hayward, gdb-patches; +Cc: nd

Hi Alan,

Just a few nits for this one.  The patch is approved with these fixed.  If
you prefer to send a new version for review, note that I'll only be able to
take a look on the 20th or after (after catching up on emails and stuff).

> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index 73cb9ea714..bfcee8564c 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -287,6 +287,103 @@ aarch64_linux_core_read_vq (struct gdbarch *gdbarch, bfd *abfd)
>    return vq;
>  }
>  
> +/* Supply register REGNUM from BUF to REGCACHE, using the register map
> +   in REGSET.  If REGNUM is -1, do this for all registers in REGSET.
> +   If BUF is NULL, set the registers to "unavailable" status.  */
> +
> +static void
> +aarch64_linux_supply_sve_regset (const struct regset *regset,
> +				 struct regcache *regcache,
> +				 int regnum, const void *buf, size_t size)
> +{
> +  gdb_byte *header = (gdb_byte *) buf;
> +  struct gdbarch *gdbarch = regcache->arch ();
> +  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +
> +  if (buf == nullptr)
> +    return regcache->supply_regset (regset, regnum, nullptr, size);
> +  gdb_assert (size > SVE_HEADER_SIZE);
> +
> +  /* BUF contains an SVE header followed by a register dump of either the
> +     passed in SVE regset or a NEON fpregset.  */
> +
> +  /* Extract required fields from the header.  */
> +  uint64_t vl = extract_unsigned_integer (header + SVE_HEADER_VL_OFFSET,
> +					  SVE_HEADER_VL_LENGTH, byte_order);
> +  uint16_t flags = extract_unsigned_integer (header + SVE_HEADER_FLAGS_OFFSET,
> +					     SVE_HEADER_FLAGS_LENGTH,
> +					     byte_order);
> +
> +  if (regnum == -1 || regnum == AARCH64_SVE_VG_REGNUM)
> +    {
> +      uint64_t vg_target;
> +      store_integer ((gdb_byte *)&vg_target, sizeof (uint64_t), byte_order,

Use

  gdb_byte vg_target[8];

instead of an uint64_t.  That value doesn't belong to an host integer variable,
putting it in an uint64_t may lead people to use it in a wrong way.

> +		     sve_vg_from_vl (vl));
> +      regcache->raw_supply (AARCH64_SVE_VG_REGNUM, &vg_target);
> +    }
> +
> +  if (flags & 1)

Can you replace this magic 1 with a define?

> +    {
> +      /* Register dump is a SVE structure.  */
> +      regcache->supply_regset (regset, regnum,
> +			       (gdb_byte *) buf + SVE_HEADER_SIZE,
> +			       size - SVE_HEADER_SIZE);
> +    }
> +  else
> +    {
> +      /* Register dump is a fpsimd structure.  First clear the SVE
> +	 registers.  */
> +      for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++)
> +	regcache->raw_supply_zeroed (AARCH64_SVE_Z0_REGNUM + i);
> +      for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++)
> +	regcache->raw_supply_zeroed (AARCH64_SVE_P0_REGNUM + i);
> +      regcache->raw_supply_zeroed (AARCH64_SVE_FFR_REGNUM);
> +
> +      /* Then supply the fpsimd registers.  */
> +      regcache->supply_regset (&aarch64_linux_fpregset, regnum,
> +			       (gdb_byte *) buf + SVE_HEADER_SIZE,
> +			       size - SVE_HEADER_SIZE);
> +    }
> +}
> +
> +/* Collect register REGNUM from REGCACHE to BUF, using the register
> +   map in REGSET.  If REGNUM is -1, do this for all registers in
> +   REGSET.  */
> +
> +static void
> +aarch64_linux_collect_sve_regset (const struct regset *regset,
> +				  const struct regcache *regcache,
> +				  int regnum, void *buf, size_t size)
> +{
> +  gdb_byte *header = (gdb_byte *) buf;
> +  struct gdbarch *gdbarch = regcache->arch ();
> +  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +  uint64_t vq = gdbarch_tdep (gdbarch)->vq;
> +
> +  gdb_assert (buf != NULL);
> +  gdb_assert (size > SVE_HEADER_SIZE);
> +
> +  /* BUF starts with a SVE header prior to the register dump.  */
> +
> +  store_unsigned_integer (header + SVE_HEADER_SIZE_OFFSET,
> +			  SVE_HEADER_SIZE_LENGTH, byte_order, size);
> +  store_unsigned_integer (header + SVE_HEADER_MAX_SIZE_OFFSET,
> +			  SVE_HEADER_MAX_SIZE_LENGTH, byte_order, size);
> +  store_unsigned_integer (header + SVE_HEADER_VL_OFFSET, SVE_HEADER_VL_LENGTH,
> +			  byte_order, sve_vl_from_vq (vq));
> +  store_unsigned_integer (header + SVE_HEADER_MAX_VL_OFFSET,
> +			  SVE_HEADER_MAX_VL_LENGTH, byte_order,
> +			  sve_vl_from_vq (vq));
> +  store_unsigned_integer (header + SVE_HEADER_FLAGS_OFFSET,
> +			  SVE_HEADER_FLAGS_LENGTH, byte_order, 1);

I guess this 1 is the same flag as up there, so could use the same define?

> diff --git a/gdb/regcache.h b/gdb/regcache.h
> index ea692f38b8..ef2cc478e2 100644
> --- a/gdb/regcache.h
> +++ b/gdb/regcache.h
> @@ -92,6 +92,14 @@ struct regcache_map_entry
>    int size;
>  };
>  
> +static inline int regcache_map_entry_size (const struct regcache_map_entry *map)

Please provide a comment and add a \n before the function name.

Also, we might want to name it "regcache_map_size", since this function provides
the size of a complete regcache_map (an array of regcache_map_entry), not the size
of a single regcache_map_entry.

Simon

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-08-10 19:25 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-10 16:09 [PATCH v3 0/3] Detect SVE when reading aarch64 core files Alan Hayward
2018-08-10 16:09 ` [PATCH v3 3/3] Parse SVE registers in aarch64 core file reading/writing Alan Hayward
2018-08-10 19:25   ` Simon Marchi
2018-08-10 16:09 ` [PATCH v3 2/3] Detect SVE when reading aarch64 core files Alan Hayward
2018-08-10 19:08   ` Simon Marchi
2018-08-10 16:09 ` [PATCH v3 1/3] Split size in regset section iterators Alan Hayward
2018-08-10 18:57   ` Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).