Fix PR symtab/15391

PR symtab/15391 is a failure with the DW_OP_GNU_implicit_pointer
feature.

I tracked it down to a logic error in read_pieced_value.  The code
truncates this_size_bits according to the type size and offset too
early -- it should do it after taking bits_to_skip into account.

This patch fixes the bug.

While testing this, I also tripped across a latent bug because
indirect_pieced_value does not sign-extend where needed.  This patch
fixes this bug as well.

Finally, Pedro pointed out that a previous version implemented sign
extension incorrectly.  This version introduces a new gdb_sign_extend
function for this.  A couple of notes on this function:

* It has the gdb_ prefix to avoid clashes with various libraries that
  felt free to avoid proper namespacing.  There is a "sign_extend"
  function in a Tile GX header, in an SOM-related BFD header (and in
  sh64-tdep.c and as a macro in arm-wince-tdep.c, but those are
  ours...)

* I looked at all the sign extensions in gdb and didn't see ones that
  I felt comfortable converting to use this function; in large part
  because I don't have a good way to test the conversion.

Built and regtested on x86-64 Fedora 18.  New test cases included;
this required a minor addition to the DWARF assembler.  Note that the
DWARF CU made by implptrpiece.exp uses a funny pointer size in order
to show the sign-extension bug on all platforms.

	* dwarf2loc.c (read_pieced_value): Truncate this_size_bits
	after taking bits_to_skip into account.  Sign extend byte_offset.
	* utils.h (gdb_sign_extend): Declare.
	* utils.c (gdb_sign_extend): New function.

	* gdb.dwarf2/implptrpiece.exp: New file.
	* gdb.dwarf2/implptrconst.exp (d): New variable.
	Print d.
	* lib/dwarf2.exp (Dwarf::_location): Handle DW_OP_piece.
This commit is contained in:
Tom Tromey
2013-06-18 18:11:19 +00:00
parent 92fac8075a
commit 5bd1ef568c
8 changed files with 194 additions and 5 deletions

View File

@@ -1641,8 +1641,6 @@ read_pieced_value (struct value *v)
bits_to_skip -= this_size_bits;
continue;
}
if (this_size_bits > type_len - offset)
this_size_bits = type_len - offset;
if (bits_to_skip > 0)
{
dest_offset_bits = 0;
@@ -1655,6 +1653,8 @@ read_pieced_value (struct value *v)
dest_offset_bits = offset;
source_offset_bits = 0;
}
if (this_size_bits > type_len - offset)
this_size_bits = type_len - offset;
this_size = (this_size_bits + source_offset_bits % 8 + 7) / 8;
source_offset = source_offset_bits / 8;
@@ -2087,8 +2087,15 @@ indirect_pieced_value (struct value *value)
frame = get_selected_frame (_("No frame selected."));
/* This is an offset requested by GDB, such as value subcripts. */
/* This is an offset requested by GDB, such as value subscripts.
However, due to how synthetic pointers are implemented, this is
always presented to us as a pointer type. This means we have to
sign-extend it manually as appropriate. */
byte_offset = value_as_address (value);
if (TYPE_LENGTH (value_type (value)) < sizeof (LONGEST))
byte_offset = gdb_sign_extend (byte_offset,
8 * TYPE_LENGTH (value_type (value)));
byte_offset += piece->v.ptr.offset;
gdb_assert (piece);
baton
@@ -2099,7 +2106,7 @@ indirect_pieced_value (struct value *value)
if (baton.data != NULL)
return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame,
baton.data, baton.size, baton.per_cu,
piece->v.ptr.offset + byte_offset);
byte_offset);
{
struct obstack temp_obstack;