read/write_pieced_value: Merge into one function

Since read_pieced_value and write_pieced_value share significant logic,
this patch merges them into a single function rw_pieced_value.

gdb/ChangeLog:

	* dwarf2loc.c (rw_pieced_value): New.  Merge logic from...
	(read_pieced_value, write_pieced_value): ...here.  Reduce to
	wrappers that just call rw_pieced_value.
This commit is contained in:
Andreas Arnez 2017-06-13 15:20:32 +02:00
parent f65e204425
commit 55acdf2242
2 changed files with 207 additions and 205 deletions

View File

@ -1,3 +1,9 @@
2017-06-13 Andreas Arnez <arnez@linux.vnet.ibm.com>
* dwarf2loc.c (rw_pieced_value): New. Merge logic from...
(read_pieced_value, write_pieced_value): ...here. Reduce to
wrappers that just call rw_pieced_value.
2017-06-13 Andreas Arnez <arnez@linux.vnet.ibm.com> 2017-06-13 Andreas Arnez <arnez@linux.vnet.ibm.com>
* dwarf2loc.c (write_pieced_value): When writing the data for a * dwarf2loc.c (write_pieced_value): When writing the data for a

View File

@ -1761,30 +1761,54 @@ bits_to_bytes (ULONGEST start, ULONGEST n_bits)
return (start % 8 + n_bits + 7) / 8; return (start % 8 + n_bits + 7) / 8;
} }
/* Read or write a pieced value V. If FROM != NULL, operate in "write
mode": copy FROM into the pieces comprising V. If FROM == NULL,
operate in "read mode": fetch the contents of the (lazy) value V by
composing it from its pieces. */
static void static void
read_pieced_value (struct value *v) rw_pieced_value (struct value *v, struct value *from)
{ {
int i; int i;
LONGEST offset = 0, max_offset; LONGEST offset = 0, max_offset;
ULONGEST bits_to_skip; ULONGEST bits_to_skip;
gdb_byte *contents; gdb_byte *v_contents;
const gdb_byte *from_contents;
struct piece_closure *c struct piece_closure *c
= (struct piece_closure *) value_computed_closure (v); = (struct piece_closure *) value_computed_closure (v);
std::vector<gdb_byte> buffer; std::vector<gdb_byte> buffer;
int bits_big_endian int bits_big_endian
= gdbarch_bits_big_endian (get_type_arch (value_type (v))); = gdbarch_bits_big_endian (get_type_arch (value_type (v)));
if (from != NULL)
{
from_contents = value_contents (from);
v_contents = NULL;
}
else
{
if (value_type (v) != value_enclosing_type (v)) if (value_type (v) != value_enclosing_type (v))
internal_error (__FILE__, __LINE__, internal_error (__FILE__, __LINE__,
_("Should not be able to create a lazy value with " _("Should not be able to create a lazy value with "
"an enclosing type")); "an enclosing type"));
v_contents = value_contents_raw (v);
from_contents = NULL;
}
contents = value_contents_raw (v);
bits_to_skip = 8 * value_offset (v); bits_to_skip = 8 * value_offset (v);
if (value_bitsize (v)) if (value_bitsize (v))
{ {
bits_to_skip += (8 * value_offset (value_parent (v)) bits_to_skip += (8 * value_offset (value_parent (v))
+ value_bitpos (v)); + value_bitpos (v));
if (from != NULL
&& (gdbarch_byte_order (get_type_arch (value_type (from)))
== BFD_ENDIAN_BIG))
{
/* Use the least significant bits of FROM. */
max_offset = 8 * TYPE_LENGTH (value_type (from));
offset = max_offset - value_bitsize (v);
}
else
max_offset = value_bitsize (v); max_offset = value_bitsize (v);
} }
else else
@ -1794,165 +1818,6 @@ read_pieced_value (struct value *v)
for (i = 0; i < c->n_pieces && bits_to_skip >= c->pieces[i].size; i++) for (i = 0; i < c->n_pieces && bits_to_skip >= c->pieces[i].size; i++)
bits_to_skip -= c->pieces[i].size; bits_to_skip -= c->pieces[i].size;
for (; i < c->n_pieces && offset < max_offset; i++)
{
struct dwarf_expr_piece *p = &c->pieces[i];
size_t this_size, this_size_bits;
this_size_bits = p->size - bits_to_skip;
if (this_size_bits > max_offset - offset)
this_size_bits = max_offset - offset;
/* Copy from the source to DEST_BUFFER. */
switch (p->location)
{
case DWARF_VALUE_REGISTER:
{
struct frame_info *frame = frame_find_by_id (c->frame_id);
struct gdbarch *arch = get_frame_arch (frame);
int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno);
ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum);
int optim, unavail;
if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
&& p->offset + p->size < reg_bits)
{
/* Big-endian, and we want less than full size. */
bits_to_skip += reg_bits - (p->offset + p->size);
}
else
bits_to_skip += p->offset;
this_size = bits_to_bytes (bits_to_skip, this_size_bits);
buffer.reserve (this_size);
if (!get_frame_register_bytes (frame, gdb_regnum,
bits_to_skip / 8,
this_size, buffer.data (),
&optim, &unavail))
{
if (optim)
mark_value_bits_optimized_out (v, offset, this_size_bits);
if (unavail)
mark_value_bits_unavailable (v, offset, this_size_bits);
break;
}
copy_bitwise (contents, offset,
buffer.data (), bits_to_skip % 8,
this_size_bits, bits_big_endian);
}
break;
case DWARF_VALUE_MEMORY:
bits_to_skip += p->offset;
this_size = bits_to_bytes (bits_to_skip, this_size_bits);
buffer.reserve (this_size);
read_value_memory (v, offset,
p->v.mem.in_stack_memory,
p->v.mem.addr + bits_to_skip / 8,
buffer.data (), this_size);
copy_bitwise (contents, offset,
buffer.data (), bits_to_skip % 8,
this_size_bits, bits_big_endian);
break;
case DWARF_VALUE_STACK:
{
struct objfile *objfile = dwarf2_per_cu_objfile (c->per_cu);
struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile);
ULONGEST stack_value_size_bits
= 8 * TYPE_LENGTH (value_type (p->v.value));
/* Use zeroes if piece reaches beyond stack value. */
if (p->offset + p->size > stack_value_size_bits)
break;
/* Piece is anchored at least significant bit end. */
if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG)
bits_to_skip += stack_value_size_bits - p->offset - p->size;
else
bits_to_skip += p->offset;
copy_bitwise (contents, offset,
value_contents_all (p->v.value),
bits_to_skip,
this_size_bits, bits_big_endian);
}
break;
case DWARF_VALUE_LITERAL:
{
ULONGEST literal_size_bits = 8 * p->v.literal.length;
size_t n = this_size_bits;
/* Cut off at the end of the implicit value. */
bits_to_skip += p->offset;
if (bits_to_skip >= literal_size_bits)
break;
if (n > literal_size_bits - bits_to_skip)
n = literal_size_bits - bits_to_skip;
copy_bitwise (contents, offset,
p->v.literal.data, bits_to_skip,
n, bits_big_endian);
}
break;
/* These bits show up as zeros -- but do not cause the value
to be considered optimized-out. */
case DWARF_VALUE_IMPLICIT_POINTER:
break;
case DWARF_VALUE_OPTIMIZED_OUT:
mark_value_bits_optimized_out (v, offset, this_size_bits);
break;
default:
internal_error (__FILE__, __LINE__, _("invalid location type"));
}
offset += this_size_bits;
bits_to_skip = 0;
}
}
static void
write_pieced_value (struct value *to, struct value *from)
{
int i;
ULONGEST bits_to_skip;
LONGEST offset = 0, max_offset;
const gdb_byte *contents;
struct piece_closure *c
= (struct piece_closure *) value_computed_closure (to);
std::vector<gdb_byte> buffer;
int bits_big_endian
= gdbarch_bits_big_endian (get_type_arch (value_type (to)));
contents = value_contents (from);
bits_to_skip = 8 * value_offset (to);
if (value_bitsize (to))
{
bits_to_skip += (8 * value_offset (value_parent (to))
+ value_bitpos (to));
/* Use the least significant bits of FROM. */
if (gdbarch_byte_order (get_type_arch (value_type (from)))
== BFD_ENDIAN_BIG)
{
max_offset = 8 * TYPE_LENGTH (value_type (from));
offset = max_offset - value_bitsize (to);
}
else
max_offset = value_bitsize (to);
}
else
max_offset = 8 * TYPE_LENGTH (value_type (to));
/* Advance to the first non-skipped piece. */
for (i = 0; i < c->n_pieces && bits_to_skip >= c->pieces[i].size; i++)
bits_to_skip -= c->pieces[i].size;
for (; i < c->n_pieces && offset < max_offset; i++) for (; i < c->n_pieces && offset < max_offset; i++)
{ {
struct dwarf_expr_piece *p = &c->pieces[i]; struct dwarf_expr_piece *p = &c->pieces[i];
@ -1970,6 +1835,7 @@ write_pieced_value (struct value *to, struct value *from)
struct gdbarch *arch = get_frame_arch (frame); struct gdbarch *arch = get_frame_arch (frame);
int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno); int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno);
ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum); ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum);
int optim, unavail;
if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
&& p->offset + p->size < reg_bits) && p->offset + p->size < reg_bits)
@ -1983,17 +1849,38 @@ write_pieced_value (struct value *to, struct value *from)
this_size = bits_to_bytes (bits_to_skip, this_size_bits); this_size = bits_to_bytes (bits_to_skip, this_size_bits);
buffer.reserve (this_size); buffer.reserve (this_size);
if (bits_to_skip % 8 != 0 || this_size_bits % 8 != 0) if (from == NULL)
{ {
/* Data is copied non-byte-aligned into the register. /* Read mode. */
Need some bits from original register value. */
int optim, unavail;
if (!get_frame_register_bytes (frame, gdb_regnum, if (!get_frame_register_bytes (frame, gdb_regnum,
bits_to_skip / 8, bits_to_skip / 8,
this_size, buffer.data (), this_size, buffer.data (),
&optim, &unavail)) &optim, &unavail))
{ {
if (optim)
mark_value_bits_optimized_out (v, offset,
this_size_bits);
if (unavail)
mark_value_bits_unavailable (v, offset,
this_size_bits);
break;
}
copy_bitwise (v_contents, offset,
buffer.data (), bits_to_skip % 8,
this_size_bits, bits_big_endian);
}
else
{
/* Write mode. */
if (bits_to_skip % 8 != 0 || this_size_bits % 8 != 0)
{
/* Data is copied non-byte-aligned into the register.
Need some bits from original register value. */
get_frame_register_bytes (frame, gdb_regnum,
bits_to_skip / 8,
this_size, buffer.data (),
&optim, &unavail);
if (optim) if (optim)
throw_error (OPTIMIZED_OUT_ERROR, throw_error (OPTIMIZED_OUT_ERROR,
_("Can't do read-modify-write to " _("Can't do read-modify-write to "
@ -2001,20 +1888,21 @@ write_pieced_value (struct value *to, struct value *from)
"has been optimized out")); "has been optimized out"));
if (unavail) if (unavail)
throw_error (NOT_AVAILABLE_ERROR, throw_error (NOT_AVAILABLE_ERROR,
_("Can't do read-modify-write to update " _("Can't do read-modify-write to "
"bitfield; containing word " "update bitfield; containing word "
"is unavailable")); "is unavailable"));
} }
}
copy_bitwise (buffer.data (), bits_to_skip % 8, copy_bitwise (buffer.data (), bits_to_skip % 8,
contents, offset, from_contents, offset,
this_size_bits, bits_big_endian); this_size_bits, bits_big_endian);
put_frame_register_bytes (frame, gdb_regnum, put_frame_register_bytes (frame, gdb_regnum,
bits_to_skip / 8, bits_to_skip / 8,
this_size, buffer.data ()); this_size, buffer.data ());
} }
}
break; break;
case DWARF_VALUE_MEMORY: case DWARF_VALUE_MEMORY:
{ {
bits_to_skip += p->offset; bits_to_skip += p->offset;
@ -2025,8 +1913,16 @@ write_pieced_value (struct value *to, struct value *from)
&& offset % 8 == 0) && offset % 8 == 0)
{ {
/* Everything is byte-aligned; no buffer needed. */ /* Everything is byte-aligned; no buffer needed. */
if (from != NULL)
write_memory_with_notification (start_addr, write_memory_with_notification (start_addr,
contents + offset / 8, (from_contents
+ offset / 8),
this_size_bits / 8);
else
read_value_memory (v, offset,
p->v.mem.in_stack_memory,
p->v.mem.addr + bits_to_skip / 8,
v_contents + offset / 8,
this_size_bits / 8); this_size_bits / 8);
break; break;
} }
@ -2034,17 +1930,32 @@ write_pieced_value (struct value *to, struct value *from)
this_size = bits_to_bytes (bits_to_skip, this_size_bits); this_size = bits_to_bytes (bits_to_skip, this_size_bits);
buffer.reserve (this_size); buffer.reserve (this_size);
if (from == NULL)
{
/* Read mode. */
read_value_memory (v, offset,
p->v.mem.in_stack_memory,
p->v.mem.addr + bits_to_skip / 8,
buffer.data (), this_size);
copy_bitwise (v_contents, offset,
buffer.data (), bits_to_skip % 8,
this_size_bits, bits_big_endian);
}
else
{
/* Write mode. */
if (bits_to_skip % 8 != 0 || this_size_bits % 8 != 0) if (bits_to_skip % 8 != 0 || this_size_bits % 8 != 0)
{ {
if (this_size <= 8) if (this_size <= 8)
{ {
/* Perform a single read for small sizes. */ /* Perform a single read for small sizes. */
read_memory (start_addr, buffer.data (), this_size); read_memory (start_addr, buffer.data (),
this_size);
} }
else else
{ {
/* Only the first and last bytes can possibly have any /* Only the first and last bytes can possibly have
bits reused. */ any bits reused. */
read_memory (start_addr, buffer.data (), 1); read_memory (start_addr, buffer.data (), 1);
read_memory (start_addr + this_size - 1, read_memory (start_addr + this_size - 1,
&buffer[this_size - 1], 1); &buffer[this_size - 1], 1);
@ -2052,21 +1963,106 @@ write_pieced_value (struct value *to, struct value *from)
} }
copy_bitwise (buffer.data (), bits_to_skip % 8, copy_bitwise (buffer.data (), bits_to_skip % 8,
contents, offset, from_contents, offset,
this_size_bits, bits_big_endian); this_size_bits, bits_big_endian);
write_memory_with_notification (start_addr, buffer.data (), write_memory_with_notification (start_addr,
buffer.data (),
this_size); this_size);
} }
}
break; break;
default:
mark_value_bytes_optimized_out (to, 0, TYPE_LENGTH (value_type (to))); case DWARF_VALUE_STACK:
{
if (from != NULL)
{
mark_value_bits_optimized_out (v, offset, this_size_bits);
break; break;
} }
struct objfile *objfile = dwarf2_per_cu_objfile (c->per_cu);
struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile);
ULONGEST stack_value_size_bits
= 8 * TYPE_LENGTH (value_type (p->v.value));
/* Use zeroes if piece reaches beyond stack value. */
if (p->offset + p->size > stack_value_size_bits)
break;
/* Piece is anchored at least significant bit end. */
if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG)
bits_to_skip += stack_value_size_bits - p->offset - p->size;
else
bits_to_skip += p->offset;
copy_bitwise (v_contents, offset,
value_contents_all (p->v.value),
bits_to_skip,
this_size_bits, bits_big_endian);
}
break;
case DWARF_VALUE_LITERAL:
{
if (from != NULL)
{
mark_value_bits_optimized_out (v, offset, this_size_bits);
break;
}
ULONGEST literal_size_bits = 8 * p->v.literal.length;
size_t n = this_size_bits;
/* Cut off at the end of the implicit value. */
bits_to_skip += p->offset;
if (bits_to_skip >= literal_size_bits)
break;
if (n > literal_size_bits - bits_to_skip)
n = literal_size_bits - bits_to_skip;
copy_bitwise (v_contents, offset,
p->v.literal.data, bits_to_skip,
n, bits_big_endian);
}
break;
case DWARF_VALUE_IMPLICIT_POINTER:
if (from != NULL)
{
mark_value_bits_optimized_out (v, offset, this_size_bits);
break;
}
/* These bits show up as zeros -- but do not cause the value to
be considered optimized-out. */
break;
case DWARF_VALUE_OPTIMIZED_OUT:
mark_value_bits_optimized_out (v, offset, this_size_bits);
break;
default:
internal_error (__FILE__, __LINE__, _("invalid location type"));
}
offset += this_size_bits; offset += this_size_bits;
bits_to_skip = 0; bits_to_skip = 0;
} }
} }
static void
read_pieced_value (struct value *v)
{
rw_pieced_value (v, NULL);
}
static void
write_pieced_value (struct value *to, struct value *from)
{
rw_pieced_value (to, from);
}
/* An implementation of an lval_funcs method to see whether a value is /* An implementation of an lval_funcs method to see whether a value is
a synthetic pointer. */ a synthetic pointer. */