forked from Imagelibrary/binutils-gdb
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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user