struct S { short a; char b, c; }; volatile int v; void foo (int x) { struct S s = { x, x + 2, x + 3 }; char *p = &s.b; s.a++; v++; /* line 8 */ } int main () { foo (1); return 0; } gcc-4.8.0-2.fc19.x86_64 gcc -g -O2 -fno-inline -fno-ipa-cp -o implptr implptr.c -Wall gdb ./implptr -ex 'b 8' -ex r -ex 'p p[-1]' -ex c -ex q -q Actual: $1 = 3 '\003' Expected: $1 = 0 '\000' Bugreported by Jakub Jelinek. Abbrev Number: 7 (DW_TAG_variable) DW_AT_name : s DW_AT_location : (DW_OP_breg5 (rdi): 1; DW_OP_stack_value; DW_OP_piece: 2; DW_OP_breg5 (rdi): 2; DW_OP_stack_value; DW_OP_piece: 1; DW_OP_breg5 (rdi): 3; DW_OP_stack_value; DW_OP_piece: 1) Abbrev Number: 7 (DW_TAG_variable) DW_AT_name : p DW_AT_location : (DW_OP_GNU_implicit_pointer: <0x88> 2)
CVSROOT: /cvs/src Module name: src Changes by: tromey@sourceware.org 2013-06-18 18:11:19 Modified files: gdb : ChangeLog dwarf2loc.c utils.c utils.h gdb/testsuite : ChangeLog gdb/testsuite/gdb.dwarf2: implptrconst.exp gdb/testsuite/lib: dwarf.exp Added files: gdb/testsuite/gdb.dwarf2: implptrpiece.exp Log message: 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. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ChangeLog.diff?cvsroot=src&r1=1.15708&r2=1.15709 http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/dwarf2loc.c.diff?cvsroot=src&r1=1.173&r2=1.174 http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/utils.c.diff?cvsroot=src&r1=1.300&r2=1.301 http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/utils.h.diff?cvsroot=src&r1=1.8&r2=1.9 http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/ChangeLog.diff?cvsroot=src&r1=1.3696&r2=1.3697 http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.dwarf2/implptrpiece.exp.diff?cvsroot=src&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.dwarf2/implptrconst.exp.diff?cvsroot=src&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/lib/dwarf.exp.diff?cvsroot=src&r1=1.9&r2=1.10
Fixed.
The master branch has been updated by Andreas Arnez <arnez@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d5d1163eff2415a01895f1cff8bbee32b3f0ab66 commit d5d1163eff2415a01895f1cff8bbee32b3f0ab66 Author: Andreas Arnez <arnez@linux.vnet.ibm.com> Date: Tue Jun 13 15:20:26 2017 +0200 write_pieced_value: Fix size capping logic A field f in a structure composed of DWARF pieces may be located in multiple pieces, where the first and last of those may contain bits from other fields as well. So when writing to f, the beginning of the first and the end of the last of those pieces may have to be skipped. But the logic in write_pieced_value for handling one of those pieces is flawed when the first and last piece are the same, i.e., f is contained in a single piece: < - - - - - - - - - piece_size - - - - - - - - - -> +-------------------------------------------------+ | skipped_bits | f_bits | / / / / / / / / / / | +-------------------------------------------------+ The current logic determines the size of the sub-piece to operate on by limiting the piece size to the bit size of f and then subtracting the skipped bits: min (piece_size, f_bits) - skipped_bits Instead of: min (piece_size - skipped_bits, f_bits) So the resulting sub-piece size is corrupted, leading to wrong handling of this piece in write_pieced_value. Note that the same bug was already found in read_pieced_value and fixed there (but not in write_pieced_value), see PR 15391. This patch swaps the calculations, bringing them into the same (correct) order as in read_pieced_value. gdb/ChangeLog: * dwarf2loc.c (write_pieced_value): Fix order of calculations for size capping. gdb/testsuite/ChangeLog: * gdb.dwarf2/var-pieces.exp: Add test case for modifying a variable at nonzero offset.