This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 2/2] Change ptype/o to print bit offset
- From: Tom Tromey <tromey at adacore dot com>
- To: gdb-patches at sourceware dot org
- Cc: Tom Tromey <tromey at adacore dot com>
- Date: Mon, 29 Apr 2019 12:31:05 -0600
- Subject: [PATCH 2/2] Change ptype/o to print bit offset
- References: <20190429183105.15973-1-tromey@adacore.com>
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-04-29 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-04-29 Tom Tromey <tromey@adacore.com>
* gdb.texinfo (Symbols): Document change to ptype/o.
gdb/testsuite/ChangeLog
2019-04-29 Tom Tromey <tromey@adacore.com>
* gdb.base/ptype-offsets.exp: Update tests.
---
gdb/ChangeLog | 5 ++++
gdb/doc/ChangeLog | 4 ++++
gdb/doc/gdb.texinfo | 9 +++----
gdb/testsuite/ChangeLog | 4 ++++
gdb/testsuite/gdb.base/ptype-offsets.exp | 30 ++++++++++++------------
gdb/typeprint.c | 30 ++++++------------------
6 files changed, 40 insertions(+), 42 deletions(-)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index cf8333d86be..83528a3385e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -17803,15 +17803,16 @@ bitfields:
/* XXX 3-bit hole */
/* XXX 4-byte hole */
/* 8 | 8 */ int64_t a5;
-/* 16:27 | 4 */ int a6 : 5;
-/* 16:56 | 8 */ int64_t a7 : 3;
+/* 16: 0 | 4 */ int a6 : 5;
+/* 16: 5 | 8 */ int64_t a7 : 3;
+"/* XXX 7-byte padding */
/* total size (bytes): 24 */
@}
@end smallexample
-Note how the offset information is now extended to also include how
-many bits are left to be used in each bitfield.
+Note how the offset information is now extended to also include the
+first bit of the bitfield.
@end table
@kindex ptype
diff --git a/gdb/testsuite/gdb.base/ptype-offsets.exp b/gdb/testsuite/gdb.base/ptype-offsets.exp
index 12b3a746005..6116520bbd7 100644
--- a/gdb/testsuite/gdb.base/ptype-offsets.exp
+++ b/gdb/testsuite/gdb.base/ptype-offsets.exp
@@ -38,7 +38,7 @@ gdb_test "ptype /o struct abc" \
"/* offset | size */ type = struct abc \{" \
" public:" \
"/* 8 | 8 */ void *field1;" \
-"/* 16:31 | 4 */ unsigned int field2 : 1;" \
+"/* 16: 0 | 4 */ unsigned int field2 : 1;" \
"/* XXX 7-bit hole */" \
"/* XXX 3-byte hole */" \
"/* 20 | 4 */ int field3;" \
@@ -63,7 +63,7 @@ gdb_test "ptype /oTM struct abc" \
"/* offset | size */ type = struct abc \{" \
" public:" \
"/* 8 | 8 */ void *field1;" \
-"/* 16:31 | 4 */ unsigned int field2 : 1;" \
+"/* 16: 0 | 4 */ unsigned int field2 : 1;" \
"/* XXX 7-bit hole */" \
"/* XXX 3-byte hole */" \
"/* 20 | 4 */ int field3;" \
@@ -93,7 +93,7 @@ gdb_test "ptype /TMo struct abc" \
"/* offset | size */ type = struct abc \{" \
" public:" \
"/* 8 | 8 */ void *field1;" \
-"/* 16:31 | 4 */ unsigned int field2 : 1;" \
+"/* 16: 0 | 4 */ unsigned int field2 : 1;" \
"/* XXX 7-bit hole */" \
"/* XXX 3-byte hole */" \
"/* 20 | 4 */ int field3;" \
@@ -264,15 +264,15 @@ gdb_test "ptype /o struct poi" \
gdb_test "ptype /o struct tyu" \
[string_to_regexp [multi_line \
"/* offset | size */ type = struct tyu \{" \
-"/* 0:31 | 4 */ int a1 : 1;" \
-"/* 0:28 | 4 */ int a2 : 3;" \
-"/* 0: 5 | 4 */ int a3 : 23;" \
+"/* 0: 0 | 4 */ int a1 : 1;" \
+"/* 0: 1 | 4 */ int a2 : 3;" \
+"/* 0: 4 | 4 */ int a3 : 23;" \
"/* 3: 3 | 1 */ signed char a4 : 2;" \
"/* XXX 3-bit hole */" \
"/* XXX 4-byte hole */" \
"/* 8 | 8 */ int64_t a5;" \
-"/* 16:27 | 4 */ int a6 : 5;" \
-"/* 16:56 | 8 */ int64_t a7 : 3;" \
+"/* 16: 0 | 4 */ int a6 : 5;" \
+"/* 16: 5 | 8 */ int64_t a7 : 3;" \
"/* XXX 7-byte padding */" \
"" \
" /* total size (bytes): 24 */" \
@@ -293,8 +293,8 @@ gdb_test "ptype /o struct asd" \
"" \
" /* total size (bytes): 8 */" \
" \} f3;" \
-"/* 24:27 | 4 */ int f4 : 5;" \
-"/* 24:26 | 4 */ unsigned int f5 : 1;" \
+"/* 24: 0 | 4 */ int f4 : 5;" \
+"/* 24: 5 | 4 */ unsigned int f5 : 1;" \
"/* XXX 2-bit hole */" \
"/* XXX 1-byte hole */" \
"/* 26 | 2 */ short f6;" \
@@ -304,11 +304,11 @@ gdb_test "ptype /o struct asd" \
" \} f7;" \
"/* 32 | 8 */ unsigned long f8;" \
"/* 40 | 8 */ signed char *f9;" \
-"/* 48:28 | 4 */ int f10 : 4;" \
-"/* 48:27 | 4 */ unsigned int f11 : 1;" \
-"/* 48:26 | 4 */ unsigned int f12 : 1;" \
-"/* 48:25 | 4 */ unsigned int f13 : 1;" \
-"/* 48:24 | 4 */ unsigned int f14 : 1;" \
+"/* 48: 0 | 4 */ int f10 : 4;" \
+"/* 48: 4 | 4 */ unsigned int f11 : 1;" \
+"/* 48: 5 | 4 */ unsigned int f12 : 1;" \
+"/* 48: 6 | 4 */ unsigned int f13 : 1;" \
+"/* 48: 7 | 4 */ unsigned int f14 : 1;" \
"/* XXX 7-byte hole */" \
"/* 56 | 8 */ void *f15;" \
"/* 64 | 8 */ void *f16;" \
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
{
--
2.20.1