[v3,1/3] Split size in regset section iterators

Message ID 20180810160849.68985-2-alan.hayward@arm.com
State New
Headers show
Series
  • Detect SVE when reading aarch64 core files
Related show

Commit Message

Alan Hayward Aug. 10, 2018, 4:08 p.m.
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(-)

-- 
2.15.2 (Apple Git-101.1)

Comments

Simon Marchi Aug. 10, 2018, 6:56 p.m. | #1
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

Patch

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);
 }
 
 
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);
 }
 
 
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);
 }
 
 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);
 }
 
 
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);
 }
 
 
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);
 }
 
 
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);
 }
 
 
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);
 }
 
 
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);
 }
 
 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);
 }
 
 
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);
 }
 
 
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);
 }
 
 
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);
 }
 
 /* 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);
 }