summaryrefslogtreecommitdiff
path: root/gdb/regcache.c
diff options
context:
space:
mode:
authorPedro Alves <pedro@codesourcery.com>2011-03-18 18:38:38 +0000
committerPedro Alves <pedro@codesourcery.com>2011-03-18 18:38:38 +0000
commit734db55da420a9ad1b8d73595f572c2daae04a6c (patch)
tree6b2ef4050eb249c9cd5ebc982e540dff6c964cc1 /gdb/regcache.c
parent9597e4d79bb5a4d999dc100cda756ac2e8e7cb54 (diff)
downloadgdb-734db55da420a9ad1b8d73595f572c2daae04a6c.tar.gz
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: Include exceptions.h (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. (regcache_read_pc): Throw NOT_AVAILABLE_ERROR if the register is unavailable. (regcache_dump): Handle unavailable cooked registers. * 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.
Diffstat (limited to 'gdb/regcache.c')
-rw-r--r--gdb/regcache.c183
1 files changed, 116 insertions, 67 deletions
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 286f1d125da..b984bc1400b 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -29,6 +29,7 @@
#include "gdb_string.h"
#include "gdbcmd.h" /* For maintenanceprintlist. */
#include "observer.h"
+#include "exceptions.h"
/*
* DATA STRUCTURE
@@ -312,14 +313,19 @@ regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read,
{
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 +358,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 +577,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 +606,53 @@ regcache_raw_read (struct regcache *regcache, int regnum, gdb_byte *buf)
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 +682,71 @@ regcache_raw_write_unsigned (struct regcache *regcache, int regnum,
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 +832,12 @@ typedef void (regcache_read_ftype) (struct regcache *regcache, int regnum,
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 +848,18 @@ regcache_xfer_part (struct regcache *regcache, int regnum,
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 +872,19 @@ regcache_xfer_part (struct regcache *regcache, int regnum,
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 +898,15 @@ regcache_raw_write_part (struct regcache *regcache, int regnum,
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
@@ -943,9 +983,11 @@ regcache_read_pc (struct regcache *regcache)
{
ULONGEST raw_val;
- regcache_cooked_read_unsigned (regcache,
- gdbarch_pc_regnum (gdbarch),
- &raw_val);
+ if (regcache_cooked_read_unsigned (regcache,
+ gdbarch_pc_regnum (gdbarch),
+ &raw_val) == REG_UNAVAILABLE)
+ throw_error (NOT_AVAILABLE_ERROR, _("PC register is not available"));
+
pc_val = gdbarch_addr_bits_remove (gdbarch, raw_val);
}
else
@@ -1164,13 +1206,20 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
fprintf_unfiltered (file, "Cooked value");
else
{
- /* FIXME: no way for cooked reads to signal unavailable
- yet. */
- regcache_cooked_read (regcache, regnum, buf);
- fprintf_unfiltered (file, "0x");
- dump_endian_bytes (file,
- gdbarch_byte_order (gdbarch), buf,
- regcache->descr->sizeof_register[regnum]);
+ enum register_status status;
+
+ status = regcache_cooked_read (regcache, regnum, buf);
+ if (status == REG_UNKNOWN)
+ fprintf_unfiltered (file, "<invalid>");
+ else if (status == REG_UNAVAILABLE)
+ fprintf_unfiltered (file, "<unavailable>");
+ else
+ {
+ fprintf_unfiltered (file, "0x");
+ dump_endian_bytes (file,
+ gdbarch_byte_order (gdbarch), buf,
+ regcache->descr->sizeof_register[regnum]);
+ }
}
}