Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [unavailable regs/locals, 01/11] registers status upwards
@ 2011-02-22 13:28 Pedro Alves
  2011-02-28 15:53 ` Jan Kratochvil
  0 siblings, 1 reply; 8+ messages in thread
From: Pedro Alves @ 2011-02-22 13:28 UTC (permalink / raw)
  To: gdb-patches

This is a step in the direction of glueing unavailable registers
to unavailable values.

Make the regcache_XXX_read_XXX functions return an indication
of whether the register's value is valid, so that the
frame module can mark frame registers as unavailable.

That's straight forward for raw registers.  For pseudo-registers,
which are built from raw registers (or something else),
only each target backend knows what from and how is a given pseudo-register
contructable.  So, change gdbarch_pseudo_register_read to
return a register status, indicating when a pseudo
register was being build from non valid raw registers
(or something else).  This then requires updating all
gdbarch target backends.  Most needed boring mechanical
changes, and couple required a bit more, but nothing fancy.

-- 
Pedro Alves

2011-02-22  Pedro Alves  <pedro@codesourcery.com>

	gdb/
	* regcache.h (regcache_raw_read, regcache_raw_read_signed)
	(regcache_raw_read_unsigned, regcache_raw_read_signed)
	(regcache_raw_read_unsigned, regcache_raw_read_part)
	(regcache_cooked_read, regcache_cooked_read_signed)
	(regcache_cooked_read_unsigned, regcache_cooked_read_part)
	(regcache_cooked_read_ftype): Change return to enum
	register_status.
	* regcache.c (regcache_save): Adjust to handle REG_UNAVAILABLE
	registers.
	(do_cooked_read): Change return to enum register_status.  Always
	forward to regcache_cooked_read.
	(regcache_raw_read): Change return to enum register_status.  If
	the register is not REG_VALID, memset the buffer.  Return the
	register's status.
	(regcache_raw_read_signed): Handle non-REG_VALID registers and
	return the register's status.
	(regcache_raw_read_unsigned): Ditto.
	(regcache_cooked_read): Change return to enum register_status.
	Assert that with read-only regcaches, the register's status must
	be known.  If the regcache is read-only, and the register is not
	REG_VALID, memset the buffer.  Return the register's status.
	(regcache_cooked_read_signed): Change return to enum
	register_status.  Handle non-REG_VALID registers and return the
	register's status.
	(regcache_cooked_read_unsigned): Change return to enum
	register_status.  Handle non-REG_VALID registers and return the
	register's status.
	(regcache_xfer_part, regcache_raw_read_part)
	(regcache_cooked_read_part): Change return to enum
	register_status.  Return the register's status.
	* frame.c (do_frame_register_read): Adjust interface to match
	regcache_cooked_read_ftype.
	* gdbarch.sh (pseudo_register_read): Change return to enum
	register_status.
	* gdbarch.h, gdbarch.c: Regenerate.

	* i386-tdep.h (i386_pseudo_register_read): Change return to enum
	register_status.
	* i386-tdep.c (i386_pseudo_register_read): Change return to enum
	register_status.  If reading a raw register indicates the raw
	register is not valid, return the raw register's status,
	otherwise, return REG_VALID.
	* amd64-tdep.c (amd64_pseudo_register_read): Change return to enum
	register_status.  Handle non-REG_VALID raw registers and return
	the register's status.
	* arm-tdep.c (arm_neon_quad_read)
	(arm_pseudo_read): Change return to enum register_status.  Handle
	non-REG_VALID raw registers and return the register's status.
	* avr-tdep.c (avr_pseudo_register_read): Ditto.
	* frv-tdep.c (frv_pseudo_register_read): Ditto.
	* h8300-tdep.c (h8300_pseudo_register_read): Ditto.
	* hppa-tdep.c (hppa_pseudo_register_read): Ditto.
	* m32c-tdep.c (m32c_move_reg_t): Change return to enum
	register_status.
	(m32c_raw_read, m32c_raw_write, m32c_banked_read)
	(m32c_banked_write, m32c_sb_read, m32c_sb_write, m32c_part_read)
	(m32c_part_write, m32c_cat_read, m32c_cat_write)
	(m32c_r3r2r1r0_read, m32c_r3r2r1r0_write)
	(m32c_pseudo_register_read): Change return to enum
	register_status.  Adjust.
	* m68hc11-tdep.c (m68hc11_pseudo_register_read): Change return to
	enum register_status.  Return the register's status.
	* mep-tdep.c (mep_pseudo_cr32_read): Change return to enum
	register_status.  Return the register's status.
	(mep_pseudo_cr64_read, mep_pseudo_register_read): Ditto.
	* mips-tdep.c (mips_pseudo_register_read): Ditto.
	* mt-tdep.c (mt_pseudo_register_read): Ditto.
	* rs6000-tdep.c (move_ev_register_func): New typedef.
	(e500_move_ev_register): Use it.  Change return to enum
	register_status.  Return the register's status.
	(do_regcache_raw_read): New function.
	(do_regcache_raw_write): New function.
	(e500_pseudo_register_read): Change return to enum
	register_status.  Return the register's status.  Use
	do_regcache_raw_read.
	(e500_pseudo_register_write): Adjust.  Use do_regcache_raw_write.
	(dfp_pseudo_register_read): Change return to enum register_status.
	Return the register's status.
	(vsx_pseudo_register_read): Ditto.
	(efpr_pseudo_register_read): Ditto.
	(rs6000_pseudo_register_read): Ditto.
	* s390-tdep.c (s390_pseudo_register_read): Change return to enum
	register_status.  Return the register's status.
	* sh64-tdep.c (pseudo_register_read_portions): New function.
	(sh64_pseudo_register_read): Change return to enum
	register_status.  Use pseudo_register_read_portions.  Return the
	register's status.
	* ia64-tdep.c (ia64_pseudo_register_read): Change return to enum
	register_status.  Return the register's status.
	* sh-tdep.c (pseudo_register_read_portions): New function.
	(sh_pseudo_register_read): Change return to enum register_status.
	Use pseudo_register_read_portions.  Return the register's status.
	* sparc-tdep.c (sparc32_pseudo_register_read): Change return to
	enum register_status.  Return the register's status.
	* sparc64-tdep.c (sparc64_pseudo_register_read): Ditto.
	* spu-tdep.c (spu_pseudo_register_read_spu)
	(spu_pseudo_register_read): Ditto.
	* xtensa-tdep.c (xtensa_register_read_masked)
	(xtensa_pseudo_register_read): Ditto.
	* bfin-tdep.c (bfin_pseudo_register_read): Ditto.
	(bfin_pseudo_register_write): Adjust.

---
 gdb/amd64-tdep.c   |   27 ++++++---
 gdb/arm-tdep.c     |   31 +++++++---
 gdb/avr-tdep.c     |    9 ++-
 gdb/bfin-tdep.c    |   23 +++++--
 gdb/frame.c        |    7 +-
 gdb/frv-tdep.c     |   29 ++++++----
 gdb/gdbarch.c      |    4 -
 gdb/gdbarch.h      |    4 -
 gdb/gdbarch.sh     |    2 
 gdb/h8300-tdep.c   |    8 +-
 gdb/hppa-tdep.c    |   19 ++++--
 gdb/i386-tdep.c    |   33 +++++++----
 gdb/i386-tdep.h    |    7 +-
 gdb/ia64-tdep.c    |   51 +++++++++++++----
 gdb/m32c-tdep.c    |   96 +++++++++++++++++++++------------
 gdb/m68hc11-tdep.c |   11 ++-
 gdb/mep-tdep.c     |   27 +++++----
 gdb/mips-tdep.c    |   14 +++-
 gdb/mt-tdep.c      |   29 ++++++----
 gdb/regcache.c     |  153 +++++++++++++++++++++++++++++++++--------------------
 gdb/regcache.h     |   66 ++++++++++++----------
 gdb/rs6000-tdep.c  |  119 ++++++++++++++++++++++++++---------------
 gdb/s390-tdep.c    |   54 ++++++++++++------
 gdb/sh-tdep.c      |   63 +++++++++++++++------
 gdb/sh64-tdep.c    |  108 ++++++++++++++++++++++++-------------
 gdb/sparc-tdep.c   |   10 ++-
 gdb/sparc64-tdep.c |   41 ++++++++++----
 gdb/spu-tdep.c     |   35 ++++++------
 gdb/xtensa-tdep.c  |   36 +++++++-----
 29 files changed, 725 insertions(+), 391 deletions(-)

Index: src/gdb/regcache.h
===================================================================
--- src.orig/gdb/regcache.h	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/regcache.h	2011-02-22 11:38:56.344708016 +0000
@@ -64,49 +64,53 @@ enum register_status regcache_register_s
 					       int regnum);
 
 /* Transfer a raw register [0..NUM_REGS) between core-gdb and the
-   regcache.  */
+   regcache.  The read variants return the status of the register.  */
 
-void regcache_raw_read (struct regcache *regcache, int rawnum, gdb_byte *buf);
+enum register_status regcache_raw_read (struct regcache *regcache,
+					int rawnum, gdb_byte *buf);
 void regcache_raw_write (struct regcache *regcache, int rawnum,
 			 const gdb_byte *buf);
-extern void regcache_raw_read_signed (struct regcache *regcache,
-				      int regnum, LONGEST *val);
-extern void regcache_raw_read_unsigned (struct regcache *regcache,
-					int regnum, ULONGEST *val);
+extern enum register_status
+  regcache_raw_read_signed (struct regcache *regcache,
+			    int regnum, LONGEST *val);
+extern enum register_status
+  regcache_raw_read_unsigned (struct regcache *regcache,
+			      int regnum, ULONGEST *val);
 extern void regcache_raw_write_signed (struct regcache *regcache,
 				       int regnum, LONGEST val);
 extern void regcache_raw_write_unsigned (struct regcache *regcache,
 					 int regnum, ULONGEST val);
 
-/* Partial transfer of a raw registers.  These perform read, modify,
-   write style operations.  */
-
-void regcache_raw_read_part (struct regcache *regcache, int regnum,
-			     int offset, int len, gdb_byte *buf);
+/* Partial transfer of raw registers.  These perform read, modify,
+   write style operations.  The read variant returns the status of the
+   register.  */
+
+extern enum register_status
+  regcache_raw_read_part (struct regcache *regcache, int regnum,
+			  int offset, int len, gdb_byte *buf);
 void regcache_raw_write_part (struct regcache *regcache, int regnum,
 			      int offset, int len, const gdb_byte *buf);
 
 void regcache_invalidate (struct regcache *regcache, int regnum);
 
+/* Transfer of pseudo-registers.  The read variants return a register
+   status, as an indication of when a ``cooked'' register was
+   constructed from valid, invalid or unavailable ``raw''
+   registers.  */
+
 /* Transfer a cooked register [0..NUM_REGS+NUM_PSEUDO_REGS).  */
-void regcache_cooked_read (struct regcache *regcache, int rawnum,
-			   gdb_byte *buf);
+enum register_status regcache_cooked_read (struct regcache *regcache,
+					   int rawnum, gdb_byte *buf);
 void regcache_cooked_write (struct regcache *regcache, int rawnum,
 			    const gdb_byte *buf);
-
-/* NOTE: cagney/2002-08-13: At present GDB has no reliable mechanism
-   for indicating when a ``cooked'' register was constructed from
-   invalid or unavailable ``raw'' registers.  One fairly easy way of
-   adding such a mechanism would be for the cooked functions to return
-   a register valid indication.  Given the possibility of such a
-   change, the extract functions below use a reference parameter,
-   rather than a function result.  */
-
+
 /* Read a register as a signed/unsigned quantity.  */
-extern void regcache_cooked_read_signed (struct regcache *regcache,
-					 int regnum, LONGEST *val);
-extern void regcache_cooked_read_unsigned (struct regcache *regcache,
-					   int regnum, ULONGEST *val);
+extern enum register_status
+  regcache_cooked_read_signed (struct regcache *regcache,
+			       int regnum, LONGEST *val);
+extern enum register_status
+  regcache_cooked_read_unsigned (struct regcache *regcache,
+				 int regnum, ULONGEST *val);
 extern void regcache_cooked_write_signed (struct regcache *regcache,
 					  int regnum, LONGEST val);
 extern void regcache_cooked_write_unsigned (struct regcache *regcache,
@@ -115,8 +119,9 @@ extern void regcache_cooked_write_unsign
 /* Partial transfer of a cooked register.  These perform read, modify,
    write style operations.  */
 
-void regcache_cooked_read_part (struct regcache *regcache, int regnum,
-				int offset, int len, gdb_byte *buf);
+enum register_status regcache_cooked_read_part (struct regcache *regcache,
+						int regnum, int offset,
+						int len, gdb_byte *buf);
 void regcache_cooked_write_part (struct regcache *regcache, int regnum,
 				 int offset, int len, const gdb_byte *buf);
 
@@ -153,8 +158,9 @@ extern int register_size (struct gdbarch
    restore_reggroup respectively.  COOKED_READ returns zero iff the
    register's value can't be returned.  */
 
-typedef int (regcache_cooked_read_ftype) (void *src, int regnum,
-					  gdb_byte *buf);
+typedef enum register_status (regcache_cooked_read_ftype) (void *src,
+							   int regnum,
+							   gdb_byte *buf);
 
 extern void regcache_save (struct regcache *dst,
 			   regcache_cooked_read_ftype *cooked_read,
Index: src/gdb/regcache.c
===================================================================
--- src.orig/gdb/regcache.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/regcache.c	2011-02-21 21:09:45.449344005 +0000
@@ -312,14 +312,19 @@ regcache_save (struct regcache *dst, reg
     {
       if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup))
 	{
-	  int valid = cooked_read (src, regnum, buf);
+	  enum register_status status = cooked_read (src, regnum, buf);
 
-	  if (valid)
+	  if (status == REG_VALID)
+	    memcpy (register_buffer (dst, regnum), buf,
+		    register_size (gdbarch, regnum));
+	  else
 	    {
-	      memcpy (register_buffer (dst, regnum), buf,
+	      gdb_assert (status != REG_UNKNOWN);
+
+	      memset (register_buffer (dst, regnum), 0,
 		      register_size (gdbarch, regnum));
-	      dst->register_status[regnum] = REG_VALID;
 	    }
+	  dst->register_status[regnum] = status;
 	}
     }
 }
@@ -352,21 +357,14 @@ regcache_restore (struct regcache *dst,
     }
 }
 
-static int
+static enum register_status
 do_cooked_read (void *src, int regnum, gdb_byte *buf)
 {
   struct regcache *regcache = src;
 
-  if (regcache->register_status[regnum] == REG_UNKNOWN && regcache->readonly_p)
-    /* Don't even think about fetching a register from a read-only
-       cache when the register isn't yet valid.  There isn't a target
-       from which the register value can be fetched.  */
-    return 0;
-  regcache_cooked_read (regcache, regnum, buf);
-  return 1;
+  return regcache_cooked_read (regcache, regnum, buf);
 }
 
-
 void
 regcache_cpy (struct regcache *dst, struct regcache *src)
 {
@@ -578,7 +576,7 @@ registers_changed (void)
   alloca (0);
 }
 
-void
+enum register_status
 regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 {
   gdb_assert (regcache != NULL && buf != NULL);
@@ -607,38 +605,53 @@ regcache_raw_read (struct regcache *regc
       gdb_assert (regcache_register_status (regcache, regnum) == REG_VALID);
 #endif
     }
-  /* Copy the value directly into the register cache.  */
-  memcpy (buf, register_buffer (regcache, regnum),
-	  regcache->descr->sizeof_register[regnum]);
+
+  if (regcache->register_status[regnum] != REG_VALID)
+    memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+  else
+    memcpy (buf, register_buffer (regcache, regnum),
+	    regcache->descr->sizeof_register[regnum]);
+
+  return regcache->register_status[regnum];
 }
 
-void
+enum register_status
 regcache_raw_read_signed (struct regcache *regcache, int regnum, LONGEST *val)
 {
   gdb_byte *buf;
+  enum register_status status;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
   buf = alloca (regcache->descr->sizeof_register[regnum]);
-  regcache_raw_read (regcache, regnum, buf);
-  (*val) = extract_signed_integer
-	     (buf, regcache->descr->sizeof_register[regnum],
-	      gdbarch_byte_order (regcache->descr->gdbarch));
+  status = regcache_raw_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    *val = extract_signed_integer
+      (buf, regcache->descr->sizeof_register[regnum],
+       gdbarch_byte_order (regcache->descr->gdbarch));
+  else
+    *val = 0;
+  return status;
 }
 
-void
+enum register_status
 regcache_raw_read_unsigned (struct regcache *regcache, int regnum,
 			    ULONGEST *val)
 {
   gdb_byte *buf;
+  enum register_status status;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
   buf = alloca (regcache->descr->sizeof_register[regnum]);
-  regcache_raw_read (regcache, regnum, buf);
-  (*val) = extract_unsigned_integer
-	     (buf, regcache->descr->sizeof_register[regnum],
-	      gdbarch_byte_order (regcache->descr->gdbarch));
+  status = regcache_raw_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    *val = extract_unsigned_integer
+      (buf, regcache->descr->sizeof_register[regnum],
+       gdbarch_byte_order (regcache->descr->gdbarch));
+  else
+    *val = 0;
+  return status;
 }
 
 void
@@ -668,52 +681,71 @@ regcache_raw_write_unsigned (struct regc
   regcache_raw_write (regcache, regnum, buf);
 }
 
-void
+enum register_status
 regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 {
   gdb_assert (regnum >= 0);
   gdb_assert (regnum < regcache->descr->nr_cooked_registers);
   if (regnum < regcache->descr->nr_raw_registers)
-    regcache_raw_read (regcache, regnum, buf);
+    return regcache_raw_read (regcache, regnum, buf);
   else if (regcache->readonly_p
-	   && regnum < regcache->descr->nr_cooked_registers
-	   && regcache->register_status[regnum] == REG_VALID)
-    /* Read-only register cache, and the cooked value was cached.  */
-    memcpy (buf, register_buffer (regcache, regnum),
-	    regcache->descr->sizeof_register[regnum]);
+	   && regcache->register_status[regnum] != REG_UNKNOWN)
+    {
+      /* Read-only register cache, perhaps the cooked value was
+	 cached?  */
+      struct gdbarch *gdbarch = regcache->descr->gdbarch;
+
+      if (regcache->register_status[regnum] == REG_VALID)
+	memcpy (buf, register_buffer (regcache, regnum),
+		regcache->descr->sizeof_register[regnum]);
+      else
+	memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+
+      return regcache->register_status[regnum];
+    }
   else
-    gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
-				  regnum, buf);
+    return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
+					 regnum, buf);
 }
 
-void
+enum register_status
 regcache_cooked_read_signed (struct regcache *regcache, int regnum,
 			     LONGEST *val)
 {
+  enum register_status status;
   gdb_byte *buf;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_cooked_registers);
   buf = alloca (regcache->descr->sizeof_register[regnum]);
-  regcache_cooked_read (regcache, regnum, buf);
-  (*val) = extract_signed_integer
-	     (buf, regcache->descr->sizeof_register[regnum],
-	      gdbarch_byte_order (regcache->descr->gdbarch));
+  status = regcache_cooked_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    *val = extract_signed_integer
+      (buf, regcache->descr->sizeof_register[regnum],
+       gdbarch_byte_order (regcache->descr->gdbarch));
+  else
+    *val = 0;
+  return status;
 }
 
-void
+enum register_status
 regcache_cooked_read_unsigned (struct regcache *regcache, int regnum,
 			       ULONGEST *val)
 {
+  enum register_status status;
   gdb_byte *buf;
 
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_cooked_registers);
   buf = alloca (regcache->descr->sizeof_register[regnum]);
-  regcache_cooked_read (regcache, regnum, buf);
-  (*val) = extract_unsigned_integer
-	     (buf, regcache->descr->sizeof_register[regnum],
-	      gdbarch_byte_order (regcache->descr->gdbarch));
+  status = regcache_cooked_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    *val = extract_unsigned_integer
+      (buf, regcache->descr->sizeof_register[regnum],
+       gdbarch_byte_order (regcache->descr->gdbarch));
+  else
+    *val = 0;
+  return status;
 }
 
 void
@@ -799,11 +831,12 @@ typedef void (regcache_read_ftype) (stru
 typedef void (regcache_write_ftype) (struct regcache *regcache, int regnum,
 				     const void *buf);
 
-static void
+static enum register_status
 regcache_xfer_part (struct regcache *regcache, int regnum,
 		    int offset, int len, void *in, const void *out,
-		    void (*read) (struct regcache *regcache, int regnum,
-				  gdb_byte *buf),
+		    enum register_status (*read) (struct regcache *regcache,
+						  int regnum,
+						  gdb_byte *buf),
 		    void (*write) (struct regcache *regcache, int regnum,
 				   const gdb_byte *buf))
 {
@@ -814,14 +847,18 @@ regcache_xfer_part (struct regcache *reg
   gdb_assert (len >= 0 && offset + len <= descr->sizeof_register[regnum]);
   /* Something to do?  */
   if (offset + len == 0)
-    return;
+    return REG_VALID;
   /* Read (when needed) ...  */
   if (in != NULL
       || offset > 0
       || offset + len < descr->sizeof_register[regnum])
     {
+      enum register_status status;
+
       gdb_assert (read != NULL);
-      read (regcache, regnum, reg);
+      status = read (regcache, regnum, reg);
+      if (status != REG_VALID)
+	return status;
     }
   /* ... modify ...  */
   if (in != NULL)
@@ -834,17 +871,19 @@ regcache_xfer_part (struct regcache *reg
       gdb_assert (write != NULL);
       write (regcache, regnum, reg);
     }
+
+  return REG_VALID;
 }
 
-void
+enum register_status
 regcache_raw_read_part (struct regcache *regcache, int regnum,
 			int offset, int len, gdb_byte *buf)
 {
   struct regcache_descr *descr = regcache->descr;
 
   gdb_assert (regnum >= 0 && regnum < descr->nr_raw_registers);
-  regcache_xfer_part (regcache, regnum, offset, len, buf, NULL,
-		      regcache_raw_read, regcache_raw_write);
+  return regcache_xfer_part (regcache, regnum, offset, len, buf, NULL,
+			     regcache_raw_read, regcache_raw_write);
 }
 
 void
@@ -858,15 +897,15 @@ regcache_raw_write_part (struct regcache
 		      regcache_raw_read, regcache_raw_write);
 }
 
-void
+enum register_status
 regcache_cooked_read_part (struct regcache *regcache, int regnum,
 			   int offset, int len, gdb_byte *buf)
 {
   struct regcache_descr *descr = regcache->descr;
 
   gdb_assert (regnum >= 0 && regnum < descr->nr_cooked_registers);
-  regcache_xfer_part (regcache, regnum, offset, len, buf, NULL,
-		      regcache_cooked_read, regcache_cooked_write);
+  return regcache_xfer_part (regcache, regnum, offset, len, buf, NULL,
+			     regcache_cooked_read, regcache_cooked_write);
 }
 
 void
Index: src/gdb/frame.c
===================================================================
--- src.orig/gdb/frame.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/frame.c	2011-02-21 21:09:45.449344005 +0000
@@ -687,10 +687,13 @@ get_frame_func (struct frame_info *this_
   return next_frame->prev_func.addr;
 }
 
-static int
+static enum register_status
 do_frame_register_read (void *src, int regnum, gdb_byte *buf)
 {
-  return frame_register_read (src, regnum, buf);
+  if (!frame_register_read (src, regnum, buf))
+    return REG_UNAVAILABLE;
+  else
+    return REG_VALID;
 }
 
 struct regcache *
Index: src/gdb/gdbarch.sh
===================================================================
--- src.orig/gdb/gdbarch.sh	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/gdbarch.sh	2011-02-21 21:09:45.449344005 +0000
@@ -417,7 +417,7 @@ F:void:write_pc:struct regcache *regcach
 # serious shakedown.
 m:void:virtual_frame_pointer:CORE_ADDR pc, int *frame_regnum, LONGEST *frame_offset:pc, frame_regnum, frame_offset:0:legacy_virtual_frame_pointer::0
 #
-M:void:pseudo_register_read:struct regcache *regcache, int cookednum, gdb_byte *buf:regcache, cookednum, buf
+M:enum register_status:pseudo_register_read:struct regcache *regcache, int cookednum, gdb_byte *buf:regcache, cookednum, buf
 M:void:pseudo_register_write:struct regcache *regcache, int cookednum, const gdb_byte *buf:regcache, cookednum, buf
 #
 v:int:num_regs:::0:-1
Index: src/gdb/gdbarch.h
===================================================================
--- src.orig/gdb/gdbarch.h	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/gdbarch.h	2011-02-21 21:09:45.449344005 +0000
@@ -212,8 +212,8 @@ extern void set_gdbarch_virtual_frame_po
 
 extern int gdbarch_pseudo_register_read_p (struct gdbarch *gdbarch);
 
-typedef void (gdbarch_pseudo_register_read_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
-extern void gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
+typedef enum register_status (gdbarch_pseudo_register_read_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
+extern enum register_status gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf);
 extern void set_gdbarch_pseudo_register_read (struct gdbarch *gdbarch, gdbarch_pseudo_register_read_ftype *pseudo_register_read);
 
 extern int gdbarch_pseudo_register_write_p (struct gdbarch *gdbarch);
Index: src/gdb/gdbarch.c
===================================================================
--- src.orig/gdb/gdbarch.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/gdbarch.c	2011-02-21 21:09:45.459344006 +0000
@@ -1682,14 +1682,14 @@ gdbarch_pseudo_register_read_p (struct g
   return gdbarch->pseudo_register_read != NULL;
 }
 
-void
+enum register_status
 gdbarch_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int cookednum, gdb_byte *buf)
 {
   gdb_assert (gdbarch != NULL);
   gdb_assert (gdbarch->pseudo_register_read != NULL);
   if (gdbarch_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "gdbarch_pseudo_register_read called\n");
-  gdbarch->pseudo_register_read (gdbarch, regcache, cookednum, buf);
+  return gdbarch->pseudo_register_read (gdbarch, regcache, cookednum, buf);
 }
 
 void
Index: src/gdb/i386-tdep.h
===================================================================
--- src.orig/gdb/i386-tdep.h	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/i386-tdep.h	2011-02-21 21:09:45.459344006 +0000
@@ -311,9 +311,10 @@ extern int i386_ymm_regnum_p (struct gdb
 extern const char *i386_pseudo_register_name (struct gdbarch *gdbarch,
 					      int regnum);
 
-extern void i386_pseudo_register_read (struct gdbarch *gdbarch,
-				       struct regcache *regcache,
-				       int regnum, gdb_byte *buf);
+extern enum register_status i386_pseudo_register_read (struct gdbarch *gdbarch,
+						       struct regcache *regcache,
+						       int regnum,
+						       gdb_byte *buf);
 extern void i386_pseudo_register_write (struct gdbarch *gdbarch,
 					struct regcache *regcache,
 					int regnum, const gdb_byte *buf);
Index: src/gdb/i386-tdep.c
===================================================================
--- src.orig/gdb/i386-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/i386-tdep.c	2011-02-21 21:09:45.459344006 +0000
@@ -2510,18 +2510,21 @@ i386_mmx_regnum_to_fp_regnum (struct reg
   return (I387_ST0_REGNUM (tdep) + fpreg);
 }
 
-void
+enum register_status
 i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int regnum, gdb_byte *buf)
 {
   gdb_byte raw_buf[MAX_REGISTER_SIZE];
+  enum register_status status;
 
   if (i386_mmx_regnum_p (gdbarch, regnum))
     {
       int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
 
       /* Extract (always little endian).  */
-      regcache_raw_read (regcache, fpnum, raw_buf);
+      status = regcache_raw_read (regcache, fpnum, raw_buf);
+      if (status != REG_VALID)
+	return status;
       memcpy (buf, raw_buf, register_size (gdbarch, regnum));
     }
   else
@@ -2533,14 +2536,18 @@ i386_pseudo_register_read (struct gdbarc
 	  regnum -= tdep->ymm0_regnum;
 
 	  /* Extract (always little endian).  Read lower 128bits.  */
-	  regcache_raw_read (regcache,
-			     I387_XMM0_REGNUM (tdep) + regnum,
-			     raw_buf);
+	  status = regcache_raw_read (regcache,
+				      I387_XMM0_REGNUM (tdep) + regnum,
+				      raw_buf);
+	  if (status != REG_VALID)
+	    return status;
 	  memcpy (buf, raw_buf, 16);
 	  /* Read upper 128bits.  */
-	  regcache_raw_read (regcache,
-			     tdep->ymm0h_regnum + regnum,
-			     raw_buf);
+	  status = regcache_raw_read (regcache,
+				      tdep->ymm0h_regnum + regnum,
+				      raw_buf);
+	  if (status != REG_VALID)
+	    return status;
 	  memcpy (buf + 16, raw_buf, 16);
 	}
       else if (i386_word_regnum_p (gdbarch, regnum))
@@ -2548,7 +2555,9 @@ i386_pseudo_register_read (struct gdbarc
 	  int gpnum = regnum - tdep->ax_regnum;
 
 	  /* Extract (always little endian).  */
-	  regcache_raw_read (regcache, gpnum, raw_buf);
+	  status = regcache_raw_read (regcache, gpnum, raw_buf);
+	  if (status != REG_VALID)
+	    return status;
 	  memcpy (buf, raw_buf, 2);
 	}
       else if (i386_byte_regnum_p (gdbarch, regnum))
@@ -2560,7 +2569,9 @@ i386_pseudo_register_read (struct gdbarc
 
 	  /* Extract (always little endian).  We read both lower and
 	     upper registers.  */
-	  regcache_raw_read (regcache, gpnum % 4, raw_buf);
+	  status = regcache_raw_read (regcache, gpnum % 4, raw_buf);
+	  if (status != REG_VALID)
+	    return status;
 	  if (gpnum >= 4)
 	    memcpy (buf, raw_buf + 1, 1);
 	  else
@@ -2569,6 +2580,8 @@ i386_pseudo_register_read (struct gdbarc
       else
 	internal_error (__FILE__, __LINE__, _("invalid regnum"));
     }
+
+  return REG_VALID;
 }
 
 void
Index: src/gdb/amd64-tdep.c
===================================================================
--- src.orig/gdb/amd64-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/amd64-tdep.c	2011-02-21 21:09:45.459344006 +0000
@@ -275,13 +275,14 @@ amd64_pseudo_register_name (struct gdbar
     return i386_pseudo_register_name (gdbarch, regnum);
 }
 
-static void
+static enum register_status
 amd64_pseudo_register_read (struct gdbarch *gdbarch,
 			    struct regcache *regcache,
 			    int regnum, gdb_byte *buf)
 {
   gdb_byte raw_buf[MAX_REGISTER_SIZE];
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum register_status status;
 
   if (i386_byte_regnum_p (gdbarch, regnum))
     {
@@ -291,25 +292,33 @@ amd64_pseudo_register_read (struct gdbar
       if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS)
 	{
 	  /* Special handling for AH, BH, CH, DH.  */
-	  regcache_raw_read (regcache,
-			     gpnum - AMD64_NUM_LOWER_BYTE_REGS, raw_buf);
-	  memcpy (buf, raw_buf + 1, 1);
+	  status = regcache_raw_read (regcache,
+				      gpnum - AMD64_NUM_LOWER_BYTE_REGS,
+				      raw_buf);
+	  if (status == REG_VALID)
+	    memcpy (buf, raw_buf + 1, 1);
 	}
       else
 	{
-	  regcache_raw_read (regcache, gpnum, raw_buf);
-	  memcpy (buf, raw_buf, 1);
+	  status = regcache_raw_read (regcache, gpnum, raw_buf);
+	  if (status == REG_VALID)
+	    memcpy (buf, raw_buf, 1);
 	}
+
+      return status;
     }
   else if (i386_dword_regnum_p (gdbarch, regnum))
     {
       int gpnum = regnum - tdep->eax_regnum;
       /* Extract (always little endian).  */
-      regcache_raw_read (regcache, gpnum, raw_buf);
-      memcpy (buf, raw_buf, 4);
+      status = regcache_raw_read (regcache, gpnum, raw_buf);
+      if (status == REG_VALID)
+	memcpy (buf, raw_buf, 4);
+
+      return status;
     }
   else
-    i386_pseudo_register_read (gdbarch, regcache, regnum, buf);
+    return i386_pseudo_register_read (gdbarch, regcache, regnum, buf);
 }
 
 static void
Index: src/gdb/arm-tdep.c
===================================================================
--- src.orig/gdb/arm-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/arm-tdep.c	2011-02-21 21:09:45.469344007 +0000
@@ -213,9 +213,9 @@ static void convert_from_extended (const
 static void convert_to_extended (const struct floatformat *, void *,
 				 const void *, int);
 
-static void arm_neon_quad_read (struct gdbarch *gdbarch,
-				struct regcache *regcache,
-				int regnum, gdb_byte *buf);
+static enum register_status arm_neon_quad_read (struct gdbarch *gdbarch,
+						struct regcache *regcache,
+						int regnum, gdb_byte *buf);
 static void arm_neon_quad_write (struct gdbarch *gdbarch,
 				 struct regcache *regcache,
 				 int regnum, const gdb_byte *buf);
@@ -7862,13 +7862,14 @@ arm_write_pc (struct regcache *regcache,
    ABI, even if a NEON unit is not present.  REGNUM is the index of
    the quad register, in [0, 15].  */
 
-static void
+static enum register_status
 arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
 		    int regnum, gdb_byte *buf)
 {
   char name_buf[4];
   gdb_byte reg_buf[8];
   int offset, double_regnum;
+  enum register_status status;
 
   sprintf (name_buf, "d%d", regnum << 1);
   double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
@@ -7880,15 +7881,21 @@ arm_neon_quad_read (struct gdbarch *gdba
   else
     offset = 0;
 
-  regcache_raw_read (regcache, double_regnum, reg_buf);
+  status = regcache_raw_read (regcache, double_regnum, reg_buf);
+  if (status != REG_VALID)
+    return status;
   memcpy (buf + offset, reg_buf, 8);
 
   offset = 8 - offset;
-  regcache_raw_read (regcache, double_regnum + 1, reg_buf);
+  status = regcache_raw_read (regcache, double_regnum + 1, reg_buf);
+  if (status != REG_VALID)
+    return status;
   memcpy (buf + offset, reg_buf, 8);
+
+  return REG_VALID;
 }
 
-static void
+static enum register_status
 arm_pseudo_read (struct gdbarch *gdbarch, struct regcache *regcache,
 		 int regnum, gdb_byte *buf)
 {
@@ -7902,9 +7909,11 @@ arm_pseudo_read (struct gdbarch *gdbarch
 
   if (gdbarch_tdep (gdbarch)->have_neon_pseudos && regnum >= 32 && regnum < 48)
     /* Quad-precision register.  */
-    arm_neon_quad_read (gdbarch, regcache, regnum - 32, buf);
+    return arm_neon_quad_read (gdbarch, regcache, regnum - 32, buf);
   else
     {
+      enum register_status status;
+
       /* Single-precision register.  */
       gdb_assert (regnum < 32);
 
@@ -7918,8 +7927,10 @@ arm_pseudo_read (struct gdbarch *gdbarch
       double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
 						   strlen (name_buf));
 
-      regcache_raw_read (regcache, double_regnum, reg_buf);
-      memcpy (buf, reg_buf + offset, 4);
+      status = regcache_raw_read (regcache, double_regnum, reg_buf);
+      if (status == REG_VALID)
+	memcpy (buf, reg_buf + offset, 4);
+      return status;
     }
 }
 
Index: src/gdb/avr-tdep.c
===================================================================
--- src.orig/gdb/avr-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/avr-tdep.c	2011-02-21 21:09:45.469344007 +0000
@@ -354,19 +354,22 @@ avr_write_pc (struct regcache *regcache,
                                   avr_convert_iaddr_to_raw (val));
 }
 
-static void
+static enum register_status
 avr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int regnum, gdb_byte *buf)
 {
   ULONGEST val;
+  enum register_status status;
 
   switch (regnum)
     {
     case AVR_PSEUDO_PC_REGNUM:
-      regcache_raw_read_unsigned (regcache, AVR_PC_REGNUM, &val);
+      status = regcache_raw_read_unsigned (regcache, AVR_PC_REGNUM, &val);
+      if (status != REG_VALID)
+	return status;
       val >>= 1;
       store_unsigned_integer (buf, 4, gdbarch_byte_order (gdbarch), val);
-      break;
+      return status;
     default:
       internal_error (__FILE__, __LINE__, _("invalid regnum"));
     }
Index: src/gdb/frv-tdep.c
===================================================================
--- src.orig/gdb/frv-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/frv-tdep.c	2011-02-21 21:09:45.469344007 +0000
@@ -300,14 +300,17 @@ frv_register_type (struct gdbarch *gdbar
     return builtin_type (gdbarch)->builtin_int32;
 }
 
-static void
+static enum register_status
 frv_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int reg, gdb_byte *buffer)
 {
+  enum register_status status;
+
   if (reg == iacc0_regnum)
     {
-      regcache_raw_read (regcache, iacc0h_regnum, buffer);
-      regcache_raw_read (regcache, iacc0l_regnum, (bfd_byte *) buffer + 4);
+      status = regcache_raw_read (regcache, iacc0h_regnum, buffer);
+      if (status == REG_VALID)
+	status = regcache_raw_read (regcache, iacc0l_regnum, (bfd_byte *) buffer + 4);
     }
   else if (accg0_regnum <= reg && reg <= accg7_regnum)
     {
@@ -316,14 +319,22 @@ frv_pseudo_register_read (struct gdbarch
 
       int raw_regnum = accg0123_regnum + (reg - accg0_regnum) / 4;
       int byte_num = (reg - accg0_regnum) % 4;
-      bfd_byte buf[4];
+      gdb_byte buf[4];
 
-      regcache_raw_read (regcache, raw_regnum, buf);
-      memset (buffer, 0, 4);
-      /* FR-V is big endian, so put the requested byte in the first byte
-         of the buffer allocated to hold the pseudo-register.  */
-      ((bfd_byte *) buffer)[0] = buf[byte_num];
+      status = regcache_raw_read (regcache, raw_regnum, buf);
+      if (status == REG_VALID)
+	{
+	  memset (buffer, 0, 4);
+	  /* FR-V is big endian, so put the requested byte in the
+	     first byte of the buffer allocated to hold the
+	     pseudo-register.  */
+	  buffer[0] = buf[byte_num];
+	}
     }
+  else
+    gdb_assert_not_reached ("invalid pseudo register number");
+
+  return status;
 }
 
 static void
Index: src/gdb/h8300-tdep.c
===================================================================
--- src.orig/gdb/h8300-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/h8300-tdep.c	2011-02-21 21:09:45.469344007 +0000
@@ -1149,17 +1149,17 @@ h8300_register_type (struct gdbarch *gdb
     }
 }
 
-static void
+static enum register_status
 h8300_pseudo_register_read (struct gdbarch *gdbarch,
 			    struct regcache *regcache, int regno,
 			    gdb_byte *buf)
 {
   if (regno == E_PSEUDO_CCR_REGNUM (gdbarch))
-    regcache_raw_read (regcache, E_CCR_REGNUM, buf);
+    return regcache_raw_read (regcache, E_CCR_REGNUM, buf);
   else if (regno == E_PSEUDO_EXR_REGNUM (gdbarch))
-    regcache_raw_read (regcache, E_EXR_REGNUM, buf);
+    return regcache_raw_read (regcache, E_EXR_REGNUM, buf);
   else
-    regcache_raw_read (regcache, regno, buf);
+    return regcache_raw_read (regcache, regno, buf);
 }
 
 static void
Index: src/gdb/hppa-tdep.c
===================================================================
--- src.orig/gdb/hppa-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/hppa-tdep.c	2011-02-21 21:09:45.479344010 +0000
@@ -2665,17 +2665,22 @@ hppa_fetch_pointer_argument (struct fram
   return get_frame_register_unsigned (frame, HPPA_R0_REGNUM + 26 - argi);
 }
 
-static void
+static enum register_status
 hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int regnum, gdb_byte *buf)
 {
-    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-    ULONGEST tmp;
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  ULONGEST tmp;
+  enum register_status status;
 
-    regcache_raw_read_unsigned (regcache, regnum, &tmp);
-    if (regnum == HPPA_PCOQ_HEAD_REGNUM || regnum == HPPA_PCOQ_TAIL_REGNUM)
-      tmp &= ~0x3;
-    store_unsigned_integer (buf, sizeof tmp, byte_order, tmp);
+  status = regcache_raw_read_unsigned (regcache, regnum, &tmp);
+  if (status == REG_VALID)
+    {
+      if (regnum == HPPA_PCOQ_HEAD_REGNUM || regnum == HPPA_PCOQ_TAIL_REGNUM)
+	tmp &= ~0x3;
+      store_unsigned_integer (buf, sizeof tmp, byte_order, tmp);
+    }
+  return status;
 }
 
 static CORE_ADDR
Index: src/gdb/m32c-tdep.c
===================================================================
--- src.orig/gdb/m32c-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/m32c-tdep.c	2011-02-21 21:09:45.479344010 +0000
@@ -54,9 +54,9 @@ struct m32c_reg;
 
 /* The type of a function that moves the value of REG between CACHE or
    BUF --- in either direction.  */
-typedef void (m32c_move_reg_t) (struct m32c_reg *reg,
-				struct regcache *cache,
-				void *buf);
+typedef enum register_status (m32c_move_reg_t) (struct m32c_reg *reg,
+						struct regcache *cache,
+						void *buf);
 
 struct m32c_reg
 {
@@ -315,18 +315,20 @@ static m32c_move_reg_t m32c_r3r2r1r0_rea
 
 
 /* Copy the value of the raw register REG from CACHE to BUF.  */
-static void
+static enum register_status
 m32c_raw_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
-  regcache_raw_read (cache, reg->num, buf);
+  return regcache_raw_read (cache, reg->num, buf);
 }
 
 
 /* Copy the value of the raw register REG from BUF to CACHE.  */
-static void
+static enum register_status
 m32c_raw_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   regcache_raw_write (cache, reg->num, (const void *) buf);
+
+  return REG_VALID;
 }
 
 
@@ -353,11 +355,11 @@ m32c_banked_register (struct m32c_reg *r
    If the value of the 'flg' register in CACHE has any of the bits
    masked in REG->n set, then read REG->ry.  Otherwise, read
    REG->rx.  */
-static void
+static enum register_status
 m32c_banked_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   struct m32c_reg *bank_reg = m32c_banked_register (reg, cache);
-  regcache_raw_read (cache, bank_reg->num, buf);
+  return regcache_raw_read (cache, bank_reg->num, buf);
 }
 
 
@@ -365,35 +367,39 @@ m32c_banked_read (struct m32c_reg *reg,
    If the value of the 'flg' register in CACHE has any of the bits
    masked in REG->n set, then write REG->ry.  Otherwise, write
    REG->rx.  */
-static void
+static enum register_status
 m32c_banked_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   struct m32c_reg *bank_reg = m32c_banked_register (reg, cache);
   regcache_raw_write (cache, bank_reg->num, (const void *) buf);
+
+  return REG_VALID;
 }
 
 
 /* Move the value of SB from CACHE to BUF.  On bfd_mach_m32c, SB is a
    banked register; on bfd_mach_m16c, it's not.  */
-static void
+static enum register_status
 m32c_sb_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   if (gdbarch_bfd_arch_info (reg->arch)->mach == bfd_mach_m16c)
-    m32c_raw_read (reg->rx, cache, buf);
+    return m32c_raw_read (reg->rx, cache, buf);
   else
-    m32c_banked_read (reg, cache, buf);
+    return m32c_banked_read (reg, cache, buf);
 }
 
 
 /* Move the value of SB from BUF to CACHE.  On bfd_mach_m32c, SB is a
    banked register; on bfd_mach_m16c, it's not.  */
-static void
+static enum register_status
 m32c_sb_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   if (gdbarch_bfd_arch_info (reg->arch)->mach == bfd_mach_m16c)
     m32c_raw_write (reg->rx, cache, buf);
   else
     m32c_banked_write (reg, cache, buf);
+
+  return REG_VALID;
 }
 
 
@@ -438,13 +444,14 @@ m32c_find_part (struct m32c_reg *reg, in
    to BUF.  Treating the value of the register REG->rx as an array of
    REG->type values, where higher indices refer to more significant
    bits, read the value of the REG->n'th element.  */
-static void
+static enum register_status
 m32c_part_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   int offset, len;
+
   memset (buf, 0, TYPE_LENGTH (reg->type));
   m32c_find_part (reg, &offset, &len);
-  regcache_cooked_read_part (cache, reg->rx->num, offset, len, buf);
+  return regcache_cooked_read_part (cache, reg->rx->num, offset, len, buf);
 }
 
 
@@ -452,45 +459,53 @@ m32c_part_read (struct m32c_reg *reg, st
    Treating the value of the register REG->rx as an array of REG->type
    values, where higher indices refer to more significant bits, write
    the value of the REG->n'th element.  */
-static void
+static enum register_status
 m32c_part_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   int offset, len;
+
   m32c_find_part (reg, &offset, &len);
   regcache_cooked_write_part (cache, reg->rx->num, offset, len, buf);
+
+  return REG_VALID;
 }
 
 
 /* Move the value of REG from CACHE to BUF.  REG's value is the
    concatenation of the values of the registers REG->rx and REG->ry,
    with REG->rx contributing the more significant bits.  */
-static void
+static enum register_status
 m32c_cat_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   int high_bytes = TYPE_LENGTH (reg->rx->type);
   int low_bytes  = TYPE_LENGTH (reg->ry->type);
   /* For address arithmetic.  */
   unsigned char *cbuf = buf;
+  enum register_status status;
 
   gdb_assert (TYPE_LENGTH (reg->type) == high_bytes + low_bytes);
 
   if (gdbarch_byte_order (reg->arch) == BFD_ENDIAN_BIG)
     {
-      regcache_cooked_read (cache, reg->rx->num, cbuf);
-      regcache_cooked_read (cache, reg->ry->num, cbuf + high_bytes);
+      status = regcache_cooked_read (cache, reg->rx->num, cbuf);
+      if (status == REG_VALID)
+	status = regcache_cooked_read (cache, reg->ry->num, cbuf + high_bytes);
     }
   else
     {
-      regcache_cooked_read (cache, reg->rx->num, cbuf + low_bytes);
-      regcache_cooked_read (cache, reg->ry->num, cbuf);
+      status = regcache_cooked_read (cache, reg->rx->num, cbuf + low_bytes);
+      if (status == REG_VALID)
+	status = regcache_cooked_read (cache, reg->ry->num, cbuf);
     }
+
+  return status;
 }
 
 
 /* Move the value of REG from CACHE to BUF.  REG's value is the
    concatenation of the values of the registers REG->rx and REG->ry,
    with REG->rx contributing the more significant bits.  */
-static void
+static enum register_status
 m32c_cat_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   int high_bytes = TYPE_LENGTH (reg->rx->type);
@@ -510,42 +525,53 @@ m32c_cat_write (struct m32c_reg *reg, st
       regcache_cooked_write (cache, reg->rx->num, cbuf + low_bytes);
       regcache_cooked_write (cache, reg->ry->num, cbuf);
     }
+
+  return REG_VALID;
 }
 
 
 /* Copy the value of the raw register REG from CACHE to BUF.  REG is
    the concatenation (from most significant to least) of r3, r2, r1,
    and r0.  */
-static void
+static enum register_status
 m32c_r3r2r1r0_read (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (reg->arch);
   int len = TYPE_LENGTH (tdep->r0->type);
+  enum register_status status;
 
   /* For address arithmetic.  */
   unsigned char *cbuf = buf;
 
   if (gdbarch_byte_order (reg->arch) == BFD_ENDIAN_BIG)
     {
-      regcache_cooked_read (cache, tdep->r0->num, cbuf + len * 3);
-      regcache_cooked_read (cache, tdep->r1->num, cbuf + len * 2);
-      regcache_cooked_read (cache, tdep->r2->num, cbuf + len * 1);
-      regcache_cooked_read (cache, tdep->r3->num, cbuf);
+      status = regcache_cooked_read (cache, tdep->r0->num, cbuf + len * 3);
+      if (status == REG_VALID)
+	status = regcache_cooked_read (cache, tdep->r1->num, cbuf + len * 2);
+      if (status == REG_VALID)
+	status = regcache_cooked_read (cache, tdep->r2->num, cbuf + len * 1);
+      if (status == REG_VALID)
+	status = regcache_cooked_read (cache, tdep->r3->num, cbuf);
     }
   else
     {
-      regcache_cooked_read (cache, tdep->r0->num, cbuf);
-      regcache_cooked_read (cache, tdep->r1->num, cbuf + len * 1);
-      regcache_cooked_read (cache, tdep->r2->num, cbuf + len * 2);
-      regcache_cooked_read (cache, tdep->r3->num, cbuf + len * 3);
+      status = regcache_cooked_read (cache, tdep->r0->num, cbuf);
+      if (status == REG_VALID)
+	status = regcache_cooked_read (cache, tdep->r1->num, cbuf + len * 1);
+      if (status == REG_VALID)
+	status = regcache_cooked_read (cache, tdep->r2->num, cbuf + len * 2);
+      if (status == REG_VALID)
+	status = regcache_cooked_read (cache, tdep->r3->num, cbuf + len * 3);
     }
+
+  return status;
 }
 
 
 /* Copy the value of the raw register REG from BUF to CACHE.  REG is
    the concatenation (from most significant to least) of r3, r2, r1,
    and r0.  */
-static void
+static enum register_status
 m32c_r3r2r1r0_write (struct m32c_reg *reg, struct regcache *cache, void *buf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (reg->arch);
@@ -568,10 +594,12 @@ m32c_r3r2r1r0_write (struct m32c_reg *re
       regcache_cooked_write (cache, tdep->r2->num, cbuf + len * 2);
       regcache_cooked_write (cache, tdep->r3->num, cbuf + len * 3);
     }
+
+  return REG_VALID;
 }
 
 
-static void
+static enum register_status
 m32c_pseudo_register_read (struct gdbarch *arch,
 			   struct regcache *cache,
 			   int cookednum,
@@ -585,7 +613,7 @@ m32c_pseudo_register_read (struct gdbarc
   gdb_assert (arch == tdep->regs[cookednum].arch);
   reg = &tdep->regs[cookednum];
 
-  reg->read (reg, cache, buf);
+  return reg->read (reg, cache, buf);
 }
 
 
Index: src/gdb/m68hc11-tdep.c
===================================================================
--- src.orig/gdb/m68hc11-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/m68hc11-tdep.c	2011-02-21 21:09:45.479344010 +0000
@@ -279,7 +279,7 @@ m68hc11_which_soft_register (CORE_ADDR a
 /* Fetch a pseudo register.  The 68hc11 soft registers are treated like
    pseudo registers.  They are located in memory.  Translate the register
    fetch into a memory read.  */
-static void
+static enum register_status
 m68hc11_pseudo_register_read (struct gdbarch *gdbarch,
 			      struct regcache *regcache,
 			      int regno, gdb_byte *buf)
@@ -292,8 +292,11 @@ m68hc11_pseudo_register_read (struct gdb
     {
       ULONGEST pc;
       const int regsize = 4;
+      enum register_status status;
 
-      regcache_cooked_read_unsigned (regcache, HARD_PC_REGNUM, &pc);
+      status = regcache_cooked_read_unsigned (regcache, HARD_PC_REGNUM, &pc);
+      if (status != REG_VALID)
+	return status;
       if (pc >= 0x8000 && pc < 0xc000)
         {
           ULONGEST page;
@@ -304,7 +307,7 @@ m68hc11_pseudo_register_read (struct gdb
           pc += 0x1000000;
         }
       store_unsigned_integer (buf, regsize, byte_order, pc);
-      return;
+      return REG_VALID;
     }
 
   m68hc11_initialize_register_info ();
@@ -318,6 +321,8 @@ m68hc11_pseudo_register_read (struct gdb
     {
       memset (buf, 0, 2);
     }
+
+  return REG_VALID;
 }
 
 /* Store a pseudo register.  Translate the register store
Index: src/gdb/mep-tdep.c
===================================================================
--- src.orig/gdb/mep-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/mep-tdep.c	2011-02-21 21:09:45.479344010 +0000
@@ -1133,12 +1133,13 @@ mep_write_pc (struct regcache *regcache,
 }
 
 
-static void
+static enum register_status
 mep_pseudo_cr32_read (struct gdbarch *gdbarch,
                       struct regcache *regcache,
                       int cookednum,
                       void *buf)
 {
+  enum register_status status;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   /* Read the raw register into a 64-bit buffer, and then return the
      appropriate end of that buffer.  */
@@ -1147,24 +1148,28 @@ mep_pseudo_cr32_read (struct gdbarch *gd
 
   gdb_assert (TYPE_LENGTH (register_type (gdbarch, rawnum)) == sizeof (buf64));
   gdb_assert (TYPE_LENGTH (register_type (gdbarch, cookednum)) == 4);
-  regcache_raw_read (regcache, rawnum, buf64);
-  /* Slow, but legible.  */
-  store_unsigned_integer (buf, 4, byte_order,
-			  extract_unsigned_integer (buf64, 8, byte_order));
+  status = regcache_raw_read (regcache, rawnum, buf64);
+  if (status == REG_VALID)
+    {
+      /* Slow, but legible.  */
+      store_unsigned_integer (buf, 4, byte_order,
+			      extract_unsigned_integer (buf64, 8, byte_order));
+    }
+  return status;
 }
 
 
-static void
+static enum register_status
 mep_pseudo_cr64_read (struct gdbarch *gdbarch,
                       struct regcache *regcache,
                       int cookednum,
                       void *buf)
 {
-  regcache_raw_read (regcache, mep_pseudo_to_raw[cookednum], buf);
+  return regcache_raw_read (regcache, mep_pseudo_to_raw[cookednum], buf);
 }
 
 
-static void
+static enum register_status
 mep_pseudo_register_read (struct gdbarch *gdbarch,
                           struct regcache *regcache,
                           int cookednum,
@@ -1172,13 +1177,13 @@ mep_pseudo_register_read (struct gdbarch
 {
   if (IS_CSR_REGNUM (cookednum)
       || IS_CCR_REGNUM (cookednum))
-    regcache_raw_read (regcache, mep_pseudo_to_raw[cookednum], buf);
+    return regcache_raw_read (regcache, mep_pseudo_to_raw[cookednum], buf);
   else if (IS_CR32_REGNUM (cookednum)
            || IS_FP_CR32_REGNUM (cookednum))
-    mep_pseudo_cr32_read (gdbarch, regcache, cookednum, buf);
+    return mep_pseudo_cr32_read (gdbarch, regcache, cookednum, buf);
   else if (IS_CR64_REGNUM (cookednum)
            || IS_FP_CR64_REGNUM (cookednum))
-    mep_pseudo_cr64_read (gdbarch, regcache, cookednum, buf);
+    return mep_pseudo_cr64_read (gdbarch, regcache, cookednum, buf);
   else
     gdb_assert_not_reached ("unexpected pseudo register");
 }
Index: src/gdb/mips-tdep.c
===================================================================
--- src.orig/gdb/mips-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/mips-tdep.c	2011-02-21 21:09:45.479344010 +0000
@@ -564,7 +564,7 @@ mips_tdesc_register_reggroup_p (struct g
    gdbarch_num_regs .. 2 * gdbarch_num_regs) back onto the corresponding raw
    registers.  Take care of alignment and size problems.  */
 
-static void
+static enum register_status
 mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int cookednum, gdb_byte *buf)
 {
@@ -572,18 +572,22 @@ mips_pseudo_register_read (struct gdbarc
   gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
 	      && cookednum < 2 * gdbarch_num_regs (gdbarch));
   if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
-    regcache_raw_read (regcache, rawnum, buf);
+    return regcache_raw_read (regcache, rawnum, buf);
   else if (register_size (gdbarch, rawnum) >
 	   register_size (gdbarch, cookednum))
     {
       if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
-	regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
+	return regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
       else
 	{
 	  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 	  LONGEST regval;
-	  regcache_raw_read_signed (regcache, rawnum, &regval);
-	  store_signed_integer (buf, 4, byte_order, regval);
+	  enum register_status status;
+
+	  status = regcache_raw_read_signed (regcache, rawnum, &regval);
+	  if (status == REG_VALID)
+	    store_signed_integer (buf, 4, byte_order, regval);
+	  return status;
 	}
     }
   else
Index: src/gdb/mt-tdep.c
===================================================================
--- src.orig/gdb/mt-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/mt-tdep.c	2011-02-21 21:09:45.479344010 +0000
@@ -524,9 +524,9 @@ mt_select_coprocessor (struct gdbarch *g
    Additionally there is an array of coprocessor registers which track
    the coprocessor registers for each coprocessor.  */
 
-static void
+static enum register_status
 mt_pseudo_register_read (struct gdbarch *gdbarch,
-			  struct regcache *regcache, int regno, gdb_byte *buf)
+			 struct regcache *regcache, int regno, gdb_byte *buf)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
@@ -534,34 +534,45 @@ mt_pseudo_register_read (struct gdbarch
     {
     case MT_COPRO_REGNUM:
     case MT_COPRO_PSEUDOREG_REGNUM:
-      regcache_raw_read (regcache, MT_COPRO_REGNUM, buf);
-      break;
+      return regcache_raw_read (regcache, MT_COPRO_REGNUM, buf);
     case MT_MAC_REGNUM:
     case MT_MAC_PSEUDOREG_REGNUM:
       if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_mrisc2
 	  || gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_ms2)
 	{
+	  enum register_status status;
 	  ULONGEST oldmac = 0, ext_mac = 0;
 	  ULONGEST newmac;
 
-	  regcache_cooked_read_unsigned (regcache, MT_MAC_REGNUM, &oldmac);
+	  status = regcache_cooked_read_unsigned (regcache, MT_MAC_REGNUM, &oldmac);
+	  if (status != REG_VALID)
+	    return status;
+
 	  regcache_cooked_read_unsigned (regcache, MT_EXMAC_REGNUM, &ext_mac);
+	  if (status != REG_VALID)
+	    return status;
+
 	  newmac =
 	    (oldmac & 0xffffffff) | ((long long) (ext_mac & 0xff) << 32);
 	  store_signed_integer (buf, 8, byte_order, newmac);
+
+	  return REG_VALID;
 	}
       else
-	regcache_raw_read (regcache, MT_MAC_REGNUM, buf);
+	return regcache_raw_read (regcache, MT_MAC_REGNUM, buf);
       break;
     default:
       {
 	unsigned index = mt_select_coprocessor (gdbarch, regcache, regno);
 	
 	if (index == MT_COPRO_PSEUDOREG_MAC_REGNUM)
-	  mt_pseudo_register_read (gdbarch, regcache,
-				   MT_MAC_PSEUDOREG_REGNUM, buf);
+	  return mt_pseudo_register_read (gdbarch, regcache,
+					  MT_MAC_PSEUDOREG_REGNUM, buf);
 	else if (index < MT_NUM_REGS - MT_CPR0_REGNUM)
-	  regcache_raw_read (regcache, index + MT_CPR0_REGNUM, buf);
+	  return regcache_raw_read (regcache, index + MT_CPR0_REGNUM, buf);
+	else
+	  /* ??? */
+	  return REG_VALID;
       }
       break;
     }
Index: src/gdb/rs6000-tdep.c
===================================================================
--- src.orig/gdb/rs6000-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/rs6000-tdep.c	2011-02-21 21:09:45.489344004 +0000
@@ -2536,6 +2536,11 @@ rs6000_value_to_register (struct frame_i
   put_frame_register (frame, regnum, to);
 }
 
+ /* The type of a function that moves the value of REG between CACHE
+    or BUF --- in either direction.  */
+typedef enum register_status (*move_ev_register_func) (struct regcache *,
+						       int, void *);
+
 /* Move SPE vector register values between a 64-bit buffer and the two
    32-bit raw register halves in a regcache.  This function handles
    both splitting a 64-bit value into two 32-bit halves, and joining
@@ -2559,16 +2564,16 @@ rs6000_value_to_register (struct frame_i
    MOVE, since this function can't tell at compile-time which of
    REGCACHE or BUFFER is acting as the source of the data.  If C had
    co-variant type qualifiers, ...  */
-static void
-e500_move_ev_register (void (*move) (struct regcache *regcache,
-                                     int regnum, gdb_byte *buf),
-                       struct regcache *regcache, int ev_reg,
-                       gdb_byte *buffer)
+
+static enum register_status
+e500_move_ev_register (move_ev_register_func move,
+		       struct regcache *regcache, int ev_reg, void *buffer)
 {
   struct gdbarch *arch = get_regcache_arch (regcache);
   struct gdbarch_tdep *tdep = gdbarch_tdep (arch); 
   int reg_index;
   gdb_byte *byte_buffer = buffer;
+  enum register_status status;
 
   gdb_assert (IS_SPE_PSEUDOREG (tdep, ev_reg));
 
@@ -2576,55 +2581,80 @@ e500_move_ev_register (void (*move) (str
 
   if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG)
     {
-      move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer);
-      move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer + 4);
+      status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index,
+		     byte_buffer);
+      if (status == REG_VALID)
+	status = move (regcache, tdep->ppc_gp0_regnum + reg_index,
+		       byte_buffer + 4);
     }
   else
     {
-      move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer);
-      move (regcache, tdep->ppc_ev0_upper_regnum + reg_index, byte_buffer + 4);
+      status = move (regcache, tdep->ppc_gp0_regnum + reg_index, byte_buffer);
+      if (status == REG_VALID)
+	status = move (regcache, tdep->ppc_ev0_upper_regnum + reg_index,
+		       byte_buffer + 4);
     }
+
+  return status;
 }
 
-static void
+static enum register_status
+do_regcache_raw_read (struct regcache *regcache, int regnum, void *buffer)
+{
+  return regcache_raw_read (regcache, regnum, buffer);
+}
+
+static enum register_status
+do_regcache_raw_write (struct regcache *regcache, int regnum, void *buffer)
+{
+  regcache_raw_write (regcache, regnum, buffer);
+
+  return REG_VALID;
+}
+
+static enum register_status
 e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
-  e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer);
+  return e500_move_ev_register (do_regcache_raw_read, regcache, reg_nr, buffer);
 }
 
 static void
 e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 			    int reg_nr, const gdb_byte *buffer)
 {
-  e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *))
-			 regcache_raw_write,
-			 regcache, reg_nr, (gdb_byte *) buffer);
+  e500_move_ev_register (do_regcache_raw_write, regcache,
+			 reg_nr, (void *) buffer);
 }
 
 /* Read method for DFP pseudo-registers.  */
-static void
+static enum register_status
 dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+  enum register_status status;
 
   if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
     {
       /* Read two FP registers to form a whole dl register.  */
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-			 2 * reg_index, buffer);
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-			 2 * reg_index + 1, buffer + 8);
+      status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+				  2 * reg_index, buffer);
+      if (status == REG_VALID)
+	status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+				    2 * reg_index + 1, buffer + 8);
     }
   else
     {
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-			 2 * reg_index + 1, buffer + 8);
-      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-			 2 * reg_index, buffer);
+      status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+				  2 * reg_index + 1, buffer + 8);
+      if (status == REG_VALID)
+	status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+				    2 * reg_index, buffer);
     }
+
+  return status;
 }
 
 /* Write method for DFP pseudo-registers.  */
@@ -2654,33 +2684,38 @@ dfp_pseudo_register_write (struct gdbarc
 }
 
 /* Read method for POWER7 VSX pseudo-registers.  */
-static void
+static enum register_status
 vsx_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+  enum register_status status;
 
   /* Read the portion that overlaps the VMX registers.  */
   if (reg_index > 31)
-    regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
-			reg_index - 32, buffer);
+    status = regcache_raw_read (regcache, tdep->ppc_vr0_regnum +
+				reg_index - 32, buffer);
   else
     /* Read the portion that overlaps the FPR registers.  */
     if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
       {
-	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-			reg_index, buffer);
-	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
-			reg_index, buffer + 8);
+	status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+				    reg_index, buffer);
+	if (status == REG_VALID)
+	  status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+				      reg_index, buffer + 8);
       }
     else
       {
-	regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
-			reg_index, buffer + 8);
-	regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
-			reg_index, buffer);
+	status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+				    reg_index, buffer + 8);
+	if (status == REG_VALID)
+	  status = regcache_raw_read (regcache, tdep->ppc_vsr0_upper_regnum +
+				      reg_index, buffer);
       }
+
+  return status;
 }
 
 /* Write method for POWER7 VSX pseudo-registers.  */
@@ -2714,7 +2749,7 @@ vsx_pseudo_register_write (struct gdbarc
 }
 
 /* Read method for POWER7 Extended FP pseudo-registers.  */
-static void
+static enum register_status
 efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
@@ -2722,8 +2757,8 @@ efpr_pseudo_register_read (struct gdbarc
   int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
 
   /* Read the portion that overlaps the VMX register.  */
-  regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index, 0,
-			  register_size (gdbarch, reg_nr), buffer);
+  return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index, 0,
+				 register_size (gdbarch, reg_nr), buffer);
 }
 
 /* Write method for POWER7 Extended FP pseudo-registers.  */
@@ -2739,7 +2774,7 @@ efpr_pseudo_register_write (struct gdbar
 			   register_size (gdbarch, reg_nr), buffer);
 }
 
-static void
+static enum register_status
 rs6000_pseudo_register_read (struct gdbarch *gdbarch,
 			     struct regcache *regcache,
 			     int reg_nr, gdb_byte *buffer)
@@ -2750,13 +2785,13 @@ rs6000_pseudo_register_read (struct gdba
   gdb_assert (regcache_arch == gdbarch);
 
   if (IS_SPE_PSEUDOREG (tdep, reg_nr))
-    e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+    return e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
-    dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+    return dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
-    vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+    return vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
-    efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+    return efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
 		    _("rs6000_pseudo_register_read: "
Index: src/gdb/s390-tdep.c
===================================================================
--- src.orig/gdb/s390-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/s390-tdep.c	2011-02-21 21:09:45.489344004 +0000
@@ -216,7 +216,7 @@ s390_pseudo_register_type (struct gdbarc
   internal_error (__FILE__, __LINE__, _("invalid regnum"));
 }
 
-static void
+static enum register_status
 s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int regnum, gdb_byte *buf)
 {
@@ -227,37 +227,53 @@ s390_pseudo_register_read (struct gdbarc
 
   if (regnum == tdep->pc_regnum)
     {
-      regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &val);
-      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
-	val &= 0x7fffffff;
-      store_unsigned_integer (buf, regsize, byte_order, val);
-      return;
+      enum register_status status;
+
+      status = regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &val);
+      if (status == REG_VALID)
+	{
+	  if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+	    val &= 0x7fffffff;
+	  store_unsigned_integer (buf, regsize, byte_order, val);
+	}
+      return status;
     }
 
   if (regnum == tdep->cc_regnum)
     {
-      regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val);
-      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
-	val = (val >> 12) & 3;
-      else
-	val = (val >> 44) & 3;
-      store_unsigned_integer (buf, regsize, byte_order, val);
-      return;
+      enum register_status status;
+
+      status = regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val);
+      if (status == REG_VALID)
+	{
+	  if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+	    val = (val >> 12) & 3;
+	  else
+	    val = (val >> 44) & 3;
+	  store_unsigned_integer (buf, regsize, byte_order, val);
+	}
+      return status;
     }
 
   if (tdep->gpr_full_regnum != -1
       && regnum >= tdep->gpr_full_regnum
       && regnum < tdep->gpr_full_regnum + 16)
     {
+      enum register_status status;
       ULONGEST val_upper;
+
       regnum -= tdep->gpr_full_regnum;
 
-      regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + regnum, &val);
-      regcache_raw_read_unsigned (regcache, S390_R0_UPPER_REGNUM + regnum,
-				  &val_upper);
-      val |= val_upper << 32;
-      store_unsigned_integer (buf, regsize, byte_order, val);
-      return;
+      status = regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + regnum, &val);
+      if (status == REG_VALID)
+	status = regcache_raw_read_unsigned (regcache, S390_R0_UPPER_REGNUM + regnum,
+					     &val_upper);
+      if (status == REG_VALID)
+	{
+	  val |= val_upper << 32;
+	  store_unsigned_integer (buf, regsize, byte_order, val);
+	}
+      return status;
     }
 
   internal_error (__FILE__, __LINE__, _("invalid regnum"));
Index: src/gdb/sh64-tdep.c
===================================================================
--- src.orig/gdb/sh64-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/sh64-tdep.c	2011-02-21 21:09:45.489344004 +0000
@@ -1619,15 +1619,40 @@ sh64_register_convert_to_raw (struct gdb
 	     "with non DR register number"));
 }
 
-static void
+/* Concatenate PORTIONS contiguous raw registers starting at
+   BASE_REGNUM into BUFFER.  */
+
+static enum register_status
+pseudo_register_read_portions (struct gdbarch *gdbarch,
+			       struct regcache *regcache,
+			       int portions,
+			       int base_regnum, gdb_byte *buffer)
+{
+  int portion;
+
+  for (portion = 0; portion < portions; portion++)
+    {
+      enum register_status status;
+      gdb_byte *b;
+
+      b = buffer + register_size (gdbarch, base_regnum) * portion;
+      status = regcache_raw_read (regcache, base_regnum + portion, b);
+      if (status != REG_VALID)
+	return status;
+    }
+
+  return REG_VALID;
+}
+
+static enum register_status
 sh64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int base_regnum;
-  int portion;
   int offset = 0;
   char temp_buffer[MAX_REGISTER_SIZE];
+  enum register_status status;
 
   if (reg_nr >= DR0_REGNUM 
       && reg_nr <= DR_LAST_REGNUM)
@@ -1637,19 +1662,20 @@ sh64_pseudo_register_read (struct gdbarc
       /* Build the value in the provided buffer.  */ 
       /* DR regs are double precision registers obtained by
 	 concatenating 2 single precision floating point registers.  */
-      for (portion = 0; portion < 2; portion++)
-	regcache_raw_read (regcache, base_regnum + portion, 
-			   (temp_buffer
-			    + register_size (gdbarch, base_regnum) * portion));
-
-      /* We must pay attention to the endianness.  */
-      sh64_register_convert_to_virtual (gdbarch, reg_nr,
-					register_type (gdbarch, reg_nr),
-					temp_buffer, buffer);
+      status = pseudo_register_read_portions (gdbarch, regcache,
+					      2, base_regnum, temp_buffer);
+      if (status == REG_VALID)
+	{
+	  /* We must pay attention to the endianness.  */
+	  sh64_register_convert_to_virtual (gdbarch, reg_nr,
+					    register_type (gdbarch, reg_nr),
+					    temp_buffer, buffer);
+	}
 
+      return status;
     }
 
-  else if (reg_nr >= FPP0_REGNUM 
+  else if (reg_nr >= FPP0_REGNUM
 	   && reg_nr <= FPP_LAST_REGNUM)
     {
       base_regnum = sh64_fpp_reg_base_num (gdbarch, reg_nr);
@@ -1657,10 +1683,8 @@ sh64_pseudo_register_read (struct gdbarc
       /* Build the value in the provided buffer.  */ 
       /* FPP regs are pairs of single precision registers obtained by
 	 concatenating 2 single precision floating point registers.  */
-      for (portion = 0; portion < 2; portion++)
-	regcache_raw_read (regcache, base_regnum + portion, 
-			   ((char *) buffer
-			    + register_size (gdbarch, base_regnum) * portion));
+      return pseudo_register_read_portions (gdbarch, regcache,
+					    2, base_regnum, buffer);
     }
 
   else if (reg_nr >= FV0_REGNUM 
@@ -1671,10 +1695,8 @@ sh64_pseudo_register_read (struct gdbarc
       /* Build the value in the provided buffer.  */ 
       /* FV regs are vectors of single precision registers obtained by
 	 concatenating 4 single precision floating point registers.  */
-      for (portion = 0; portion < 4; portion++)
-	regcache_raw_read (regcache, base_regnum + portion, 
-			   ((char *) buffer
-			    + register_size (gdbarch, base_regnum) * portion));
+      return pseudo_register_read_portions (gdbarch, regcache,
+					    4, base_regnum, buffer);
     }
 
   /* sh compact pseudo registers.  1-to-1 with a shmedia register.  */
@@ -1684,11 +1706,14 @@ sh64_pseudo_register_read (struct gdbarc
       base_regnum = sh64_compact_reg_base_num (gdbarch, reg_nr);
 
       /* Build the value in the provided buffer.  */ 
-      regcache_raw_read (regcache, base_regnum, temp_buffer);
+      status = regcache_raw_read (regcache, base_regnum, temp_buffer);
+      if (status != REG_VALID)
+	return status;
       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
 	offset = 4;
       memcpy (buffer,
 	      temp_buffer + offset, 4); /* get LOWER 32 bits only????  */
+      return REG_VALID;
     }
 
   else if (reg_nr >= FP0_C_REGNUM
@@ -1699,7 +1724,7 @@ sh64_pseudo_register_read (struct gdbarc
       /* Build the value in the provided buffer.  */ 
       /* Floating point registers map 1-1 to the media fp regs,
 	 they have the same size and endianness.  */
-      regcache_raw_read (regcache, base_regnum, buffer);
+      return regcache_raw_read (regcache, base_regnum, buffer);
     }
 
   else if (reg_nr >= DR0_C_REGNUM 
@@ -1709,15 +1734,16 @@ sh64_pseudo_register_read (struct gdbarc
 
       /* DR_C regs are double precision registers obtained by
 	 concatenating 2 single precision floating point registers.  */
-      for (portion = 0; portion < 2; portion++)
-	regcache_raw_read (regcache, base_regnum + portion, 
-			   (temp_buffer
-			    + register_size (gdbarch, base_regnum) * portion));
-
-      /* We must pay attention to the endianness.  */
-      sh64_register_convert_to_virtual (gdbarch, reg_nr, 
-					register_type (gdbarch, reg_nr),
-					temp_buffer, buffer);
+      status = pseudo_register_read_portions (gdbarch, regcache,
+					      2, base_regnum, temp_buffer);
+      if (status == REG_VALID)
+	{
+	  /* We must pay attention to the endianness.  */
+	  sh64_register_convert_to_virtual (gdbarch, reg_nr,
+					    register_type (gdbarch, reg_nr),
+					    temp_buffer, buffer);
+	}
+      return status;
     }
 
   else if (reg_nr >= FV0_C_REGNUM 
@@ -1728,10 +1754,8 @@ sh64_pseudo_register_read (struct gdbarc
       /* Build the value in the provided buffer.  */ 
       /* FV_C regs are vectors of single precision registers obtained by
 	 concatenating 4 single precision floating point registers.  */
-      for (portion = 0; portion < 4; portion++)
-	regcache_raw_read (regcache, base_regnum + portion, 
-			   ((char *) buffer
-			    + register_size (gdbarch, base_regnum) * portion));
+      return pseudo_register_read_portions (gdbarch, regcache,
+					    4, base_regnum, buffer);
     }
 
   else if (reg_nr == FPSCR_C_REGNUM)
@@ -1762,11 +1786,15 @@ sh64_pseudo_register_read (struct gdbarc
        */
       /* *INDENT-ON* */
       /* Get FPSCR into a local buffer.  */
-      regcache_raw_read (regcache, fpscr_base_regnum, temp_buffer);
+      status = regcache_raw_read (regcache, fpscr_base_regnum, temp_buffer);
+      if (status != REG_VALID)
+	return status;
       /* Get value as an int.  */
       fpscr_value = extract_unsigned_integer (temp_buffer, 4, byte_order);
       /* Get SR into a local buffer */
-      regcache_raw_read (regcache, sr_base_regnum, temp_buffer);
+      status = regcache_raw_read (regcache, sr_base_regnum, temp_buffer);
+      if (status != REG_VALID)
+	return status;
       /* Get value as an int.  */
       sr_value = extract_unsigned_integer (temp_buffer, 4, byte_order);
       /* Build the new value.  */
@@ -1776,6 +1804,8 @@ sh64_pseudo_register_read (struct gdbarc
       /* Store that in out buffer!!!  */
       store_unsigned_integer (buffer, 4, byte_order, fpscr_c_value);
       /* FIXME There is surely an endianness gotcha here.  */
+
+      return REG_VALID;
     }
 
   else if (reg_nr == FPUL_C_REGNUM)
@@ -1784,8 +1814,10 @@ sh64_pseudo_register_read (struct gdbarc
 
       /* FPUL_C register is floating point register 32,
 	 same size, same endianness.  */
-      regcache_raw_read (regcache, base_regnum, buffer);
+      return regcache_raw_read (regcache, base_regnum, buffer);
     }
+  else
+    gdb_assert_not_reached ("invalid pseudo register number");
 }
 
 static void
Index: src/gdb/ia64-tdep.c
===================================================================
--- src.orig/gdb/ia64-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/ia64-tdep.c	2011-02-21 21:09:45.489344004 +0000
@@ -933,11 +933,12 @@ rse_address_add(CORE_ADDR addr, int nslo
   return new_addr;
 }
 
-static void
+static enum register_status
 ia64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                            int regnum, gdb_byte *buf)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum register_status status;
 
   if (regnum >= V32_REGNUM && regnum <= V127_REGNUM)
     {
@@ -952,12 +953,21 @@ ia64_pseudo_register_read (struct gdbarc
 	     found sequentially in memory starting at $bof.  This
 	     isn't always true, but without libunwind, this is the
 	     best we can do.  */
+	  enum register_status status;
 	  ULONGEST cfm;
 	  ULONGEST bsp;
 	  CORE_ADDR reg;
-	  regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
-	  regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
-	  
+
+	  status = regcache_cooked_read_unsigned (regcache,
+						  IA64_BSP_REGNUM, &bsp);
+	  if (status != REG_VALID)
+	    return status;
+
+	  status = regcache_cooked_read_unsigned (regcache,
+						  IA64_CFM_REGNUM, &cfm);
+	  if (status != REG_VALID)
+	    return status;
+
 	  /* The bsp points at the end of the register frame so we
 	     subtract the size of frame from it to get start of
 	     register frame.  */
@@ -979,7 +989,9 @@ ia64_pseudo_register_read (struct gdbarc
     {
       ULONGEST unatN_val;
       ULONGEST unat;
-      regcache_cooked_read_unsigned (regcache, IA64_UNAT_REGNUM, &unat);
+      status = regcache_cooked_read_unsigned (regcache, IA64_UNAT_REGNUM, &unat);
+      if (status != REG_VALID)
+	return status;
       unatN_val = (unat & (1LL << (regnum - IA64_NAT0_REGNUM))) != 0;
       store_unsigned_integer (buf, register_size (gdbarch, regnum),
 			      byte_order, unatN_val);
@@ -990,8 +1002,12 @@ ia64_pseudo_register_read (struct gdbarc
       ULONGEST bsp;
       ULONGEST cfm;
       CORE_ADDR gr_addr = 0;
-      regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
-      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
+      status = regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
+      if (status != REG_VALID)
+	return status;
+      status = regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
+      if (status != REG_VALID)
+	return status;
 
       /* The bsp points at the end of the register frame so we
 	 subtract the size of frame from it to get start of register frame.  */
@@ -1028,8 +1044,12 @@ ia64_pseudo_register_read (struct gdbarc
       ULONGEST bsp, vbsp;
       ULONGEST cfm;
       CORE_ADDR reg;
-      regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
-      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
+      status = regcache_cooked_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp);
+      if (status != REG_VALID)
+	return status;
+      status = regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
+      if (status != REG_VALID)
+	return status;
 
       /* The bsp points at the end of the register frame so we
 	 subtract the size of frame from it to get beginning of frame.  */
@@ -1043,8 +1063,12 @@ ia64_pseudo_register_read (struct gdbarc
       ULONGEST cfm;
       ULONGEST prN_val;
       CORE_ADDR reg;
-      regcache_cooked_read_unsigned (regcache, IA64_PR_REGNUM, &pr);
-      regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
+      status = regcache_cooked_read_unsigned (regcache, IA64_PR_REGNUM, &pr);
+      if (status != REG_VALID)
+	return status;
+      status = regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm);
+      if (status != REG_VALID)
+	return status;
 
       if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM)
 	{
@@ -1062,6 +1086,8 @@ ia64_pseudo_register_read (struct gdbarc
     }
   else
     memset (buf, 0, register_size (gdbarch, regnum));
+
+  return REG_VALID;
 }
 
 static void
@@ -1132,7 +1158,8 @@ ia64_pseudo_register_write (struct gdbar
 	     collection from the computed address.  */
 	  if (nat_addr >= bsp)
 	    {
-	      regcache_cooked_read_unsigned (regcache, IA64_RNAT_REGNUM,
+	      regcache_cooked_read_unsigned (regcache,
+					     IA64_RNAT_REGNUM,
 					     &nat_collection);
 	      if (natN_val)
 		nat_collection |= natN_mask;
Index: src/gdb/sh-tdep.c
===================================================================
--- src.orig/gdb/sh-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/sh-tdep.c	2011-02-21 21:09:45.489344004 +0000
@@ -2300,43 +2300,68 @@ dr_reg_base_num (struct gdbarch *gdbarch
   return fp_regnum;
 }
 
-static void
+/* Concatenate PORTIONS contiguous raw registers starting at
+   BASE_REGNUM into BUFFER.  */
+
+static enum register_status
+pseudo_register_read_portions (struct gdbarch *gdbarch,
+			       struct regcache *regcache,
+			       int portions,
+			       int base_regnum, gdb_byte *buffer)
+{
+  int portion;
+
+  for (portion = 0; portion < portions; portion++)
+    {
+      enum register_status status;
+      gdb_byte *b;
+
+      b = buffer + register_size (gdbarch, base_regnum) * portion;
+      status = regcache_raw_read (regcache, base_regnum + portion, b);
+      if (status != REG_VALID)
+	return status;
+    }
+
+  return REG_VALID;
+}
+
+static enum register_status
 sh_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			 int reg_nr, gdb_byte *buffer)
 {
-  int base_regnum, portion;
+  int base_regnum;
   char temp_buffer[MAX_REGISTER_SIZE];
+  enum register_status status;
 
   if (reg_nr == PSEUDO_BANK_REGNUM)
-    regcache_raw_read (regcache, BANK_REGNUM, buffer);
-  else
-  if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
+    return regcache_raw_read (regcache, BANK_REGNUM, buffer);
+  else if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
     {
       base_regnum = dr_reg_base_num (gdbarch, reg_nr);
 
       /* Build the value in the provided buffer.  */
       /* Read the real regs for which this one is an alias.  */
-      for (portion = 0; portion < 2; portion++)
-	regcache_raw_read (regcache, base_regnum + portion,
-			   (temp_buffer
-			    + register_size (gdbarch,
-					     base_regnum) * portion));
-      /* We must pay attention to the endiannes.  */
-      sh_register_convert_to_virtual (reg_nr,
-				      register_type (gdbarch, reg_nr),
-				      temp_buffer, buffer);
+      status = pseudo_register_read_portions (gdbarch, regcache,
+					      2, base_regnum, temp_buffer);
+      if (status == REG_VALID)
+	{
+	  /* We must pay attention to the endiannes. */
+	  sh_register_convert_to_virtual (reg_nr,
+					  register_type (gdbarch, reg_nr),
+					  temp_buffer, buffer);
+	}
+      return status;
     }
   else if (reg_nr >= FV0_REGNUM && reg_nr <= FV_LAST_REGNUM)
     {
       base_regnum = fv_reg_base_num (gdbarch, reg_nr);
 
       /* Read the real regs for which this one is an alias.  */
-      for (portion = 0; portion < 4; portion++)
-	regcache_raw_read (regcache, base_regnum + portion,
-			   ((char *) buffer
-			    + register_size (gdbarch,
-					     base_regnum) * portion));
+      return pseudo_register_read_portions (gdbarch, regcache,
+					    4, base_regnum, buffer);
     }
+  else
+    gdb_assert_not_reached ("invalid pseudo register number");
 }
 
 static void
Index: src/gdb/sparc-tdep.c
===================================================================
--- src.orig/gdb/sparc-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/sparc-tdep.c	2011-02-21 21:09:45.499344005 +0000
@@ -373,16 +373,20 @@ sparc32_register_type (struct gdbarch *g
   return builtin_type (gdbarch)->builtin_int32;
 }
 
-static void
+static enum register_status
 sparc32_pseudo_register_read (struct gdbarch *gdbarch,
 			      struct regcache *regcache,
 			      int regnum, gdb_byte *buf)
 {
+  enum register_status status;
+
   gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
 
   regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
-  regcache_raw_read (regcache, regnum, buf);
-  regcache_raw_read (regcache, regnum + 1, buf + 4);
+  status = regcache_raw_read (regcache, regnum, buf);
+  if (status == REG_VALID)
+    status = regcache_raw_read (regcache, regnum + 1, buf + 4);
+  return status;
 }
 
 static void
Index: src/gdb/sparc64-tdep.c
===================================================================
--- src.orig/gdb/sparc64-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/sparc64-tdep.c	2011-02-21 21:09:45.499344005 +0000
@@ -320,38 +320,52 @@ sparc64_register_type (struct gdbarch *g
   internal_error (__FILE__, __LINE__, _("invalid regnum"));
 }
 
-static void
+static enum register_status
 sparc64_pseudo_register_read (struct gdbarch *gdbarch,
 			      struct regcache *regcache,
 			      int regnum, gdb_byte *buf)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum register_status status;
+
   gdb_assert (regnum >= SPARC64_NUM_REGS);
 
   if (regnum >= SPARC64_D0_REGNUM && regnum <= SPARC64_D30_REGNUM)
     {
       regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC64_D0_REGNUM);
-      regcache_raw_read (regcache, regnum, buf);
-      regcache_raw_read (regcache, regnum + 1, buf + 4);
+      status = regcache_raw_read (regcache, regnum, buf);
+      if (status == REG_VALID)
+	status = regcache_raw_read (regcache, regnum + 1, buf + 4);
+      return status;
     }
   else if (regnum >= SPARC64_D32_REGNUM && regnum <= SPARC64_D62_REGNUM)
     {
       regnum = SPARC64_F32_REGNUM + (regnum - SPARC64_D32_REGNUM);
-      regcache_raw_read (regcache, regnum, buf);
+      return regcache_raw_read (regcache, regnum, buf);
     }
   else if (regnum >= SPARC64_Q0_REGNUM && regnum <= SPARC64_Q28_REGNUM)
     {
       regnum = SPARC_F0_REGNUM + 4 * (regnum - SPARC64_Q0_REGNUM);
-      regcache_raw_read (regcache, regnum, buf);
-      regcache_raw_read (regcache, regnum + 1, buf + 4);
-      regcache_raw_read (regcache, regnum + 2, buf + 8);
-      regcache_raw_read (regcache, regnum + 3, buf + 12);
+
+      status = regcache_raw_read (regcache, regnum, buf);
+      if (status == REG_VALID)
+	status = regcache_raw_read (regcache, regnum + 1, buf + 4);
+      if (status == REG_VALID)
+	status = regcache_raw_read (regcache, regnum + 2, buf + 8);
+      if (status == REG_VALID)
+	status = regcache_raw_read (regcache, regnum + 3, buf + 12);
+
+      return status;
     }
   else if (regnum >= SPARC64_Q32_REGNUM && regnum <= SPARC64_Q60_REGNUM)
     {
       regnum = SPARC64_F32_REGNUM + 2 * (regnum - SPARC64_Q32_REGNUM);
-      regcache_raw_read (regcache, regnum, buf);
-      regcache_raw_read (regcache, regnum + 1, buf + 8);
+
+      status = regcache_raw_read (regcache, regnum, buf);
+      if (status == REG_VALID)
+	status = regcache_raw_read (regcache, regnum + 1, buf + 8);
+
+      return status;
     }
   else if (regnum == SPARC64_CWP_REGNUM
 	   || regnum == SPARC64_PSTATE_REGNUM
@@ -360,7 +374,10 @@ sparc64_pseudo_register_read (struct gdb
     {
       ULONGEST state;
 
-      regcache_raw_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
+      status = regcache_raw_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
+      if (status != REG_VALID)
+	return status;
+
       switch (regnum)
 	{
 	case SPARC64_CWP_REGNUM:
@@ -378,6 +395,8 @@ sparc64_pseudo_register_read (struct gdb
 	}
       store_unsigned_integer (buf, 8, byte_order, state);
     }
+
+  return REG_VALID;
 }
 
 static void
Index: src/gdb/spu-tdep.c
===================================================================
--- src.orig/gdb/spu-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/spu-tdep.c	2011-02-21 21:09:45.499344005 +0000
@@ -183,61 +183,66 @@ spu_register_type (struct gdbarch *gdbar
 
 /* Pseudo registers for preferred slots - stack pointer.  */
 
-static void
+static enum register_status
 spu_pseudo_register_read_spu (struct regcache *regcache, const char *regname,
 			      gdb_byte *buf)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum register_status status;
   gdb_byte reg[32];
   char annex[32];
   ULONGEST id;
 
-  regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+  status = regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+  if (status != REG_VALID)
+    return status;
   xsnprintf (annex, sizeof annex, "%d/%s", (int) id, regname);
   memset (reg, 0, sizeof reg);
   target_read (&current_target, TARGET_OBJECT_SPU, annex,
 	       reg, 0, sizeof reg);
 
   store_unsigned_integer (buf, 4, byte_order, strtoulst (reg, NULL, 16));
+  return REG_VALID;
 }
 
-static void
+static enum register_status
 spu_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int regnum, gdb_byte *buf)
 {
   gdb_byte reg[16];
   char annex[32];
   ULONGEST id;
+  enum register_status status;
 
   switch (regnum)
     {
     case SPU_SP_REGNUM:
-      regcache_raw_read (regcache, SPU_RAW_SP_REGNUM, reg);
+      status = regcache_raw_read (regcache, SPU_RAW_SP_REGNUM, reg);
+      if (status != REG_VALID)
+	return status;
       memcpy (buf, reg, 4);
-      break;
+      return status;
 
     case SPU_FPSCR_REGNUM:
-      regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+      status = regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+      if (status != REG_VALID)
+	return status;
       xsnprintf (annex, sizeof annex, "%d/fpcr", (int) id);
       target_read (&current_target, TARGET_OBJECT_SPU, annex, buf, 0, 16);
-      break;
+      return status;
 
     case SPU_SRR0_REGNUM:
-      spu_pseudo_register_read_spu (regcache, "srr0", buf);
-      break;
+      return spu_pseudo_register_read_spu (regcache, "srr0", buf);
 
     case SPU_LSLR_REGNUM:
-      spu_pseudo_register_read_spu (regcache, "lslr", buf);
-      break;
+      return spu_pseudo_register_read_spu (regcache, "lslr", buf);
 
     case SPU_DECR_REGNUM:
-      spu_pseudo_register_read_spu (regcache, "decr", buf);
-      break;
+      return spu_pseudo_register_read_spu (regcache, "decr", buf);
 
     case SPU_DECR_STATUS_REGNUM:
-      spu_pseudo_register_read_spu (regcache, "decr_status", buf);
-      break;
+      return spu_pseudo_register_read_spu (regcache, "decr_status", buf);
 
     default:
       internal_error (__FILE__, __LINE__, _("invalid regnum"));
Index: src/gdb/xtensa-tdep.c
===================================================================
--- src.orig/gdb/xtensa-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/xtensa-tdep.c	2011-02-21 21:09:45.499344005 +0000
@@ -411,7 +411,7 @@ xtensa_register_write_masked (struct reg
 /* Read a tie state or mapped registers.  Read the masked areas
    of the registers and assemble them into a single value.  */
 
-static void
+static enum register_status
 xtensa_register_read_masked (struct regcache *regcache,
 			     xtensa_register_t *reg, gdb_byte *buffer)
 {
@@ -437,8 +437,12 @@ xtensa_register_read_masked (struct regc
       int r = mask->mask[i].reg_num;
       if (r >= 0)
 	{
+	  enum register_status status;
 	  ULONGEST val;
-	  regcache_cooked_read_unsigned (regcache, r, &val);
+
+	  status = regcache_cooked_read_unsigned (regcache, r, &val);
+	  if (status != REG_VALID)
+	    return status;
 	  regval = (unsigned int) val;
 	}
       else
@@ -493,12 +497,14 @@ xtensa_register_read_masked (struct regc
 	buffer[i] = mem & 0xff;
 	mem >>= 8;
       }
+
+  return REG_VALID;
 }
 
 
 /* Read pseudo registers.  */
 
-static void
+static enum register_status
 xtensa_pseudo_register_read (struct gdbarch *gdbarch,
 			     struct regcache *regcache,
 			     int regnum,
@@ -519,16 +525,20 @@ xtensa_pseudo_register_read (struct gdba
       && (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
     {
       gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
+      enum register_status status;
 
-      regcache_raw_read (regcache, gdbarch_tdep (gdbarch)->wb_regnum, buf);
+      status = regcache_raw_read (regcache,
+				  gdbarch_tdep (gdbarch)->wb_regnum,
+				  buf);
+      if (status != REG_VALID)
+	return status;
       regnum = arreg_number (gdbarch, regnum,
 			     extract_unsigned_integer (buf, 4, byte_order));
     }
 
   /* We can always read non-pseudo registers.  */
   if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
-    regcache_raw_read (regcache, regnum, buffer);
-
+    return regcache_raw_read (regcache, regnum, buffer);
 
   /* We have to find out how to deal with priveleged registers.
      Let's treat them as pseudo-registers, but we cannot read/write them.  */
@@ -539,6 +549,7 @@ xtensa_pseudo_register_read (struct gdba
       buffer[1] = (gdb_byte)0;
       buffer[2] = (gdb_byte)0;
       buffer[3] = (gdb_byte)0;
+      return REG_VALID;
     }
   /* Pseudo registers.  */
   else if (regnum >= 0
@@ -556,7 +567,7 @@ xtensa_pseudo_register_read (struct gdba
 	    {
 	      warning (_("cannot read register %s"),
 		       xtensa_register_name (gdbarch, regnum));
-	      return;
+	      return REG_VALID;
 	    }
 	}
 
@@ -567,26 +578,23 @@ xtensa_pseudo_register_read (struct gdba
 	  if (flags & xtTargetFlagsUseFetchStore)
 	    {
 	      warning (_("cannot read register"));
-	      return;
+	      return REG_VALID;
 	    }
 
 	  /* On some targets (esp. simulators), we can always read the reg.  */
 	  else if ((flags & xtTargetFlagsNonVisibleRegs) == 0)
 	    {
 	      warning (_("cannot read register"));
-	      return;
+	      return REG_VALID;
 	    }
 	}
 
       /* We can always read mapped registers.  */
       else if (type == xtRegisterTypeMapped || type == xtRegisterTypeTieState)
-        {
-	  xtensa_register_read_masked (regcache, reg, buffer);
-	  return;
-	}
+	return xtensa_register_read_masked (regcache, reg, buffer);
 
       /* Assume that we can read the register.  */
-      regcache_raw_read (regcache, regnum, buffer);
+      return regcache_raw_read (regcache, regnum, buffer);
     }
   else
     internal_error (__FILE__, __LINE__,
Index: src/gdb/bfin-tdep.c
===================================================================
--- src.orig/gdb/bfin-tdep.c	2011-02-21 20:30:32.149344005 +0000
+++ src/gdb/bfin-tdep.c	2011-02-21 21:09:45.499344005 +0000
@@ -687,20 +687,25 @@ bfin_register_name (struct gdbarch *gdba
   return bfin_register_name_strings[i];
 }
 
-static void
+static enum register_status
 bfin_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int regnum, gdb_byte *buffer)
 {
   gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
+  enum register_status status;
 
   if (regnum != BFIN_CC_REGNUM)
     internal_error (__FILE__, __LINE__,
 		    _("invalid register number %d"), regnum);
 
   /* Extract the CC bit from the ASTAT register.  */
-  regcache_raw_read (regcache, BFIN_ASTAT_REGNUM, buf);
-  buffer[1] = buffer[2] = buffer[3] = 0;
-  buffer[0] = !!(buf[0] & ASTAT_CC);
+  status = regcache_raw_read (regcache, BFIN_ASTAT_REGNUM, buf);
+  if (status == REG_VALID)
+    {
+      buffer[1] = buffer[2] = buffer[3] = 0;
+      buffer[0] = !!(buf[0] & ASTAT_CC);
+    }
+  return status;
 }
 
 static void
@@ -708,15 +713,19 @@ bfin_pseudo_register_write (struct gdbar
 			    int regnum, const gdb_byte *buffer)
 {
   gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
+  enum register_status status;
 
   if (regnum != BFIN_CC_REGNUM)
     internal_error (__FILE__, __LINE__,
 		    _("invalid register number %d"), regnum);
 
   /* Overlay the CC bit in the ASTAT register.  */
-  regcache_raw_read (regcache, BFIN_ASTAT_REGNUM, buf);
-  buf[0] = (buf[0] & ~ASTAT_CC) | ((buffer[0] & 1) << ASTAT_CC_POS);
-  regcache_raw_write (regcache, BFIN_ASTAT_REGNUM, buf);
+  status = regcache_raw_read (regcache, BFIN_ASTAT_REGNUM, buf);
+  if (status == REG_VALID)
+    {
+      buf[0] = (buf[0] & ~ASTAT_CC) | ((buffer[0] & 1) << ASTAT_CC_POS);
+      regcache_raw_write (regcache, BFIN_ASTAT_REGNUM, buf);
+    }
 }
 
 static CORE_ADDR


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

* Re: [unavailable regs/locals, 01/11] registers status upwards
  2011-02-22 13:28 [unavailable regs/locals, 01/11] registers status upwards Pedro Alves
@ 2011-02-28 15:53 ` Jan Kratochvil
  2011-03-16  1:40   ` Pedro Alves
  0 siblings, 1 reply; 8+ messages in thread
From: Jan Kratochvil @ 2011-02-28 15:53 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Tue, 22 Feb 2011 14:27:50 +0100, Pedro Alves wrote:
> Make the regcache_XXX_read_XXX functions return an indication
> of whether the register's value is valid, so that the
> frame module can mark frame registers as unavailable.

The basic question on my mind is why instead of REG_UNAVAILABLE it does not
throw NOT_AVAILABLE_ERROR?

And if not NOT_AVAILABLE_ERROR then there should be
__attribute__((warn_unused_result)) as if the caller is operating with
not-available value - it is the case this patchset exactly tries to fix.
In fact all the memsets (, 0, ) could be rather changed to debug-stub 0x55.

Just __attribute__((warn_unused_result)) errors on too many cases which
suggests more for the NOT_AVAILABLE_ERROR throw.

The mail:
	graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
is sure better but without this last mail it it printed:
(gdb) bt
#0  f () at 1.c:11
#1  0x0000000000000000 in ?? ()

and while I did not try I believe one could still find some case(s) where GDB
will print 0.

Currently even if one catches all the cases it is still fragile for future
changes as the developers are not well aware of the `availability'.


Thanks,
Jan


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

* Re: [unavailable regs/locals, 01/11] registers status upwards
  2011-02-28 15:53 ` Jan Kratochvil
@ 2011-03-16  1:40   ` Pedro Alves
  2011-03-17 16:31     ` Jan Kratochvil
  0 siblings, 1 reply; 8+ messages in thread
From: Pedro Alves @ 2011-03-16  1:40 UTC (permalink / raw)
  To: gdb-patches; +Cc: Jan Kratochvil

Finally getting back to this.

On Monday 28 February 2011 15:53:25, Jan Kratochvil wrote:
> On Tue, 22 Feb 2011 14:27:50 +0100, Pedro Alves wrote:
> > Make the regcache_XXX_read_XXX functions return an indication
> > of whether the register's value is valid, so that the
> > frame module can mark frame registers as unavailable.
> 
> The basic question on my mind is why instead of REG_UNAVAILABLE it does not
> throw NOT_AVAILABLE_ERROR?

There are other non-valid statuses.  Then, from the patch:

-/* NOTE: cagney/2002-08-13: At present GDB has no reliable mechanism
-   for indicating when a ``cooked'' register was constructed from
-   invalid or unavailable ``raw'' registers.  One fairly easy way of
-   adding such a mechanism would be for the cooked functions to return
-   a register valid indication.  Given the possibility of such a
-   change, the extract functions below use a reference parameter,
-   rather than a function result.  */

I agree that throwing versions may be something good to have.
But if we do have them, I think they should be alternative
variants, not replacements, and they should look something like:

extern LONGEST regcache_cooked_get_signed (struct regcache *regcache,
                                          int regnum);

rather than:

extern enum register_status
  regcache_cooked_read_signed (struct regcache *regcache,
                              int regnum, LONGEST *val);

or the current:

extern void
  regcache_cooked_read_signed (struct regcache *regcache,
                              int regnum, LONGEST *val);

That is, make the return be the register value.  The frame
code has similar throw and non-throw variants.

> And if not NOT_AVAILABLE_ERROR then there should be
> __attribute__((warn_unused_result)) as if the caller is operating with
> not-available value - it is the case this patchset exactly tries to fix.

The thing is there are many many callers that only read register
values in the context of an inferior with execution.  E.g., stuff around infcalls, and extracting return values, and _writting_ registers (stuff that
needs to read-combine-write).  For those (and it's really a big a bunch
of those), I do agree that trying to work with such an unavailable
value might as well throw, because there's nothing else the
callers can do other than letting the error propagate up until the CLI.
But OTOH, there's no pressing need to change those.

> In fact all the memsets (, 0, ) could be rather changed to debug-stub 0x55.

Agreed, but I think it'd be better if we _don't_ do that _yet_.  Users are
quite used to seeing 0's and recognizing that as "bogus".  I think that if
we do that, we do it after branching.  Not even touching the contents is
a bit better during development, since then valgrind tells us when we touch
such invalid buffer contents.  That helped me a bit while developing all
this <unavailable> stuff.

> 
> Just __attribute__((warn_unused_result)) errors on too many cases which
> suggests more for the NOT_AVAILABLE_ERROR throw.

IMO it makes sense for the low level register cache read functions to have
non-throwing variants, to let the caller decide to throw or not.  Making the
low level functions themselves throw makes the code that _needs_ to care about
the register status be quite awkward by needing to wrap in TRY_CATCH.  The
REG_UNAVAILABLE error is more for the case when you want the
error to cross several layers  up (e.g., register -> frame | value -> expression -> CLI).  In those cases, it would be from awkward to 
impossible-to-do-sanely to propagate an "unavailable" error all the way
through error returns.

This patch (and the series), is only concerned with the _reading_ 
side of the story, and making that work gracefuly.  And on that
side I think it makes sense to use non-throwing variants, when
directly manipulating a regcache.

So while I agree that warn_unused_result is an interesting idea,
I think to get there we'd need the throwing register read
routine variants mentioned above first, and to go through the
hundreds of regcache_XX_read_XXX instances, replacing those that
should throw, with a call to the throwing variant.

> The mail:
> 	graceful unwind termination when we'd need unavailable/uncollect memory or registers to unwind further
> is sure better but without this last mail it it printed:
> (gdb) bt
> #0  f () at 1.c:11
> #1  0x0000000000000000 in ?? ()

That was is because "frame_unwind_register" currently swallows
errors.  As you've discovered, only the "graceful unwind termination"
fixes that.  It has this:

Index: src/gdb/frame.c
===================================================================
--- src.orig/gdb/frame.c        2011-03-15 23:52:19.000000000 +0000
+++ src/gdb/frame.c     2011-03-15 23:53:09.418353559 +0000
@@ -912,6 +912,12 @@ frame_unwind_register (struct frame_info
 
   frame_register_unwind (frame, regnum, &optimized, &unavailable,
                         &lval, &addr, &realnum, buf);
+
+  if (optimized)
+    error (_("Register %d was optimized out"), regnum);
+  if (unavailable)
+    throw_error (NOT_AVAILABLE_ERROR,
+                _("Register %d is not available"), regnum);
 }

The problem is that I can't bring in that hunk into this
series without the rest of the "graceful unwind termination" patch,
otherwise, the user will get this:

(gdb) bt
#0  args_test_func (argc=<unavailable>, argi=<unavailable>, argf=<unavailable>, argd=<unavailable>, argstruct=..., argarray=<unavailable>)
    at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:199
#1  0x0000000000400d0b in main (argc=1, argv=0x7fff16571178, envp=0x7fff16571188) at ../../../src/gdb/testsuite/gdb.trace/unavailable.cc:364
PC not available

The "PC not available" note is an error thrown.  With MI, one
would get this:

(gdb) interpreter-exec mi "-stack-list-frames"
^error,msg="PC not available"

Instead of:

(gdb) interpreter-exec mi "-stack-list-frames"
^done,stack=[frame={level="0",addr="0x00000000004007ba",func="args_test_func",file="../../../src/gdb/testsuite/gdb.trace/unavailable.cc",fullname="/home/pedro/gdb/tdd_upstream/src/gdb/testsuite/gdb.trace/unavailable.cc",line="199"},frame={level="1",addr="0x0000000000400d0b",func="main",file="../../../src/gdb/testsuite/gdb.trace/unavailable.cc",fullname="/home/pedro/gdb/tdd_upstream/src/gdb/testsuite/gdb.trace/unavailable.cc",line="364"},frame={level="2",addr="0x0000000000000000",func="??"}]

... which would be a serious regression.

> and while I did not try I believe one could still find some case(s) where GDB
> will print 0.

I dare you find some (on x86-linux)  :-)

Does that answer your questions?

-- 
Pedro Alves


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

* Re: [unavailable regs/locals, 01/11] registers status upwards
  2011-03-16  1:40   ` Pedro Alves
@ 2011-03-17 16:31     ` Jan Kratochvil
  2011-03-17 16:48       ` Pedro Alves
  2011-03-28 21:17       ` Tom Tromey
  0 siblings, 2 replies; 8+ messages in thread
From: Jan Kratochvil @ 2011-03-17 16:31 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Wed, 16 Mar 2011 01:12:50 +0100, Pedro Alves wrote:
> I agree that throwing versions may be something good to have.
> But if we do have them, I think they should be alternative
> variants, not replacements,

The goal is to make any current code safe by default (that it throws an
exception), if one forgets to fix/modify/review it.  Another possibility is to
make it a compilation error by default (warn_unused_result) unless it is
either manually reviewed as safe (and marked by some (void) expr;) or changed
to be safe etc.  But there should be no invalid user data (=value 0) when the
developer forgets to review some part of code.


> > and while I did not try I believe one could still find some case(s) where GDB
> > will print 0.
> 
> I dare you find some (on x86-linux)  :-)

That is not the point whether you have or have not forgotten for such case
this time.  You can be sure at least any 3rd party patches (and all the
distros out there incl. CodeSourcery have some patches) can/will become
silently violating the <unavailable> rules.


> Not even touching the contents is a bit better during development, since
> then valgrind tells us when we touch such invalid buffer contents.

OK, true.


> > Just __attribute__((warn_unused_result)) errors on too many cases which
> > suggests more for the NOT_AVAILABLE_ERROR throw.
> 
> IMO it makes sense for the low level register cache read functions to have
> non-throwing variants, to let the caller decide to throw or not.  Making the
> low level functions themselves throw makes the code that _needs_ to care about
> the register status be quite awkward by needing to wrap in TRY_CATCH.

Yes, for callers who want to deal with it there should be some way to report
it without the GDB exceptions magic.

My point is by default it should behave safely (throw exception or
a compilation error).  How to code properly some alternative variants when one
is already modifying the caller code should be obvious.


> This patch (and the series), is only concerned with the _reading_ 
> side of the story, and making that work gracefuly.  And on that
> side I think it makes sense to use non-throwing variants, when
> directly manipulating a regcache.

In such case these functions should be `warn_unused_result' and they should be
renamed from the original functions.  The original function names should throw
an exception (for the case of infcall etc.) - if any <unavailable> code should
be handled directly by the callers the original function names can even
internal_error on <unavailable> values.


> --- src.orig/gdb/frame.c        2011-03-15 23:52:19.000000000 +0000
> +++ src/gdb/frame.c     2011-03-15 23:53:09.418353559 +0000
> @@ -912,6 +912,12 @@ frame_unwind_register (struct frame_info
>  
>    frame_register_unwind (frame, regnum, &optimized, &unavailable,
>                          &lval, &addr, &realnum, buf);
> +
> +  if (optimized)
> +    error (_("Register %d was optimized out"), regnum);
> +  if (unavailable)
> +    throw_error (NOT_AVAILABLE_ERROR,
> +                _("Register %d is not available"), regnum);
>  }

This shows how fragile the code it is.  If you forget a new error-checking
code invalid values silently leak into the upper layers.


> Does that answer your questions?

I wanted to express general disagreement with this style expecting preciseness
and no mistakes by the developers, which is not considered to be a "safe
enterprise development style".


Thanks,
Jan


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

* Re: [unavailable regs/locals, 01/11] registers status upwards
  2011-03-17 16:31     ` Jan Kratochvil
@ 2011-03-17 16:48       ` Pedro Alves
  2011-03-17 17:25         ` Jan Kratochvil
  2011-03-28 21:17       ` Tom Tromey
  1 sibling, 1 reply; 8+ messages in thread
From: Pedro Alves @ 2011-03-17 16:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Jan Kratochvil

On Thursday 17 March 2011 15:06:28, Jan Kratochvil wrote:
> Yes, for callers who want to deal with it there should be some way to report
> it without the GDB exceptions magic.

The key point is that the interface/prototype of the current functions has been
designed from the start to return a status indication instead of throwing.
The non-valid status of registers is _not_ new.  A nicer throwing variant
interface would return the register's value, instead of void.  That
interface/prototype would make it obvious to the reader that since there's
no way to return an error indication by return value, then it must throw.

> I wanted to express general disagreement with this style expecting preciseness
> and no mistakes by the developers, which is not considered to be a "safe
> enterprise development style".

Another key point, is that not putting a TRY_CATCH were it would matter
is fragile as well.  The whole operation is cancelled.  It makes the whole
user experience _worse_.  Seing 0s is worse than <unavailable> at places,
but it's much better than not seeing _anything_ at all.  E.g, the MI
command I showed upthread.

How about proceeding as is, and I'll revisit later if necessary?
This is just _one_ detail in the whole story afterall.

-- 
Pedro Alves


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

* Re: [unavailable regs/locals, 01/11] registers status upwards
  2011-03-17 16:48       ` Pedro Alves
@ 2011-03-17 17:25         ` Jan Kratochvil
  2011-03-17 19:15           ` Pedro Alves
  0 siblings, 1 reply; 8+ messages in thread
From: Jan Kratochvil @ 2011-03-17 17:25 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Thu, 17 Mar 2011 17:21:48 +0100, Pedro Alves wrote:
> Another key point, is that not putting a TRY_CATCH were it would matter
> is fragile as well.  The whole operation is cancelled.  It makes the whole
> user experience _worse_.  Seing 0s is worse than <unavailable> at places,
> but it's much better than not seeing _anything_ at all.  E.g, the MI
> command I showed upthread.

Here is probably the major disagreement.  People bugreport when they see error
while they give up when the program does weird things they cannot understand.


> How about proceeding as is, and I'll revisit later if necessary?
> This is just _one_ detail in the whole story afterall.

I do not want to block anything.  But in such case a review does not make
sense as it is easier to put there compiler and/or exception checks than to
verify each statement by humans.


Thanks,
Jan


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

* Re: [unavailable regs/locals, 01/11] registers status upwards
  2011-03-17 17:25         ` Jan Kratochvil
@ 2011-03-17 19:15           ` Pedro Alves
  0 siblings, 0 replies; 8+ messages in thread
From: Pedro Alves @ 2011-03-17 19:15 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Thursday 17 March 2011 16:31:26, Jan Kratochvil wrote:
> On Thu, 17 Mar 2011 17:21:48 +0100, Pedro Alves wrote:
> > How about proceeding as is, and I'll revisit later if necessary?
> > This is just _one_ detail in the whole story afterall.
> 
> I do not want to block anything.  But in such case a review does not make
> sense as it is easier to put there compiler and/or exception checks than to
> verify each statement by humans.

Okay, thanks.  I do respect and understand your point.  I mainly
disagree that the existing functions are the ones that should throw.
I'll try to see about adding throwing variants (and using them where
it makes sense) after the series is in.

Not sure if anyone's wanting to further review the rest
of the series, and/or the "graceful unwind termination" patch.
I guess if I don't hear back, I'll apply the whole shebang tomorrow.

-- 
Pedro Alves


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

* Re: [unavailable regs/locals, 01/11] registers status upwards
  2011-03-17 16:31     ` Jan Kratochvil
  2011-03-17 16:48       ` Pedro Alves
@ 2011-03-28 21:17       ` Tom Tromey
  1 sibling, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2011-03-28 21:17 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: Pedro Alves, gdb-patches

I read this thread today.  A bit late, I know, but since it impacts
post-7.3 work (I hope :-) I would like to bring it up.

Jan> In such case these functions should be `warn_unused_result' and
Jan> they should be renamed from the original functions.  The original
Jan> function names should throw an exception (for the case of infcall
Jan> etc.) - if any <unavailable> code should be handled directly by the
Jan> callers the original function names can even internal_error on
Jan> <unavailable> values.

If I read correctly, we're all in agreement about this as a long term
goal.

Jan> I wanted to express general disagreement with this style expecting
Jan> preciseness and no mistakes by the developers, which is not
Jan> considered to be a "safe enterprise development style".

I think we generally agree about this too.


My understanding is that the code in 7.3 is at least as robust as
gdb-before-the-series-was-applied.  That is, the changes were, if not
"fail-safe", at least "fail-compatibly".

Pedro, are you planning to implement the API changes post-7.3?
If not, could you file a bug report about it?

Tom


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

end of thread, other threads:[~2011-03-28 20:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-22 13:28 [unavailable regs/locals, 01/11] registers status upwards Pedro Alves
2011-02-28 15:53 ` Jan Kratochvil
2011-03-16  1:40   ` Pedro Alves
2011-03-17 16:31     ` Jan Kratochvil
2011-03-17 16:48       ` Pedro Alves
2011-03-17 17:25         ` Jan Kratochvil
2011-03-17 19:15           ` Pedro Alves
2011-03-28 21:17       ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox