* 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.
This commit is contained in:
parent
42037fe5bb
commit
00fa51f680
5 changed files with 146 additions and 147 deletions
|
@ -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>
|
2007-01-08 Jim Blandy <jimb@codesourcery.com>
|
||||||
|
|
||||||
* MAINTAINERS: Update Stan Shebs' email address.
|
* MAINTAINERS: Update Stan Shebs' email address.
|
||||||
|
|
108
gdb/findvar.c
108
gdb/findvar.c
|
@ -599,11 +599,7 @@ addresses have not been bound by the dynamic loader. Try again when executable i
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a value of type TYPE, stored in register REGNUM, in frame
|
/* Return a value of type TYPE, stored in register REGNUM, in frame FRAME. */
|
||||||
FRAME.
|
|
||||||
|
|
||||||
NOTE: returns NULL if register value is not available.
|
|
||||||
Caller will check return value or die! */
|
|
||||||
|
|
||||||
struct value *
|
struct value *
|
||||||
value_from_register (struct type *type, int regnum, struct frame_info *frame)
|
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);
|
struct value *v = allocate_value (type);
|
||||||
CHECK_TYPEDEF (type);
|
CHECK_TYPEDEF (type);
|
||||||
|
|
||||||
if (TYPE_LENGTH (type) == 0)
|
VALUE_LVAL (v) = lval_register;
|
||||||
{
|
VALUE_FRAME_ID (v) = get_frame_id (frame);
|
||||||
/* It doesn't matter much what we return for this: since the
|
VALUE_REGNUM (v) = regnum;
|
||||||
length is zero, it could be anything. But if allowed to see
|
|
||||||
a zero-length type, the register-finding loop below will set
|
if (CONVERT_REGISTER_P (regnum, type))
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
/* The ISA/ABI need to something weird when obtaining the
|
/* The ISA/ABI need to something weird when obtaining the
|
||||||
specified value from this register. It might need to
|
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
|
is that REGISTER_TO_VALUE populates the entire value
|
||||||
including the location. */
|
including the location. */
|
||||||
REGISTER_TO_VALUE (frame, regnum, type, value_contents_raw (v));
|
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
|
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 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
|
/* Any structure stored in more than one register will always be
|
||||||
an integral number of registers. Otherwise, you need to do
|
an integral number of registers. Otherwise, you need to do
|
||||||
some fiddling with the last register copied here for little
|
some fiddling with the last register copied here for little
|
||||||
endian machines. */
|
endian machines. */
|
||||||
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
|
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. */
|
/* 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
|
else
|
||||||
set_value_offset (v, 0);
|
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;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
78
gdb/frame.c
78
gdb/frame.c
|
@ -742,6 +742,84 @@ frame_register_read (struct frame_info *frame, int regnum,
|
||||||
return !optimized;
|
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
|
/* Map between a frame register number and its name. A frame register
|
||||||
space is a superset of the cooked register space --- it also
|
space is a superset of the cooked register space --- it also
|
||||||
|
|
12
gdb/frame.h
12
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,
|
extern void put_frame_register (struct frame_info *frame, int regnum,
|
||||||
const gdb_byte *buf);
|
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
|
/* Map between a frame register number and its name. A frame register
|
||||||
space is a superset of the cooked register space --- it also
|
space is a superset of the cooked register space --- it also
|
||||||
includes builtin registers. If NAMELEN is negative, use the NAME's
|
includes builtin registers. If NAMELEN is negative, use the NAME's
|
||||||
|
|
84
gdb/valops.c
84
gdb/valops.c
|
@ -651,8 +651,7 @@ value_assign (struct value *toval, struct value *fromval)
|
||||||
if (!frame)
|
if (!frame)
|
||||||
error (_("Value being assigned to is no longer active."));
|
error (_("Value being assigned to is no longer active."));
|
||||||
|
|
||||||
if (VALUE_LVAL (toval) == lval_register
|
if (CONVERT_REGISTER_P (VALUE_REGNUM (toval), type))
|
||||||
&& CONVERT_REGISTER_P (VALUE_REGNUM (toval), type))
|
|
||||||
{
|
{
|
||||||
/* If TOVAL is a special machine register requiring
|
/* If TOVAL is a special machine register requiring
|
||||||
conversion of program values to a special raw format. */
|
conversion of program values to a special raw format. */
|
||||||
|
@ -661,59 +660,40 @@ value_assign (struct value *toval, struct value *fromval)
|
||||||
}
|
}
|
||||||
else
|
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))
|
if (value_bitsize (toval))
|
||||||
amount_to_copy = byte_offset + 1;
|
{
|
||||||
|
int changed_len;
|
||||||
|
gdb_byte buffer[sizeof (LONGEST)];
|
||||||
|
|
||||||
|
changed_len = (value_bitpos (toval)
|
||||||
|
+ value_bitsize (toval)
|
||||||
|
+ HOST_CHAR_BIT - 1)
|
||||||
|
/ HOST_CHAR_BIT;
|
||||||
|
|
||||||
|
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
|
else
|
||||||
amount_to_copy = byte_offset + TYPE_LENGTH (type);
|
{
|
||||||
|
put_frame_register_bytes (frame, value_reg,
|
||||||
/* And a bounce buffer. Be slightly over generous. */
|
value_offset (toval),
|
||||||
buffer = alloca (amount_to_copy + MAX_REGISTER_SIZE);
|
TYPE_LENGTH (type),
|
||||||
|
value_contents (fromval));
|
||||||
/* 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));
|
|
||||||
|
|
||||||
/* 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 (deprecated_register_changed_hook)
|
if (deprecated_register_changed_hook)
|
||||||
deprecated_register_changed_hook (-1);
|
deprecated_register_changed_hook (-1);
|
||||||
observer_notify_target_changed (¤t_target);
|
observer_notify_target_changed (¤t_target);
|
||||||
|
|
Loading…
Add table
Reference in a new issue