From patchwork Mon Apr 29 18:31:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 32462 Received: (qmail 10806 invoked by alias); 29 Apr 2019 18:31:11 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 10763 invoked by uid 89); 29 Apr 2019 18:31:11 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=abc, sergio, HX-Envelope-From:sk:tromey@, H*F:U*tromey X-HELO: rock.gnat.com Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 29 Apr 2019 18:31:09 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id C8BA811717F; Mon, 29 Apr 2019 14:31:07 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 8DqHiX9AXcUC; Mon, 29 Apr 2019 14:31:07 -0400 (EDT) Received: from murgatroyd.Home (97-122-168-123.hlrn.qwest.net [97.122.168.123]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by rock.gnat.com (Postfix) with ESMTPSA id 711BA1170BD; Mon, 29 Apr 2019 14:31:07 -0400 (EDT) From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 2/2] Change ptype/o to print bit offset Date: Mon, 29 Apr 2019 12:31:05 -0600 Message-Id: <20190429183105.15973-3-tromey@adacore.com> In-Reply-To: <20190429183105.15973-1-tromey@adacore.com> References: <20190429183105.15973-1-tromey@adacore.com> MIME-Version: 1.0 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 * typeprint.c (print_offset_data::update): Print the bit offset, not the number of bits remaining. gdb/doc/ChangeLog 2019-04-29 Tom Tromey * gdb.texinfo (Symbols): Document change to ptype/o. gdb/testsuite/ChangeLog 2019-04-29 Tom Tromey * 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 {