Change ptype/o to print bit offset

Consider this short C example:

    struct inner
    {
      unsigned x;
      unsigned y : 3;
      unsigned z : 3;
    };

    struct outer
    {
      unsigned char o : 3;
      struct inner i __attribute__ ((packed));
    };

When I use "ptype/o" on this, I get:

    (gdb) ptype/o struct outer
    /* offset    |  size */  type = struct outer {
    /*    0: 5   |     1 */    unsigned char o : 3;
    /* XXX  5-bit hole  */
    /*    1      |     8 */    struct inner {
    /*    1      |     4 */        unsigned int x;
    /*    5:29   |     4 */        unsigned int y : 3;
    /*    5:26   |     4 */        unsigned int z : 3;
    /* XXX  2-bit padding  */
    /* XXX  3-byte padding */

				   /* total size (bytes):    8 */
			       } i;

			       /* total size (bytes):    9 */
			     }

In the location of "o" ("0: 5"), the "5" means "there are 5 bits left
relative to the size of the underlying type.

I find this very difficult to follow.  On irc, Sergio said that this
choice came because it is what pahole does.  However, I think it's not
very useful, and maybe is just an artifact of the way that
DW_AT_bit_offset was defined in DWARF 3.

This patch changes ptype/o to print the offset of a bitfield in a more
natural way, that is, using the bit number according to the platform's
bit numbering.

With this patch, the output is now:

    (gdb) ptype/o struct outer
    /* offset    |  size */  type = struct outer {
    /*    0: 0   |     1 */    unsigned char o : 3;
    /* XXX  5-bit hole  */
    /*    1      |     8 */    struct inner {
    /*    1      |     4 */        unsigned int x;
    /*    5: 0   |     4 */        unsigned int y : 3;
    /*    5: 3   |     4 */        unsigned int z : 3;
    /* XXX  2-bit padding  */
    /* XXX  3-byte padding */

				   /* total size (bytes):    8 */
			       } i;

			       /* total size (bytes):    9 */
			     }

This is better, IMO, because now the "offset" of a bitfield is
consistent with the offset of an ordinary member, referring to its
offset from the start of the structure.

gdb/ChangeLog
2019-05-08  Tom Tromey  <tromey@adacore.com>

	* typeprint.c (print_offset_data::update): Print the bit offset,
	not the number of bits remaining.

gdb/doc/ChangeLog
2019-05-08  Tom Tromey  <tromey@adacore.com>

	* gdb.texinfo (Symbols): Document change to ptype/o.

gdb/testsuite/ChangeLog
2019-05-08  Tom Tromey  <tromey@adacore.com>

	* gdb.base/ptype-offsets.exp: Update tests.
This commit is contained in:
Tom Tromey 2019-04-29 09:55:56 -06:00
parent 844333e249
commit 9d3421afbb
6 changed files with 40 additions and 42 deletions

View File

@ -1,3 +1,8 @@
2019-05-08 Tom Tromey <tromey@adacore.com>
* typeprint.c (print_offset_data::update): Print the bit offset,
not the number of bits remaining.
2019-05-08 Tom Tromey <tromey@adacore.com> 2019-05-08 Tom Tromey <tromey@adacore.com>
* typeprint.c (print_offset_data::maybe_print_hole): Add extra * typeprint.c (print_offset_data::maybe_print_hole): Add extra

View File

@ -1,3 +1,7 @@
2019-05-08 Tom Tromey <tromey@adacore.com>
* gdb.texinfo (Symbols): Document change to ptype/o.
2019-05-03 Eli Zaretskii <eliz@gnu.org> 2019-05-03 Eli Zaretskii <eliz@gnu.org>
* gdb.texinfo (Separate Debug Files): Document how the * gdb.texinfo (Separate Debug Files): Document how the

View File

@ -17861,15 +17861,16 @@ bitfields:
/* XXX 3-bit hole */ /* XXX 3-bit hole */
/* XXX 4-byte hole */ /* XXX 4-byte hole */
/* 8 | 8 */ int64_t a5; /* 8 | 8 */ int64_t a5;
/* 16:27 | 4 */ int a6 : 5; /* 16: 0 | 4 */ int a6 : 5;
/* 16:56 | 8 */ int64_t a7 : 3; /* 16: 5 | 8 */ int64_t a7 : 3;
"/* XXX 7-byte padding */
/* total size (bytes): 24 */ /* total size (bytes): 24 */
@} @}
@end smallexample @end smallexample
Note how the offset information is now extended to also include how Note how the offset information is now extended to also include the
many bits are left to be used in each bitfield. first bit of the bitfield.
@end table @end table
@kindex ptype @kindex ptype

View File

@ -1,3 +1,7 @@
2019-05-08 Tom Tromey <tromey@adacore.com>
* gdb.base/ptype-offsets.exp: Update tests.
2019-05-08 Tom Tromey <tromey@adacore.com> 2019-05-08 Tom Tromey <tromey@adacore.com>
* gdb.base/ptype-offsets.exp: Use string_to_regexp. Fix test * gdb.base/ptype-offsets.exp: Use string_to_regexp. Fix test

View File

@ -38,7 +38,7 @@ gdb_test "ptype /o struct abc" \
"/* offset | size */ type = struct abc \{" \ "/* offset | size */ type = struct abc \{" \
" public:" \ " public:" \
"/* 8 | 8 */ void *field1;" \ "/* 8 | 8 */ void *field1;" \
"/* 16:31 | 4 */ unsigned int field2 : 1;" \ "/* 16: 0 | 4 */ unsigned int field2 : 1;" \
"/* XXX 7-bit hole */" \ "/* XXX 7-bit hole */" \
"/* XXX 3-byte hole */" \ "/* XXX 3-byte hole */" \
"/* 20 | 4 */ int field3;" \ "/* 20 | 4 */ int field3;" \
@ -63,7 +63,7 @@ gdb_test "ptype /oTM struct abc" \
"/* offset | size */ type = struct abc \{" \ "/* offset | size */ type = struct abc \{" \
" public:" \ " public:" \
"/* 8 | 8 */ void *field1;" \ "/* 8 | 8 */ void *field1;" \
"/* 16:31 | 4 */ unsigned int field2 : 1;" \ "/* 16: 0 | 4 */ unsigned int field2 : 1;" \
"/* XXX 7-bit hole */" \ "/* XXX 7-bit hole */" \
"/* XXX 3-byte hole */" \ "/* XXX 3-byte hole */" \
"/* 20 | 4 */ int field3;" \ "/* 20 | 4 */ int field3;" \
@ -93,7 +93,7 @@ gdb_test "ptype /TMo struct abc" \
"/* offset | size */ type = struct abc \{" \ "/* offset | size */ type = struct abc \{" \
" public:" \ " public:" \
"/* 8 | 8 */ void *field1;" \ "/* 8 | 8 */ void *field1;" \
"/* 16:31 | 4 */ unsigned int field2 : 1;" \ "/* 16: 0 | 4 */ unsigned int field2 : 1;" \
"/* XXX 7-bit hole */" \ "/* XXX 7-bit hole */" \
"/* XXX 3-byte hole */" \ "/* XXX 3-byte hole */" \
"/* 20 | 4 */ int field3;" \ "/* 20 | 4 */ int field3;" \
@ -264,15 +264,15 @@ gdb_test "ptype /o struct poi" \
gdb_test "ptype /o struct tyu" \ gdb_test "ptype /o struct tyu" \
[string_to_regexp [multi_line \ [string_to_regexp [multi_line \
"/* offset | size */ type = struct tyu \{" \ "/* offset | size */ type = struct tyu \{" \
"/* 0:31 | 4 */ int a1 : 1;" \ "/* 0: 0 | 4 */ int a1 : 1;" \
"/* 0:28 | 4 */ int a2 : 3;" \ "/* 0: 1 | 4 */ int a2 : 3;" \
"/* 0: 5 | 4 */ int a3 : 23;" \ "/* 0: 4 | 4 */ int a3 : 23;" \
"/* 3: 3 | 1 */ signed char a4 : 2;" \ "/* 3: 3 | 1 */ signed char a4 : 2;" \
"/* XXX 3-bit hole */" \ "/* XXX 3-bit hole */" \
"/* XXX 4-byte hole */" \ "/* XXX 4-byte hole */" \
"/* 8 | 8 */ int64_t a5;" \ "/* 8 | 8 */ int64_t a5;" \
"/* 16:27 | 4 */ int a6 : 5;" \ "/* 16: 0 | 4 */ int a6 : 5;" \
"/* 16:56 | 8 */ int64_t a7 : 3;" \ "/* 16: 5 | 8 */ int64_t a7 : 3;" \
"/* XXX 7-byte padding */" \ "/* XXX 7-byte padding */" \
"" \ "" \
" /* total size (bytes): 24 */" \ " /* total size (bytes): 24 */" \
@ -293,8 +293,8 @@ gdb_test "ptype /o struct asd" \
"" \ "" \
" /* total size (bytes): 8 */" \ " /* total size (bytes): 8 */" \
" \} f3;" \ " \} f3;" \
"/* 24:27 | 4 */ int f4 : 5;" \ "/* 24: 0 | 4 */ int f4 : 5;" \
"/* 24:26 | 4 */ unsigned int f5 : 1;" \ "/* 24: 5 | 4 */ unsigned int f5 : 1;" \
"/* XXX 2-bit hole */" \ "/* XXX 2-bit hole */" \
"/* XXX 1-byte hole */" \ "/* XXX 1-byte hole */" \
"/* 26 | 2 */ short f6;" \ "/* 26 | 2 */ short f6;" \
@ -304,11 +304,11 @@ gdb_test "ptype /o struct asd" \
" \} f7;" \ " \} f7;" \
"/* 32 | 8 */ unsigned long f8;" \ "/* 32 | 8 */ unsigned long f8;" \
"/* 40 | 8 */ signed char *f9;" \ "/* 40 | 8 */ signed char *f9;" \
"/* 48:28 | 4 */ int f10 : 4;" \ "/* 48: 0 | 4 */ int f10 : 4;" \
"/* 48:27 | 4 */ unsigned int f11 : 1;" \ "/* 48: 4 | 4 */ unsigned int f11 : 1;" \
"/* 48:26 | 4 */ unsigned int f12 : 1;" \ "/* 48: 5 | 4 */ unsigned int f12 : 1;" \
"/* 48:25 | 4 */ unsigned int f13 : 1;" \ "/* 48: 6 | 4 */ unsigned int f13 : 1;" \
"/* 48:24 | 4 */ unsigned int f14 : 1;" \ "/* 48: 7 | 4 */ unsigned int f14 : 1;" \
"/* XXX 7-byte hole */" \ "/* XXX 7-byte hole */" \
"/* 56 | 8 */ void *f15;" \ "/* 56 | 8 */ void *f15;" \
"/* 64 | 8 */ void *f16;" \ "/* 64 | 8 */ void *f16;" \

View File

@ -131,32 +131,16 @@ print_offset_data::update (struct type *type, unsigned int field_idx,
maybe_print_hole (stream, bitpos, "hole"); maybe_print_hole (stream, bitpos, "hole");
if (TYPE_FIELD_PACKED (type, field_idx)) if (TYPE_FIELD_PACKED (type, field_idx)
|| offset_bitpos % TARGET_CHAR_BIT != 0)
{ {
/* We're dealing with a bitfield. Print how many bits are left /* We're dealing with a bitfield. Print the bit offset. */
to be used. */ fieldsize_bit = TYPE_FIELD_BITSIZE (type, field_idx);
unsigned int bitsize = TYPE_FIELD_BITSIZE (type, field_idx);
/* The bitpos relative to the beginning of our container
field. */
unsigned int relative_bitpos;
/* The following was copied from unsigned real_bitpos = bitpos + offset_bitpos;
value.c:value_primitive_field. */
if ((bitpos % fieldsize_bit) + bitsize <= fieldsize_bit)
relative_bitpos = bitpos % fieldsize_bit;
else
relative_bitpos = bitpos % TARGET_CHAR_BIT;
/* This is the exact offset (in bits) of this bitfield. */ fprintf_filtered (stream, "/* %4u:%2u", real_bitpos / TARGET_CHAR_BIT,
unsigned int bit_offset real_bitpos % TARGET_CHAR_BIT);
= (bitpos - relative_bitpos) + offset_bitpos;
/* The position of the field, relative to the beginning of the
struct, and how many bits are left to be used in this
container. */
fprintf_filtered (stream, "/* %4u:%2u", bit_offset / TARGET_CHAR_BIT,
fieldsize_bit - (relative_bitpos + bitsize));
fieldsize_bit = bitsize;
} }
else else
{ {