* 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>
|
||||
|
||||
* 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 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;
|
||||
}
|
||||
|
|
78
gdb/frame.c
78
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
|
||||
|
|
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,
|
||||
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
|
||||
|
|
84
gdb/valops.c
84
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;
|
||||
{
|
||||
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
|
||||
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));
|
||||
|
||||
/* 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);
|
||||
|
||||
{
|
||||
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 (¤t_target);
|
||||
|
|
Loading…
Add table
Reference in a new issue