diff options
author | Tom Tromey <tromey@adacore.com> | 2019-04-29 09:55:56 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2019-05-08 10:15:51 -0600 |
commit | 9d3421afbb9f3cfc8e67366ba75ea12ed8f732a3 (patch) | |
tree | 66eb6aba210e07f4f76b979c07687598d477dcea /gdb/typeprint.c | |
parent | 844333e24966817fe4d622494a75c8ae0acdb91f (diff) | |
download | binutils-gdb-9d3421afbb9f3cfc8e67366ba75ea12ed8f732a3.tar.gz |
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.
Diffstat (limited to 'gdb/typeprint.c')
-rw-r--r-- | gdb/typeprint.c | 30 |
1 files changed, 7 insertions, 23 deletions
diff --git a/gdb/typeprint.c b/gdb/typeprint.c index d1cdfe11cc0..7a44dbdb313 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -131,32 +131,16 @@ print_offset_data::update (struct type *type, unsigned int field_idx, 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 - to be used. */ - 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 - value.c:value_primitive_field. */ - if ((bitpos % fieldsize_bit) + bitsize <= fieldsize_bit) - relative_bitpos = bitpos % fieldsize_bit; - else - relative_bitpos = bitpos % TARGET_CHAR_BIT; + /* We're dealing with a bitfield. Print the bit offset. */ + fieldsize_bit = TYPE_FIELD_BITSIZE (type, field_idx); - /* This is the exact offset (in bits) of this bitfield. */ - unsigned int bit_offset - = (bitpos - relative_bitpos) + offset_bitpos; + unsigned real_bitpos = 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; + fprintf_filtered (stream, "/* %4u:%2u", real_bitpos / TARGET_CHAR_BIT, + real_bitpos % TARGET_CHAR_BIT); } else { |