summaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorPedro Alves <pedro@codesourcery.com>2011-03-18 18:42:40 +0000
committerPedro Alves <pedro@codesourcery.com>2011-03-18 18:42:40 +0000
commit4a8a3091dd993a919822dc434546f8959d16a22c (patch)
tree87f11fa757b7c6b7b937896aa7799ae03ec7c323 /gdb
parentef749a8958424d7fde1db60719cdc6425831f9de (diff)
downloadgdb-4a8a3091dd993a919822dc434546f8959d16a22c.tar.gz
gdb/
* dwarf2loc.c (read_pieced_value): Handle get_frame_register_bytes returning that the register piece is unavailable/optimized out. (write_pieced_value): Handle get_frame_register_bytes returning that the register piece is unavailable/optimized out when doing a read-modify write of a bitfield. * findvar.c (value_from_register): Handle get_frame_register_bytes returning that the register piece is unavailable/optimized out. * frame.c (get_frame_register_bytes): New parameters `optimizedp' and `unavailablep'. Throw error on bad debug info. Use frame_register instead of frame_register_read, to fill in the new arguments. * frame.h (get_frame_register_bytes): New parameters `optimizedp' and `unavailablep'. * valops.c: (value_assign): Adjust, and handle get_frame_register_bytes failing. * spu-tdep.c: Include exceptions.h. (spu_software_single_step): Adjust, and handle get_frame_register_bytes failing. (spu_get_longjmp_target): Ditto. * gdbarch.sh (register_to_value): Change to return int. New parameters `optimizedp' and `unavailablep'. * gdbarch.h, gdbarch.c: Regenerate. * i386-tdep.c (i386_register_to_value): Adjust to new gdbarch_register_to_value interface. * i387-tdep.c (i387_register_to_value): Ditto. * i387-tdep.h (i387_register_to_value): Ditto. * alpha-tdep.c (alpha_register_to_value): Ditto. * ia64-tdep.c (ia64_register_to_value): Ditto. * m68k-tdep.c (m68k_register_to_value): Ditto. * mips-tdep.c (mips_register_to_value): Ditto. * rs6000-tdep.c (rs6000_register_to_value): Ditto.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/alpha-tdep.c25
-rw-r--r--gdb/dwarf2loc.c34
-rw-r--r--gdb/findvar.c19
-rw-r--r--gdb/frame.c27
-rw-r--r--gdb/frame.h7
-rw-r--r--gdb/gdbarch.c6
-rw-r--r--gdb/gdbarch.h4
-rwxr-xr-xgdb/gdbarch.sh2
-rw-r--r--gdb/i386-tdep.c23
-rw-r--r--gdb/i387-tdep.c15
-rw-r--r--gdb/i387-tdep.h5
-rw-r--r--gdb/ia64-tdep.c15
-rw-r--r--gdb/m68k-tdep.c17
-rw-r--r--gdb/mips-tdep.c28
-rw-r--r--gdb/rs6000-tdep.c13
-rw-r--r--gdb/spu-tdep.c25
-rw-r--r--gdb/testsuite/ChangeLog34
-rw-r--r--gdb/valops.c12
18 files changed, 240 insertions, 71 deletions
diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c
index cc49a07cefd..2f309a7c998 100644
--- a/gdb/alpha-tdep.c
+++ b/gdb/alpha-tdep.c
@@ -239,21 +239,28 @@ alpha_convert_register_p (struct gdbarch *gdbarch, int regno,
&& TYPE_LENGTH (type) != 8);
}
-static void
+static int
alpha_register_to_value (struct frame_info *frame, int regnum,
- struct type *valtype, gdb_byte *out)
+ struct type *valtype, gdb_byte *out,
+ int *optimizedp, int *unavailablep)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte in[MAX_REGISTER_SIZE];
- frame_register_read (frame, regnum, in);
- switch (TYPE_LENGTH (valtype))
+ /* Convert to TYPE. */
+ if (!get_frame_register_bytes (frame, regnum, 0,
+ register_size (gdbarch, regnum),
+ in, optimizedp, unavailablep))
+ return 0;
+
+ if (TYPE_LENGTH (valtype) == 4)
{
- case 4:
- alpha_sts (get_frame_arch (frame), out, in);
- break;
- default:
- error (_("Cannot retrieve value from floating point register"));
+ alpha_sts (gdbarch, out, in);
+ *optimizedp = *unavailablep = 0;
+ return 1;
}
+
+ error (_("Cannot retrieve value from floating point register"));
}
static void
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index f90ee71a2b9..285081e472f 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -591,8 +591,20 @@ read_pieced_value (struct value *v)
if (gdb_regnum != -1)
{
- get_frame_register_bytes (frame, gdb_regnum, reg_offset,
- this_size, buffer);
+ int optim, unavail;
+
+ if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset,
+ this_size, buffer,
+ &optim, &unavail))
+ {
+ /* Just so garbage doesn't ever shine through. */
+ memset (buffer, 0, this_size);
+
+ if (optim)
+ set_value_optimized_out (v, 1);
+ if (unavail)
+ mark_value_bytes_unavailable (v, offset, this_size);
+ }
}
else
{
@@ -776,8 +788,22 @@ write_pieced_value (struct value *to, struct value *from)
{
if (need_bitwise)
{
- get_frame_register_bytes (frame, gdb_regnum, reg_offset,
- this_size, buffer);
+ int optim, unavail;
+
+ if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset,
+ this_size, buffer,
+ &optim, &unavail))
+ {
+ if (optim)
+ error (_("Can't do read-modify-write to "
+ "update bitfield; containing word has been "
+ "optimized out"));
+ if (unavail)
+ throw_error (NOT_AVAILABLE_ERROR,
+ _("Can't do read-modify-write to update "
+ "bitfield; containing word "
+ "is unavailable"));
+ }
copy_bitwise (buffer, dest_offset_bits,
contents, source_offset_bits,
this_size_bits,
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 809a99e8a72..2b361efeda3 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -628,6 +628,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
struct gdbarch *gdbarch = get_frame_arch (frame);
struct type *type1 = check_typedef (type);
struct value *v;
+ int optim, unavail, ok;
if (gdbarch_convert_register_p (gdbarch, regnum, type1))
{
@@ -642,8 +643,9 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
VALUE_LVAL (v) = lval_register;
VALUE_FRAME_ID (v) = get_frame_id (frame);
VALUE_REGNUM (v) = regnum;
- gdbarch_register_to_value (gdbarch,
- frame, regnum, type1, value_contents_raw (v));
+ ok = gdbarch_register_to_value (gdbarch, frame, regnum, type1,
+ value_contents_raw (v), &optim,
+ &unavail);
}
else
{
@@ -653,10 +655,19 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
v = gdbarch_value_from_register (gdbarch, type, regnum, frame);
/* Get the data. */
- if (!get_frame_register_bytes (frame, regnum, value_offset (v), len,
- value_contents_raw (v)))
+ ok = get_frame_register_bytes (frame, regnum, value_offset (v), len,
+ value_contents_raw (v),
+ &optim, &unavail);
+ }
+
+ if (!ok)
+ {
+ if (optim)
set_value_optimized_out (v, 1);
+ if (unavail)
+ mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
}
+
return v;
}
diff --git a/gdb/frame.c b/gdb/frame.c
index 42380eb550e..5bd1b03966a 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -1001,7 +1001,8 @@ frame_register_read (struct frame_info *frame, int regnum,
int
get_frame_register_bytes (struct frame_info *frame, int regnum,
- CORE_ADDR offset, int len, gdb_byte *myaddr)
+ CORE_ADDR offset, int len, gdb_byte *myaddr,
+ int *optimizedp, int *unavailablep)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
int i;
@@ -1028,11 +1029,8 @@ get_frame_register_bytes (struct frame_info *frame, int regnum,
maxsize += thissize;
}
if (len > maxsize)
- {
- warning (_("Bad debug information detected: "
- "Attempt to read %d bytes from registers."), len);
- return 0;
- }
+ error (_("Bad debug information detected: "
+ "Attempt to read %d bytes from registers."), len);
/* Copy the data. */
while (len > 0)
@@ -1044,14 +1042,25 @@ get_frame_register_bytes (struct frame_info *frame, int regnum,
if (curr_len == register_size (gdbarch, regnum))
{
- if (!frame_register_read (frame, regnum, myaddr))
+ enum lval_type lval;
+ CORE_ADDR addr;
+ int realnum;
+
+ frame_register (frame, regnum, optimizedp, unavailablep,
+ &lval, &addr, &realnum, myaddr);
+ if (*optimizedp || *unavailablep)
return 0;
}
else
{
gdb_byte buf[MAX_REGISTER_SIZE];
+ enum lval_type lval;
+ CORE_ADDR addr;
+ int realnum;
- if (!frame_register_read (frame, regnum, buf))
+ frame_register (frame, regnum, optimizedp, unavailablep,
+ &lval, &addr, &realnum, buf);
+ if (*optimizedp || *unavailablep)
return 0;
memcpy (myaddr, buf + offset, curr_len);
}
@@ -1062,6 +1071,8 @@ get_frame_register_bytes (struct frame_info *frame, int regnum,
regnum++;
}
+ *optimizedp = 0;
+ *unavailablep = 0;
return 1;
}
diff --git a/gdb/frame.h b/gdb/frame.h
index 605528cff26..e7053a8e7f5 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -520,10 +520,13 @@ extern void put_frame_register (struct frame_info *frame, int regnum,
const gdb_byte *buf);
/* Read LEN bytes from one or multiple registers starting with REGNUM
- in frame FRAME, starting at OFFSET, into BUF. */
+ in frame FRAME, starting at OFFSET, into BUF. If the register
+ contents are optimized out or unavailable, set *OPTIMIZEDP,
+ *UNAVAILABLEP accordingly. */
extern int get_frame_register_bytes (struct frame_info *frame, int regnum,
CORE_ADDR offset, int len,
- gdb_byte *myaddr);
+ gdb_byte *myaddr,
+ int *optimizedp, int *unavailablep);
/* Write LEN bytes to one or multiple registers starting with REGNUM
in frame FRAME, starting at OFFSET, into BUF. */
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 8b97f20413a..7f983067a7c 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -2262,14 +2262,14 @@ set_gdbarch_convert_register_p (struct gdbarch *gdbarch,
gdbarch->convert_register_p = convert_register_p;
}
-void
-gdbarch_register_to_value (struct gdbarch *gdbarch, struct frame_info *frame, int regnum, struct type *type, gdb_byte *buf)
+int
+gdbarch_register_to_value (struct gdbarch *gdbarch, struct frame_info *frame, int regnum, struct type *type, gdb_byte *buf, int *optimizedp, int *unavailablep)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->register_to_value != NULL);
if (gdbarch_debug >= 2)
fprintf_unfiltered (gdb_stdlog, "gdbarch_register_to_value called\n");
- gdbarch->register_to_value (frame, regnum, type, buf);
+ return gdbarch->register_to_value (frame, regnum, type, buf, optimizedp, unavailablep);
}
void
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 7284f76e92c..50221d782b4 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -384,8 +384,8 @@ typedef int (gdbarch_convert_register_p_ftype) (struct gdbarch *gdbarch, int reg
extern int gdbarch_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type);
extern void set_gdbarch_convert_register_p (struct gdbarch *gdbarch, gdbarch_convert_register_p_ftype *convert_register_p);
-typedef void (gdbarch_register_to_value_ftype) (struct frame_info *frame, int regnum, struct type *type, gdb_byte *buf);
-extern void gdbarch_register_to_value (struct gdbarch *gdbarch, struct frame_info *frame, int regnum, struct type *type, gdb_byte *buf);
+typedef int (gdbarch_register_to_value_ftype) (struct frame_info *frame, int regnum, struct type *type, gdb_byte *buf, int *optimizedp, int *unavailablep);
+extern int gdbarch_register_to_value (struct gdbarch *gdbarch, struct frame_info *frame, int regnum, struct type *type, gdb_byte *buf, int *optimizedp, int *unavailablep);
extern void set_gdbarch_register_to_value (struct gdbarch *gdbarch, gdbarch_register_to_value_ftype *register_to_value);
typedef void (gdbarch_value_to_register_ftype) (struct frame_info *frame, int regnum, struct type *type, const gdb_byte *buf);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 2f987ae1150..3112f4465cf 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -484,7 +484,7 @@ F:int:get_longjmp_target:struct frame_info *frame, CORE_ADDR *pc:frame, pc
v:int:believe_pcc_promotion:::::::
#
m:int:convert_register_p:int regnum, struct type *type:regnum, type:0:generic_convert_register_p::0
-f:void:register_to_value:struct frame_info *frame, int regnum, struct type *type, gdb_byte *buf:frame, regnum, type, buf:0
+f:int:register_to_value:struct frame_info *frame, int regnum, struct type *type, gdb_byte *buf, int *optimizedp, int *unavailablep:frame, regnum, type, buf, optimizedp, unavailablep:0
f:void:value_to_register:struct frame_info *frame, int regnum, struct type *type, const gdb_byte *buf:frame, regnum, type, buf:0
# Construct a value representing the contents of register REGNUM in
# frame FRAME, interpreted as type TYPE. The routine needs to
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 6330ceb7d2f..62df6141ece 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -2746,21 +2746,17 @@ i386_convert_register_p (struct gdbarch *gdbarch,
/* Read a value of type TYPE from register REGNUM in frame FRAME, and
return its contents in TO. */
-static void
+static int
i386_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, gdb_byte *to)
+ struct type *type, gdb_byte *to,
+ int *optimizedp, int *unavailablep)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
int len = TYPE_LENGTH (type);
- /* FIXME: kettenis/20030609: What should we do if REGNUM isn't
- available in FRAME (i.e. if it wasn't saved)? */
-
if (i386_fp_regnum_p (gdbarch, regnum))
- {
- i387_register_to_value (frame, regnum, type, to);
- return;
- }
+ return i387_register_to_value (frame, regnum, type, to,
+ optimizedp, unavailablep);
/* Read a value spread across multiple registers. */
@@ -2771,11 +2767,18 @@ i386_register_to_value (struct frame_info *frame, int regnum,
gdb_assert (regnum != -1);
gdb_assert (register_size (gdbarch, regnum) == 4);
- get_frame_register (frame, regnum, to);
+ if (!get_frame_register_bytes (frame, regnum, 0,
+ register_size (gdbarch, regnum),
+ to, optimizedp, unavailablep))
+ return 0;
+
regnum = i386_next_regnum (regnum);
len -= 4;
to += 4;
}
+
+ *optimizedp = *unavailablep = 0;
+ return 1;
}
/* Write the contents FROM of a value of type TYPE into register
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index 122bd83a397..9eece418b2c 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -307,9 +307,10 @@ i387_convert_register_p (struct gdbarch *gdbarch, int regnum,
/* Read a value of type TYPE from register REGNUM in frame FRAME, and
return its contents in TO. */
-void
+int
i387_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, gdb_byte *to)
+ struct type *type, gdb_byte *to,
+ int *optimizedp, int *unavailablep)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte from[I386_MAX_REGISTER_SIZE];
@@ -321,12 +322,18 @@ i387_register_to_value (struct frame_info *frame, int regnum,
{
warning (_("Cannot convert floating-point register value "
"to non-floating-point type."));
- return;
+ *optimizedp = *unavailablep = 0;
+ return 0;
}
/* Convert to TYPE. */
- get_frame_register (frame, regnum, from);
+ if (!get_frame_register_bytes (frame, regnum, 0, TYPE_LENGTH (type),
+ from, optimizedp, unavailablep))
+ return 0;
+
convert_typed_floating (from, i387_ext_type (gdbarch), to, type);
+ *optimizedp = *unavailablep = 0;
+ return 1;
}
/* Write the contents FROM of a value of type TYPE into register
diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h
index bd592ba7722..b87654900dd 100644
--- a/gdb/i387-tdep.h
+++ b/gdb/i387-tdep.h
@@ -66,8 +66,9 @@ extern int i387_convert_register_p (struct gdbarch *gdbarch, int regnum,
/* Read a value of type TYPE from register REGNUM in frame FRAME, and
return its contents in TO. */
-extern void i387_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, gdb_byte *to);
+extern int i387_register_to_value (struct frame_info *frame, int regnum,
+ struct type *type, gdb_byte *to,
+ int *optimizedp, int *unavailablep);
/* Write the contents FROM of a value of type TYPE into register
REGNUM in frame FRAME. */
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index cbd8514acc5..363800dbf29 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -1223,14 +1223,23 @@ ia64_convert_register_p (struct gdbarch *gdbarch, int regno, struct type *type)
&& type != ia64_ext_type (gdbarch));
}
-static void
+static int
ia64_register_to_value (struct frame_info *frame, int regnum,
- struct type *valtype, gdb_byte *out)
+ struct type *valtype, gdb_byte *out,
+ int *optimizedp, int *unavailablep)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
char in[MAX_REGISTER_SIZE];
- frame_register_read (frame, regnum, in);
+
+ /* Convert to TYPE. */
+ if (!get_frame_register_bytes (frame, regnum, 0,
+ register_size (gdbarch, regnum),
+ in, optimizedp, unavailablep))
+ return 0;
+
convert_typed_floating (in, ia64_ext_type (gdbarch), out, valtype);
+ *optimizedp = *unavailablep = 0;
+ return 1;
}
static void
diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c
index 082cb84ff80..2706969dac5 100644
--- a/gdb/m68k-tdep.c
+++ b/gdb/m68k-tdep.c
@@ -203,9 +203,10 @@ m68k_convert_register_p (struct gdbarch *gdbarch,
/* Read a value of type TYPE from register REGNUM in frame FRAME, and
return its contents in TO. */
-static void
+static int
m68k_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, gdb_byte *to)
+ struct type *type, gdb_byte *to,
+ int *optimizedp, int *unavailablep)
{
gdb_byte from[M68K_MAX_REGISTER_SIZE];
struct type *fpreg_type = register_type (get_frame_arch (frame),
@@ -216,12 +217,20 @@ m68k_register_to_value (struct frame_info *frame, int regnum,
{
warning (_("Cannot convert floating-point register value "
"to non-floating-point type."));
- return;
+ *optimizedp = *unavailablep = 0;
+ return 0;
}
/* Convert to TYPE. */
- get_frame_register (frame, regnum, from);
+
+ /* Convert to TYPE. */
+ if (!get_frame_register_bytes (frame, regnum, 0, TYPE_LENGTH (type),
+ from, optimizedp, unavailablep))
+ return 0;
+
convert_typed_floating (from, fpreg_type, to, type);
+ *optimizedp = *unavailablep = 0;
+ return 1;
}
/* Write the contents FROM of a value of type TYPE into register
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 04ce30a29ba..e5aed94c578 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -737,9 +737,10 @@ mips_convert_register_p (struct gdbarch *gdbarch,
|| mips_convert_register_gpreg_case_p (gdbarch, regnum, type);
}
-static void
+static int
mips_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, gdb_byte *to)
+ struct type *type, gdb_byte *to,
+ int *optimizedp, int *unavailablep)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
@@ -747,14 +748,29 @@ mips_register_to_value (struct frame_info *frame, int regnum,
{
get_frame_register (frame, regnum + 0, to + 4);
get_frame_register (frame, regnum + 1, to + 0);
+
+ if (!get_frame_register_bytes (frame, regnum + 0, 0, 4, to + 4,
+ optimizedp, unavailablep))
+ return 0;
+
+ if (!get_frame_register_bytes (frame, regnum + 1, 0, 4, to + 0,
+ optimizedp, unavailablep))
+ return 0;
+ *optimizedp = *unavailablep = 0;
+ return 1;
}
else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
{
int len = TYPE_LENGTH (type);
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- get_frame_register_bytes (frame, regnum, 8 - len, len, to);
- else
- get_frame_register_bytes (frame, regnum, 0, len, to);
+ CORE_ADDR offset;
+
+ offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 - len : 0;
+ if (!get_frame_register_bytes (frame, regnum, offset, len, to,
+ optimizedp, unavailablep))
+ return 0;
+
+ *optimizedp = *unavailablep = 0;
+ return 1;
}
else
{
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index b8c87fb8b82..23fe9e336fe 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -2504,20 +2504,27 @@ rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
!= TYPE_LENGTH (builtin_type (gdbarch)->builtin_double));
}
-static void
+static int
rs6000_register_to_value (struct frame_info *frame,
int regnum,
struct type *type,
- gdb_byte *to)
+ gdb_byte *to,
+ int *optimizedp, int *unavailablep)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte from[MAX_REGISTER_SIZE];
gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
- get_frame_register (frame, regnum, from);
+ if (!get_frame_register_bytes (frame, regnum, 0,
+ register_size (gdbarch, regnum),
+ from, optimizedp, unavailablep))
+ return 0;
+
convert_typed_floating (from, builtin_type (gdbarch)->builtin_double,
to, type);
+ *optimizedp = *unavailablep = 0;
+ return 1;
}
static void
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index 7f0cd7d3dbb..da7024a0b39 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -45,7 +45,7 @@
#include "observer.h"
#include "infcall.h"
#include "dwarf2.h"
-
+#include "exceptions.h"
#include "spu-tdep.h"
@@ -1594,8 +1594,21 @@ spu_software_single_step (struct frame_info *frame)
target += SPUADDR_ADDR (pc);
else if (reg != -1)
{
- get_frame_register_bytes (frame, reg, 0, 4, buf);
- target += extract_unsigned_integer (buf, 4, byte_order) & -4;
+ int optim, unavail;
+
+ if (get_frame_register_bytes (frame, reg, 0, 4, buf,
+ &optim, &unavail))
+ target += extract_unsigned_integer (buf, 4, byte_order) & -4;
+ else
+ {
+ if (optim)
+ error (_("Could not determine address of "
+ "single-step breakpoint."));
+ if (unavail)
+ throw_error (NOT_AVAILABLE_ERROR,
+ _("Could not determine address of "
+ "single-step breakpoint."));
+ }
}
target = target & lslr;
@@ -1618,9 +1631,13 @@ spu_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[4];
CORE_ADDR jb_addr;
+ int optim, unavail;
/* Jump buffer is pointed to by the argument register $r3. */
- get_frame_register_bytes (frame, SPU_ARG1_REGNUM, 0, 4, buf);
+ if (!get_frame_register_bytes (frame, SPU_ARG1_REGNUM, 0, 4, buf,
+ &optim, &unavail))
+ return 0;
+
jb_addr = extract_unsigned_integer (buf, 4, byte_order);
if (target_read_memory (SPUADDR (tdep->id, jb_addr), buf, 4))
return 0;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 77bad9fb738..5984d2dfdde 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,39 @@
2011-03-18 Pedro Alves <pedro@codesourcery.com>
+ * dwarf2loc.c (read_pieced_value): Handle get_frame_register_bytes
+ returning that the register piece is unavailable/optimized out.
+ (write_pieced_value): Handle get_frame_register_bytes returning
+ that the register piece is unavailable/optimized out when doing a
+ read-modify write of a bitfield.
+ * findvar.c (value_from_register): Handle get_frame_register_bytes
+ returning that the register piece is unavailable/optimized out.
+ * frame.c (get_frame_register_bytes): New parameters `optimizedp'
+ and `unavailablep'. Throw error on bad debug info. Use
+ frame_register instead of frame_register_read, to fill in the new
+ arguments.
+ * frame.h (get_frame_register_bytes): New parameters `optimizedp'
+ and `unavailablep'.
+ * valops.c: (value_assign): Adjust, and handle
+ get_frame_register_bytes failing.
+ * spu-tdep.c: Include exceptions.h.
+ (spu_software_single_step): Adjust, and handle
+ get_frame_register_bytes failing.
+ (spu_get_longjmp_target): Ditto.
+ * gdbarch.sh (register_to_value): Change to return int. New
+ parameters `optimizedp' and `unavailablep'.
+ * gdbarch.h, gdbarch.c: Regenerate.
+ * i386-tdep.c (i386_register_to_value): Adjust to new
+ gdbarch_register_to_value interface.
+ * i387-tdep.c (i387_register_to_value): Ditto.
+ * i387-tdep.h (i387_register_to_value): Ditto.
+ * alpha-tdep.c (alpha_register_to_value): Ditto.
+ * ia64-tdep.c (ia64_register_to_value): Ditto.
+ * m68k-tdep.c (m68k_register_to_value): Ditto.
+ * mips-tdep.c (mips_register_to_value): Ditto.
+ * rs6000-tdep.c (rs6000_register_to_value): Ditto.
+
+2011-03-18 Pedro Alves <pedro@codesourcery.com>
+
* gdb.trace/unavailable.exp (fpreg, spreg, pcreg): Define.
(test_register, test_register_unavailable): New procedures.
(gdb_unavailable_registers_test): New procedure.
diff --git a/gdb/valops.c b/gdb/valops.c
index 0c07e5ce9ec..b9f55081a1d 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -1343,8 +1343,16 @@ value_assign (struct value *toval, struct value *fromval)
"don't fit in a %d bit word."),
(int) sizeof (LONGEST) * HOST_CHAR_BIT);
- get_frame_register_bytes (frame, value_reg, offset,
- changed_len, buffer);
+ if (!get_frame_register_bytes (frame, value_reg, offset,
+ changed_len, buffer,
+ &optim, &unavail))
+ {
+ if (optim)
+ error (_("value has been optimized out"));
+ if (unavail)
+ throw_error (NOT_AVAILABLE_ERROR,
+ _("value is not available"));
+ }
modify_field (type, buffer, value_as_long (fromval),
value_bitpos (toval), value_bitsize (toval));