aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2007-01-08 17:34:12 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2007-01-08 17:34:12 +0000
commit00fa51f6801ada6b33763db75f5cdab6c74ea90b (patch)
tree5655c58c8bee2c41ad8d0a09542f3c3d05a38886
parent42037fe5bbb1bc401de372fca49768eeef2c21dc (diff)
downloadgdb-00fa51f6801ada6b33763db75f5cdab6c74ea90b.zip
gdb-00fa51f6801ada6b33763db75f5cdab6c74ea90b.tar.gz
gdb-00fa51f6801ada6b33763db75f5cdab6c74ea90b.tar.bz2
* frame.c (get_frame_register_bytes): New function.
(put_frame_register_bytes): Likewise. * frame.h (get_frame_register_bytes): Declare. (put_frame_register_bytes): Likewise. * findvar.c (value_from_register): Always construct lval_register values. Use get_frame_register_bytes. * valops.c (value_assign): Use get_frame_register_bytes and put_frame_register_bytes.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/findvar.c110
-rw-r--r--gdb/frame.c78
-rw-r--r--gdb/frame.h12
-rw-r--r--gdb/valops.c82
5 files changed, 146 insertions, 147 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2d21861..1203a63 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2007-01-08 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * frame.c (get_frame_register_bytes): New function.
+ (put_frame_register_bytes): Likewise.
+ * frame.h (get_frame_register_bytes): Declare.
+ (put_frame_register_bytes): Likewise.
+ * findvar.c (value_from_register): Always construct lval_register
+ values. Use get_frame_register_bytes.
+ * valops.c (value_assign): Use get_frame_register_bytes and
+ put_frame_register_bytes.
+
2007-01-08 Jim Blandy <jimb@codesourcery.com>
* MAINTAINERS: Update Stan Shebs' email address.
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 9edd151..51fa408 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -599,11 +599,7 @@ addresses have not been bound by the dynamic loader. Try again when executable i
return v;
}
-/* Return a value of type TYPE, stored in register REGNUM, in frame
- FRAME.
-
- NOTE: returns NULL if register value is not available.
- Caller will check return value or die! */
+/* Return a value of type TYPE, stored in register REGNUM, in frame FRAME. */
struct value *
value_from_register (struct type *type, int regnum, struct frame_info *frame)
@@ -612,30 +608,11 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
struct value *v = allocate_value (type);
CHECK_TYPEDEF (type);
- if (TYPE_LENGTH (type) == 0)
- {
- /* It doesn't matter much what we return for this: since the
- length is zero, it could be anything. But if allowed to see
- a zero-length type, the register-finding loop below will set
- neither mem_stor nor reg_stor, and then report an internal
- error.
-
- Zero-length types can legitimately arise from declarations
- like 'struct {}' (a GCC extension, not valid ISO C). GDB may
- also create them when it finds bogus debugging information;
- for example, in GCC 2.95.4 and binutils 2.11.93.0.2, the
- STABS BINCL->EXCL compression process can create bad type
- numbers. GDB reads these as TYPE_CODE_UNDEF types, with zero
- length. (That bug is actually the only known way to get a
- zero-length value allocated to a register --- which is what
- it takes to make it here.)
-
- We'll just attribute the value to the original register. */
- VALUE_LVAL (v) = lval_register;
- VALUE_ADDRESS (v) = regnum;
- VALUE_REGNUM (v) = regnum;
- }
- else if (CONVERT_REGISTER_P (regnum, type))
+ VALUE_LVAL (v) = lval_register;
+ VALUE_FRAME_ID (v) = get_frame_id (frame);
+ VALUE_REGNUM (v) = regnum;
+
+ if (CONVERT_REGISTER_P (regnum, type))
{
/* The ISA/ABI need to something weird when obtaining the
specified value from this register. It might need to
@@ -645,85 +622,26 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
is that REGISTER_TO_VALUE populates the entire value
including the location. */
REGISTER_TO_VALUE (frame, regnum, type, value_contents_raw (v));
- VALUE_LVAL (v) = lval_register;
- VALUE_FRAME_ID (v) = get_frame_id (frame);
- VALUE_REGNUM (v) = regnum;
}
else
{
- int local_regnum;
- int mem_stor = 0, reg_stor = 0;
- int mem_tracking = 1;
- CORE_ADDR last_addr = 0;
- CORE_ADDR first_addr = 0;
- int first_realnum = regnum;
int len = TYPE_LENGTH (type);
- int value_bytes_copied;
- int optimized = 0;
- gdb_byte *value_bytes = alloca (len + MAX_REGISTER_SIZE);
-
- /* Copy all of the data out, whereever it may be. */
- for (local_regnum = regnum, value_bytes_copied = 0;
- value_bytes_copied < len;
- (value_bytes_copied += register_size (current_gdbarch, local_regnum),
- ++local_regnum))
- {
- int realnum;
- int optim;
- enum lval_type lval;
- CORE_ADDR addr;
- frame_register (frame, local_regnum, &optim, &lval, &addr,
- &realnum, value_bytes + value_bytes_copied);
- optimized += optim;
- if (register_cached (local_regnum) == -1)
- return NULL; /* register value not available */
-
- if (regnum == local_regnum)
- {
- first_addr = addr;
- first_realnum = realnum;
- }
- if (lval == lval_register)
- reg_stor++;
- else
- {
- mem_stor++;
-
- /* FIXME: cagney/2004-11-12: I think this is trying to
- check that the stored registers are adjacent in
- memory. It isn't doing a good job? */
- mem_tracking = (mem_tracking
- && (regnum == local_regnum
- || addr == last_addr));
- }
- last_addr = addr;
- }
-
- if (mem_tracking && mem_stor && !reg_stor)
- {
- VALUE_LVAL (v) = lval_memory;
- VALUE_ADDRESS (v) = first_addr;
- }
- else
- {
- VALUE_LVAL (v) = lval_register;
- VALUE_FRAME_ID (v) = get_frame_id (frame);
- VALUE_REGNUM (v) = regnum;
- }
-
- set_value_optimized_out (v, optimized);
-
+
/* Any structure stored in more than one register will always be
an integral number of registers. Otherwise, you need to do
some fiddling with the last register copied here for little
endian machines. */
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
- && len < register_size (current_gdbarch, regnum))
+ && len < register_size (gdbarch, regnum))
/* Big-endian, and we want less than full size. */
- set_value_offset (v, register_size (current_gdbarch, regnum) - len);
+ set_value_offset (v, register_size (gdbarch, regnum) - len);
else
set_value_offset (v, 0);
- memcpy (value_contents_raw (v), value_bytes + value_offset (v), len);
+
+ /* Get the data. */
+ if (!get_frame_register_bytes (frame, regnum, value_offset (v), len,
+ value_contents_raw (v)))
+ set_value_optimized_out (v, 1);
}
return v;
}
diff --git a/gdb/frame.c b/gdb/frame.c
index f1b28f7..fcd8fdd 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -742,6 +742,84 @@ frame_register_read (struct frame_info *frame, int regnum,
return !optimized;
}
+int
+get_frame_register_bytes (struct frame_info *frame, int regnum,
+ CORE_ADDR offset, int len, gdb_byte *myaddr)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+
+ /* Skip registers wholly inside of OFFSET. */
+ while (offset >= register_size (gdbarch, regnum))
+ {
+ offset -= register_size (gdbarch, regnum);
+ regnum++;
+ }
+
+ /* Copy the data. */
+ while (len > 0)
+ {
+ int curr_len = register_size (gdbarch, regnum) - offset;
+ if (curr_len > len)
+ curr_len = len;
+
+ if (curr_len == register_size (gdbarch, regnum))
+ {
+ if (!frame_register_read (frame, regnum, myaddr))
+ return 0;
+ }
+ else
+ {
+ gdb_byte buf[MAX_REGISTER_SIZE];
+ if (!frame_register_read (frame, regnum, buf))
+ return 0;
+ memcpy (myaddr, buf + offset, curr_len);
+ }
+
+ len -= curr_len;
+ offset = 0;
+ regnum++;
+ }
+
+ return 1;
+}
+
+void
+put_frame_register_bytes (struct frame_info *frame, int regnum,
+ CORE_ADDR offset, int len, const gdb_byte *myaddr)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+
+ /* Skip registers wholly inside of OFFSET. */
+ while (offset >= register_size (gdbarch, regnum))
+ {
+ offset -= register_size (gdbarch, regnum);
+ regnum++;
+ }
+
+ /* Copy the data. */
+ while (len > 0)
+ {
+ int curr_len = register_size (gdbarch, regnum) - offset;
+ if (curr_len > len)
+ curr_len = len;
+
+ if (curr_len == register_size (gdbarch, regnum))
+ {
+ put_frame_register (frame, regnum, myaddr);
+ }
+ else
+ {
+ gdb_byte buf[MAX_REGISTER_SIZE];
+ frame_register_read (frame, regnum, buf);
+ memcpy (buf + offset, myaddr, curr_len);
+ put_frame_register (frame, regnum, buf);
+ }
+
+ len -= curr_len;
+ offset = 0;
+ regnum++;
+ }
+}
/* Map between a frame register number and its name. A frame register
space is a superset of the cooked register space --- it also
diff --git a/gdb/frame.h b/gdb/frame.h
index 5843a25..a0b41a5 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -491,6 +491,18 @@ extern void frame_register (struct frame_info *frame, int regnum,
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. */
+extern int get_frame_register_bytes (struct frame_info *frame, int regnum,
+ CORE_ADDR offset, int len,
+ gdb_byte *myaddr);
+
+/* Write LEN bytes to one or multiple registers starting with REGNUM
+ in frame FRAME, starting at OFFSET, into BUF. */
+extern void put_frame_register_bytes (struct frame_info *frame, int regnum,
+ CORE_ADDR offset, int len,
+ const gdb_byte *myaddr);
+
/* Map between a frame register number and its name. A frame register
space is a superset of the cooked register space --- it also
includes builtin registers. If NAMELEN is negative, use the NAME's
diff --git a/gdb/valops.c b/gdb/valops.c
index b6a0ad7..19c80c9 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -651,8 +651,7 @@ value_assign (struct value *toval, struct value *fromval)
if (!frame)
error (_("Value being assigned to is no longer active."));
- if (VALUE_LVAL (toval) == lval_register
- && CONVERT_REGISTER_P (VALUE_REGNUM (toval), type))
+ if (CONVERT_REGISTER_P (VALUE_REGNUM (toval), type))
{
/* If TOVAL is a special machine register requiring
conversion of program values to a special raw format. */
@@ -661,59 +660,40 @@ value_assign (struct value *toval, struct value *fromval)
}
else
{
- /* TOVAL is stored in a series of registers in the frame
- specified by the structure. Copy that value out,
- modify it, and copy it back in. */
- int amount_copied;
- int amount_to_copy;
- gdb_byte *buffer;
- int reg_offset;
- int byte_offset;
- int regno;
-
- /* Locate the first register that falls in the value that
- needs to be transfered. Compute the offset of the
- value in that register. */
- {
- int offset;
- for (reg_offset = value_reg, offset = 0;
- offset + register_size (current_gdbarch, reg_offset) <= value_offset (toval);
- reg_offset++);
- byte_offset = value_offset (toval) - offset;
- }
-
- /* Compute the number of register aligned values that need
- to be copied. */
- if (value_bitsize (toval))
- amount_to_copy = byte_offset + 1;
- else
- amount_to_copy = byte_offset + TYPE_LENGTH (type);
-
- /* And a bounce buffer. Be slightly over generous. */
- buffer = alloca (amount_to_copy + MAX_REGISTER_SIZE);
-
- /* Copy it in. */
- for (regno = reg_offset, amount_copied = 0;
- amount_copied < amount_to_copy;
- amount_copied += register_size (current_gdbarch, regno), regno++)
- frame_register_read (frame, regno, buffer + amount_copied);
-
- /* Modify what needs to be modified. */
if (value_bitsize (toval))
- modify_field (buffer + byte_offset,
- value_as_long (fromval),
- value_bitpos (toval), value_bitsize (toval));
- else
- memcpy (buffer + byte_offset, value_contents (fromval),
- TYPE_LENGTH (type));
+ {
+ int changed_len;
+ gdb_byte buffer[sizeof (LONGEST)];
+
+ changed_len = (value_bitpos (toval)
+ + value_bitsize (toval)
+ + HOST_CHAR_BIT - 1)
+ / HOST_CHAR_BIT;
- /* Copy it out. */
- for (regno = reg_offset, amount_copied = 0;
- amount_copied < amount_to_copy;
- amount_copied += register_size (current_gdbarch, regno), regno++)
- put_frame_register (frame, regno, buffer + amount_copied);
+ if (changed_len > (int) sizeof (LONGEST))
+ error (_("Can't handle bitfields which don't fit in a %d bit word."),
+ (int) sizeof (LONGEST) * HOST_CHAR_BIT);
+ get_frame_register_bytes (frame, value_reg,
+ value_offset (toval),
+ changed_len, buffer);
+
+ modify_field (buffer, value_as_long (fromval),
+ value_bitpos (toval), value_bitsize (toval));
+
+ put_frame_register_bytes (frame, value_reg,
+ value_offset (toval),
+ changed_len, buffer);
+ }
+ else
+ {
+ put_frame_register_bytes (frame, value_reg,
+ value_offset (toval),
+ TYPE_LENGTH (type),
+ value_contents (fromval));
+ }
}
+
if (deprecated_register_changed_hook)
deprecated_register_changed_hook (-1);
observer_notify_target_changed (&current_target);