gdb/1433: Broken Display of Bitfields

jimb@redhat.com jimb@redhat.com
Wed Oct 29 17:43:00 GMT 2003


Synopsis: Broken Display of Bitfields

State-Changed-From-To: open->closed
State-Changed-By: jimb
State-Changed-When: Wed Oct 29 17:43:10 2003
State-Changed-Why:
    Thanks for the very clear and explicit bug report.
    
    I believe this is a compiler problem: GCC is generatating Dwarf 2 info
    that incorrectly describes the location of the bitfield in the
    structure.
    
    Here is the machine code in your assembly file for the assignment to
    s1.elvis:
    
    .Lg2:
    	movl	s1,%eax
    	andl	$-8192,%eax
    	orl	$8191,%eax
    	movl	%eax,s1
    
    It fetches the first longword (32 bits) of s1, clears the low 13 bits,
    sets them to all ones, and then writes the longword back to s1.  So as
    far as the machine code is concerned, elvis lives in the 13 least
    significant bits of the first longword of s1.
    
    Since the i386 is little-endian, those bits are also the least
    significant end of the first word (16 bits) of s1.  So the debug
    info's 'DW_AT_byte_size' is correct.
    
    However, DW_AT_bit_offset counts from the most significant bit of the
    containing word, not the least significant.  So the proper bit offset
    would be three, not zero.
    
    GCC 3.3 generates the following Dwarf 2 for this:
    
    	.uleb128 0x3	# (DIE (0x2f) DW_TAG_member)
    	.long	.LC0	# DW_AT_name: "elvis"
    	.byte	0x1	# DW_AT_decl_file
    	.byte	0x2	# DW_AT_decl_line
    	.long	0x60	# DW_AT_type
    	.byte	0x4	# DW_AT_byte_size
    	.byte	0xd	# DW_AT_bit_size
    	.byte	0x13	# DW_AT_bit_offset
    	.byte	0x2	# DW_AT_data_member_location
    	.byte	0x23	# DW_OP_plus_uconst
    	.uleb128 0x0
    
    This stipulates a four-byte container, and gives a bit offset of 19,
    which is correct: there are 19 bits of the 32-bit container above the
    13 that contain the actual value.
    
    Here is a transcript of GDB debugging the program correctly, when it
    is compiled with GCC 3.3:
    
    $ cat jvd.c
    struct t {
            int     elvis   :13;
            int     bruce   :5;
            char    jvd;
    } s1;
    
    main() {
    
            s1.elvis = -1;
            s1.bruce = -1;
    
            return s1.jvd == 0;
    }
    $ gcc --version
    gcc (GCC) 3.3
    Copyright (C) 2003 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    $ gcc -g -dA -save-temps jvd.c -o jvd
    $ $D6/gdb/gdb jvd
    GNU gdb 2003-10-17-cvs
    Copyright 2003 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you are
    welcome to change it and/or distribute copies of it under certain conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB.  Type "show warranty" for details.
    This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".
    
    (gdb) break main
    Breakpoint 1 at 0x8048324: file jvd.c, line 9.
    (gdb) run
    Starting program: /rigel/jimb/gdb/bugs/1433/jvd
    
    Breakpoint 1, main () at jvd.c:9
    9               s1.elvis = -1;
    (gdb) disp s1
    1: s1 = {elvis = 0, bruce = 0, jvd = 0 '\0'}
    (gdb) step
    10              s1.bruce = -1;
    1: s1 = {elvis = -1, bruce = 0, jvd = 0 '\0'}
    (gdb)
    12              return s1.jvd == 0;
    1: s1 = {elvis = -1, bruce = -1, jvd = 0 '\0'}
    (gdb)
    13      }
    1: s1 = {elvis = -1, bruce = -1, jvd = 0 '\0'}
    (gdb)

http://sources.redhat.com/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=1433



More information about the Gdb-prs mailing list