diff --git a/gdb/record-full.c b/gdb/record-full.c
index 4f73e2a5ad0d4a2407b31a1d391e813147e15798..00bbda213605110324a6529b9d4d538cd292c62f 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -167,7 +167,7 @@ struct record_full_core_buf_entry
 };

 /* Record buf with core target.  */
-static gdb_byte *record_full_core_regbuf = NULL;
+static struct regcache *record_full_core_regcache = NULL;
 static struct target_section *record_full_core_start;
 static struct target_section *record_full_core_end;
 static struct record_full_core_buf_entry *record_full_core_buf_list = NULL;
@@ -793,22 +793,17 @@ static void
 record_full_core_open_1 (const char *name, int from_tty)
 {
   struct regcache *regcache = get_current_regcache ();
-  int regnum = gdbarch_num_regs (get_regcache_arch (regcache));
-  int i;

-  /* Get record_full_core_regbuf.  */
+  /* Get record_full_core_regcache.  */
   target_fetch_registers (regcache, -1);
-  record_full_core_regbuf = (gdb_byte *) xmalloc (MAX_REGISTER_SIZE * regnum);
-  for (i = 0; i < regnum; i ++)
-    regcache_raw_collect (regcache, i,
-			  record_full_core_regbuf + MAX_REGISTER_SIZE * i);
+  record_full_core_regcache = regcache_dup (regcache);

   /* Get record_full_core_start and record_full_core_end.  */
   if (build_section_table (core_bfd, &record_full_core_start,
 			   &record_full_core_end))
     {
-      xfree (record_full_core_regbuf);
-      record_full_core_regbuf = NULL;
+      regcache_xfree (record_full_core_regcache);
+      record_full_core_regcache = NULL;
       error (_("\"%s\": Can't find sections: %s"),
 	     bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
     }
@@ -886,11 +881,11 @@ record_full_close (struct target_ops *self)

   record_full_list_release (record_full_list);

-  /* Release record_full_core_regbuf.  */
-  if (record_full_core_regbuf)
+  /* Release record_full_core_regcache.  */
+  if (record_full_core_regcache)
     {
-      xfree (record_full_core_regbuf);
-      record_full_core_regbuf = NULL;
+      regcache_xfree (record_full_core_regcache);
+      record_full_core_regcache = NULL;
     }

   /* Release record_full_core_buf_list.  */
@@ -2051,15 +2046,12 @@ record_full_core_fetch_registers (struct target_ops *ops,
   if (regno < 0)
     {
       int num = gdbarch_num_regs (get_regcache_arch (regcache));
-      int i;

-      for (i = 0; i < num; i ++)
-        regcache_raw_supply (regcache, i,
-                             record_full_core_regbuf + MAX_REGISTER_SIZE * i);
+      for (int i = 0; i < num; i ++)
+	regcache->raw_copy (i, record_full_core_regcache);
     }
   else
-    regcache_raw_supply (regcache, regno,
-                         record_full_core_regbuf + MAX_REGISTER_SIZE * regno);
+    regcache->raw_copy (regno, record_full_core_regcache);
 }

 /* "to_prepare_to_store" method for prec over corefile.  */
@@ -2078,8 +2070,7 @@ record_full_core_store_registers (struct target_ops *ops,
                              int regno)
 {
   if (record_full_gdb_operation_disable)
-    regcache_raw_collect (regcache, regno,
-                          record_full_core_regbuf + MAX_REGISTER_SIZE * regno);
+    record_full_core_regcache->raw_copy (regno, regcache);
   else
     error (_("You can't do that without a process to debug."));
 }
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 00b729d9af1b9d9823fc84fb424047c2b918ec8d..24257d8eafd4f7168b622a48ec1e646b9027153e 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -324,6 +324,8 @@ public:

   void raw_supply_zeroed (int regnum);

+  void raw_copy (int regnum, const struct regcache *src_regcache);
+
   enum register_status get_register_status (int regnum) const;

   void raw_set_cached_value (int regnum, const gdb_byte *buf);
@@ -402,8 +404,8 @@ private:
   /* Is this a read-only cache?  A read-only cache is used for saving
      the target's register state (e.g, across an inferior function
      call or just before forcing a function return).  A read-only
-     cache can only be updated via the methods regcache_dup() and
-     regcache_cpy().  The actual contents are determined by the
+     cache can only be updated via the methods regcache_dup (), regcache_cpy ()
+     and regcache::raw_copy ().  The actual contents are determined by the
      reggroup_save and reggroup_restore methods.  */
   bool m_readonly_p;
   /* If this is a read-write cache, which thread's registers is
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 4e8c1ee0e648fd17ce2a120c61ecd495ff2e2467..54454e3f039ff5d6ab436cd9e0f1da607476ce32 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -1256,6 +1256,20 @@ regcache::raw_collect (int regnum, void *buf) const
   memcpy (buf, regbuf, size);
 }

+/* Collect register REGNUM from SRC_REGCACHE and store its contents in
+   REGCACHE.  Regcaches must have matching gdbarches.  */
+
+void
+regcache::raw_copy (int regnum, const struct regcache *src_regcache)
+{
+  gdb_assert (src_regcache != NULL);
+  gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
+  gdb_assert (m_descr->gdbarch == src_regcache->m_descr->gdbarch);
+
+  src_regcache->raw_collect (regnum, register_buffer (regnum));
+  m_register_status[regnum] = src_regcache->m_register_status[regnum];
+}
+
 /* Transfer a single or all registers belonging to a certain register
    set to or from a buffer.  This is the main worker function for
    regcache_supply_regset and regcache_collect_regset.  */
