[RFA] Show padding in ptype/o output
Commit Message
>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
Tom> I was recently using ptype/o to look at the layout of some objects in
Tom> gdb. I noticed that trailing padding was not shown -- but I wanted to
Tom> be able to look at that, too.
Tom> This patch changes ptype/o to also print trailing holes.
Oops, I forgot to squash those commits and only sent the test suite
change.
Here's the real patch.
Tom
commit f4c9741648a991f4591b290000214a9dbaf8099a
Author: Tom Tromey <tom@tromey.com>
Date: Sat May 12 17:04:50 2018 -0600
Show padding in ptype/o output
I was recently using ptype/o to look at the layout of some objects in
gdb. I noticed that trailing padding was not shown -- but I wanted to
be able to look at that, too.
This patch changes ptype/o to also print trailing holes.
Tested on x86-64 Fedora 26.
gdb/ChangeLog
2018-05-17 Tom Tromey <tom@tromey.com>
* c-typeprint.c (maybe_print_hole): New function.
(c_print_type_struct_field_offset): Update.
(c_type_print_base_struct_union): Call maybe_print_hole.
gdb/testsuite/ChangeLog
2018-05-17 Tom Tromey <tom@tromey.com>
* gdb.base/ptype-offsets.exp: Update.
Comments
On Thursday, May 17 2018, Tom Tromey wrote:
>>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
>
> Tom> I was recently using ptype/o to look at the layout of some objects in
> Tom> gdb. I noticed that trailing padding was not shown -- but I wanted to
> Tom> be able to look at that, too.
>
> Tom> This patch changes ptype/o to also print trailing holes.
Hm, I don't remember why I didn't implement this. Maybe I was too
frustrated trying to figure out how to deal with bitfields... Though I
seem to remember having a bit of a trouble with holes at the end of
objects. But I don't really know, and if you ran the testcase and
everything passed, then I'd say it's good to go.
Thanks for implementing it.
> Oops, I forgot to squash those commits and only sent the test suite
> change.
>
> Here's the real patch.
>
> Tom
>
> commit f4c9741648a991f4591b290000214a9dbaf8099a
> Author: Tom Tromey <tom@tromey.com>
> Date: Sat May 12 17:04:50 2018 -0600
>
> Show padding in ptype/o output
>
> I was recently using ptype/o to look at the layout of some objects in
> gdb. I noticed that trailing padding was not shown -- but I wanted to
> be able to look at that, too.
>
> This patch changes ptype/o to also print trailing holes.
>
> Tested on x86-64 Fedora 26.
>
> gdb/ChangeLog
> 2018-05-17 Tom Tromey <tom@tromey.com>
>
> * c-typeprint.c (maybe_print_hole): New function.
> (c_print_type_struct_field_offset): Update.
> (c_type_print_base_struct_union): Call maybe_print_hole.
>
> gdb/testsuite/ChangeLog
> 2018-05-17 Tom Tromey <tom@tromey.com>
>
> * gdb.base/ptype-offsets.exp: Update.
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 4ae46c1ae4..759ce08577 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,11 @@
> 2018-05-17 Tom Tromey <tom@tromey.com>
>
> + * c-typeprint.c (maybe_print_hole): New function.
> + (c_print_type_struct_field_offset): Update.
> + (c_type_print_base_struct_union): Call maybe_print_hole.
> +
> +2018-05-17 Tom Tromey <tom@tromey.com>
> +
> * extension.h (struct ext_lang_type_printers) <py_type_printers>:
> Initialize.
>
> diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
> index 1a8af78669..cb793f0770 100644
> --- a/gdb/c-typeprint.c
> +++ b/gdb/c-typeprint.c
> @@ -937,6 +937,42 @@ c_print_type_union_field_offset (struct type *type, unsigned int field_idx,
> fprintf_filtered (stream, "/* %4u */", TYPE_LENGTH (ftype));
> }
>
> +/* Helper function for ptype/o implementation that prints information
> + about a hole, if necessary. STREAM is where to print. BITPOS is
> + the bitpos of the current field. PODATA is the offset-printing
> + state. FOR_WHAT is a string describing the purpose of the
> + hole. */
> +
> +static void
> +maybe_print_hole (struct ui_file *stream, unsigned int bitpos,
> + struct print_offset_data *podata, const char *for_what)
> +{
> + /* We check for PODATA->END_BITPOS > 0 because there is a specific
> + scenario when PODATA->END_BITPOS can be zero and BITPOS can be >
> + 0: when we are dealing with a struct/class with a virtual method.
> + Because of the vtable, the first field of the struct/class will
> + have an offset of sizeof (void *) (the size of the vtable). If
> + we do not check for PODATA->END_BITPOS > 0 here, GDB will report
> + a hole before the first field, which is not accurate. */
> + if (podata->end_bitpos > 0 && podata->end_bitpos < bitpos)
> + {
> + /* If PODATA->END_BITPOS is smaller than the current type's
> + bitpos, it means there's a hole in the struct, so we report
> + it here. */
> + unsigned int hole = bitpos - podata->end_bitpos;
> + unsigned int hole_byte = hole / TARGET_CHAR_BIT;
> + unsigned int hole_bit = hole % TARGET_CHAR_BIT;
> +
> + if (hole_bit > 0)
> + fprintf_filtered (stream, "/* XXX %2u-bit %s */\n", hole_bit,
> + for_what);
> +
> + if (hole_byte > 0)
> + fprintf_filtered (stream, "/* XXX %2u-byte %s */\n", hole_byte,
> + for_what);
> + }
> +}
> +
> /* Print information about field at index FIELD_IDX of the struct type
> TYPE.
>
> @@ -963,28 +999,7 @@ c_print_type_struct_field_offset (struct type *type, unsigned int field_idx,
> unsigned int fieldsize_byte = TYPE_LENGTH (ftype);
> unsigned int fieldsize_bit = fieldsize_byte * TARGET_CHAR_BIT;
>
> - /* We check for PODATA->END_BITPOS > 0 because there is a specific
> - scenario when PODATA->END_BITPOS can be zero and BITPOS can be >
> - 0: when we are dealing with a struct/class with a virtual method.
> - Because of the vtable, the first field of the struct/class will
> - have an offset of sizeof (void *) (the size of the vtable). If
> - we do not check for PODATA->END_BITPOS > 0 here, GDB will report
> - a hole before the first field, which is not accurate. */
> - if (podata->end_bitpos > 0 && podata->end_bitpos < bitpos)
> - {
> - /* If PODATA->END_BITPOS is smaller than the current type's
> - bitpos, it means there's a hole in the struct, so we report
> - it here. */
> - unsigned int hole = bitpos - podata->end_bitpos;
> - unsigned int hole_byte = hole / TARGET_CHAR_BIT;
> - unsigned int hole_bit = hole % TARGET_CHAR_BIT;
> -
> - if (hole_bit > 0)
> - fprintf_filtered (stream, "/* XXX %2u-bit hole */\n", hole_bit);
> -
> - if (hole_byte > 0)
> - fprintf_filtered (stream, "/* XXX %2u-byte hole */\n", hole_byte);
> - }
> + maybe_print_hole (stream, bitpos, podata, "hole");
>
> if (TYPE_FIELD_PACKED (type, field_idx))
> {
> @@ -1508,6 +1523,9 @@ c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
> {
> if (show > 0)
> {
> + unsigned int bitpos = TYPE_LENGTH (type) * TARGET_CHAR_BIT;
> + maybe_print_hole (stream, bitpos, podata, "padding");
> +
> fputs_filtered ("\n", stream);
> print_spaces_filtered_with_print_options (level + 4,
> stream,
> diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
> index b18d4b6743..03fd99bf41 100644
> --- a/gdb/testsuite/ChangeLog
> +++ b/gdb/testsuite/ChangeLog
> @@ -1,3 +1,7 @@
> +2018-05-17 Tom Tromey <tom@tromey.com>
> +
> + * gdb.base/ptype-offsets.exp: Update.
> +
> 2018-05-15 Maciej W. Rozycki <macro@mips.com>
>
> * gdb.server/server-kill.exp: Verify whether `server_pid' exists
> diff --git a/gdb/testsuite/gdb.base/ptype-offsets.exp b/gdb/testsuite/gdb.base/ptype-offsets.exp
> index 003e294a74..d8718d581b 100644
> --- a/gdb/testsuite/gdb.base/ptype-offsets.exp
> +++ b/gdb/testsuite/gdb.base/ptype-offsets.exp
> @@ -52,6 +52,7 @@ gdb_test "ptype /o struct abc" \
> { /\* total size \(bytes\): 8 \*/} \
> { \} field8;} \
> {/\* 48 | 4 \*/ my_int_type field9;} \
> +{/\* XXX 4-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 56 \*/} \
> { \}}]
> @@ -81,6 +82,7 @@ gdb_test "ptype /oTM struct abc" \
> { ~abc\(\);} \
> {} \
> { typedef int my_int_type;} \
> +{/\* XXX 4-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 56 \*/} \
> { \}}]
> @@ -105,6 +107,7 @@ gdb_test "ptype /TMo struct abc" \
> { /\* total size \(bytes\): 8 \*/} \
> { \} field8;} \
> {/\* 48 | 4 \*/ my_int_type field9;} \
> +{/\* XXX 4-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 56 \*/} \
> { \}}]
> @@ -133,6 +136,7 @@ gdb_test "ptype /o struct pqr" \
> { \} ff2;} \
> {/\* XXX 28-byte hole \*/} \
> {/\* 72 | 1 \*/ signed char ff3;} \
> +{/\* XXX 7-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 56 \*/} \
> { \}}]
> @@ -148,6 +152,7 @@ gdb_test "ptype /o union qwe" \
> {/\* XXX 4-byte hole \*/} \
> {/\* 8 | 8 \*/ signed char \*a2;} \
> {/\* 16 | 4 \*/ int a3;} \
> +{/\* XXX 4-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 24 \*/} \
> { \} fff1;} \
> @@ -161,6 +166,7 @@ gdb_test "ptype /o union qwe" \
> {/\* XXX 4-byte hole \*/} \
> {/\* 24 | 8 \*/ signed char \*a2;} \
> {/\* 32 | 4 \*/ int a3;} \
> +{/\* XXX 4-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 24 \*/} \
> { \} f4;} \
> @@ -184,6 +190,7 @@ gdb_test "ptype /o struct poi" \
> {/\* XXX 4-byte hole \*/} \
> {/\* 16 | 8 \*/ signed char \*a2;} \
> {/\* 24 | 4 \*/ int a3;} \
> +{/\* XXX 4-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 24 \*/} \
> { \} fff1;} \
> @@ -197,9 +204,11 @@ gdb_test "ptype /o struct poi" \
> {/\* XXX 4-byte hole \*/} \
> {/\* 32 | 8 \*/ signed char \*a2;} \
> {/\* 40 | 4 \*/ int a3;} \
> +{/\* XXX 4-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 24 \*/} \
> { \} f4;} \
> +{/\* XXX 32-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 40 \*/} \
> { \} fff2;} \
> @@ -221,6 +230,7 @@ gdb_test "ptype /o struct poi" \
> {/\* XXX 4-byte hole \*/} \
> {/\* 112 | 8 \*/ signed char \*a2;} \
> {/\* 120 | 4 \*/ int a3;} \
> +{/\* XXX 4-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 24 \*/} \
> { \} f4;} \
> @@ -228,6 +238,7 @@ gdb_test "ptype /o struct poi" \
> { /\* total size \(bytes\): 40 \*/} \
> { \} ff2;} \
> {/\* 152 | 1 \*/ signed char ff3;} \
> +{/\* XXX 7-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 56 \*/} \
> { \} f4;} \
> @@ -262,6 +273,7 @@ gdb_test "ptype /o struct tyu" \
> {/\* 8 | 8 \*/ int64_t a5;} \
> {/\* 16:27 | 4 \*/ int a6 : 5;} \
> {/\* 16:56 | 8 \*/ int64_t a7 : 3;} \
> +{/\* XXX 7-byte padding \*/} \
> {} \
> { /\* total size \(bytes\): 24 \*/} \
> { \}}]
> commit f4c9741648a991f4591b290000214a9dbaf8099a
> Author: Tom Tromey <tom@tromey.com>
> Date: Sat May 12 17:04:50 2018 -0600
>
> Show padding in ptype/o output
>
> I was recently using ptype/o to look at the layout of some objects in
> gdb. I noticed that trailing padding was not shown -- but I wanted to
> be able to look at that, too.
>
> This patch changes ptype/o to also print trailing holes.
>
> Tested on x86-64 Fedora 26.
>
> gdb/ChangeLog
> 2018-05-17 Tom Tromey <tom@tromey.com>
>
> * c-typeprint.c (maybe_print_hole): New function.
> (c_print_type_struct_field_offset): Update.
> (c_type_print_base_struct_union): Call maybe_print_hole.
>
> gdb/testsuite/ChangeLog
> 2018-05-17 Tom Tromey <tom@tromey.com>
>
> * gdb.base/ptype-offsets.exp: Update.
Looks good to me, Tom.
Thanks for this enhancement!
@@ -1,5 +1,11 @@
2018-05-17 Tom Tromey <tom@tromey.com>
+ * c-typeprint.c (maybe_print_hole): New function.
+ (c_print_type_struct_field_offset): Update.
+ (c_type_print_base_struct_union): Call maybe_print_hole.
+
+2018-05-17 Tom Tromey <tom@tromey.com>
+
* extension.h (struct ext_lang_type_printers) <py_type_printers>:
Initialize.
@@ -937,6 +937,42 @@ c_print_type_union_field_offset (struct type *type, unsigned int field_idx,
fprintf_filtered (stream, "/* %4u */", TYPE_LENGTH (ftype));
}
+/* Helper function for ptype/o implementation that prints information
+ about a hole, if necessary. STREAM is where to print. BITPOS is
+ the bitpos of the current field. PODATA is the offset-printing
+ state. FOR_WHAT is a string describing the purpose of the
+ hole. */
+
+static void
+maybe_print_hole (struct ui_file *stream, unsigned int bitpos,
+ struct print_offset_data *podata, const char *for_what)
+{
+ /* We check for PODATA->END_BITPOS > 0 because there is a specific
+ scenario when PODATA->END_BITPOS can be zero and BITPOS can be >
+ 0: when we are dealing with a struct/class with a virtual method.
+ Because of the vtable, the first field of the struct/class will
+ have an offset of sizeof (void *) (the size of the vtable). If
+ we do not check for PODATA->END_BITPOS > 0 here, GDB will report
+ a hole before the first field, which is not accurate. */
+ if (podata->end_bitpos > 0 && podata->end_bitpos < bitpos)
+ {
+ /* If PODATA->END_BITPOS is smaller than the current type's
+ bitpos, it means there's a hole in the struct, so we report
+ it here. */
+ unsigned int hole = bitpos - podata->end_bitpos;
+ unsigned int hole_byte = hole / TARGET_CHAR_BIT;
+ unsigned int hole_bit = hole % TARGET_CHAR_BIT;
+
+ if (hole_bit > 0)
+ fprintf_filtered (stream, "/* XXX %2u-bit %s */\n", hole_bit,
+ for_what);
+
+ if (hole_byte > 0)
+ fprintf_filtered (stream, "/* XXX %2u-byte %s */\n", hole_byte,
+ for_what);
+ }
+}
+
/* Print information about field at index FIELD_IDX of the struct type
TYPE.
@@ -963,28 +999,7 @@ c_print_type_struct_field_offset (struct type *type, unsigned int field_idx,
unsigned int fieldsize_byte = TYPE_LENGTH (ftype);
unsigned int fieldsize_bit = fieldsize_byte * TARGET_CHAR_BIT;
- /* We check for PODATA->END_BITPOS > 0 because there is a specific
- scenario when PODATA->END_BITPOS can be zero and BITPOS can be >
- 0: when we are dealing with a struct/class with a virtual method.
- Because of the vtable, the first field of the struct/class will
- have an offset of sizeof (void *) (the size of the vtable). If
- we do not check for PODATA->END_BITPOS > 0 here, GDB will report
- a hole before the first field, which is not accurate. */
- if (podata->end_bitpos > 0 && podata->end_bitpos < bitpos)
- {
- /* If PODATA->END_BITPOS is smaller than the current type's
- bitpos, it means there's a hole in the struct, so we report
- it here. */
- unsigned int hole = bitpos - podata->end_bitpos;
- unsigned int hole_byte = hole / TARGET_CHAR_BIT;
- unsigned int hole_bit = hole % TARGET_CHAR_BIT;
-
- if (hole_bit > 0)
- fprintf_filtered (stream, "/* XXX %2u-bit hole */\n", hole_bit);
-
- if (hole_byte > 0)
- fprintf_filtered (stream, "/* XXX %2u-byte hole */\n", hole_byte);
- }
+ maybe_print_hole (stream, bitpos, podata, "hole");
if (TYPE_FIELD_PACKED (type, field_idx))
{
@@ -1508,6 +1523,9 @@ c_type_print_base_struct_union (struct type *type, struct ui_file *stream,
{
if (show > 0)
{
+ unsigned int bitpos = TYPE_LENGTH (type) * TARGET_CHAR_BIT;
+ maybe_print_hole (stream, bitpos, podata, "padding");
+
fputs_filtered ("\n", stream);
print_spaces_filtered_with_print_options (level + 4,
stream,
@@ -1,3 +1,7 @@
+2018-05-17 Tom Tromey <tom@tromey.com>
+
+ * gdb.base/ptype-offsets.exp: Update.
+
2018-05-15 Maciej W. Rozycki <macro@mips.com>
* gdb.server/server-kill.exp: Verify whether `server_pid' exists
@@ -52,6 +52,7 @@ gdb_test "ptype /o struct abc" \
{ /\* total size \(bytes\): 8 \*/} \
{ \} field8;} \
{/\* 48 | 4 \*/ my_int_type field9;} \
+{/\* XXX 4-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 56 \*/} \
{ \}}]
@@ -81,6 +82,7 @@ gdb_test "ptype /oTM struct abc" \
{ ~abc\(\);} \
{} \
{ typedef int my_int_type;} \
+{/\* XXX 4-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 56 \*/} \
{ \}}]
@@ -105,6 +107,7 @@ gdb_test "ptype /TMo struct abc" \
{ /\* total size \(bytes\): 8 \*/} \
{ \} field8;} \
{/\* 48 | 4 \*/ my_int_type field9;} \
+{/\* XXX 4-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 56 \*/} \
{ \}}]
@@ -133,6 +136,7 @@ gdb_test "ptype /o struct pqr" \
{ \} ff2;} \
{/\* XXX 28-byte hole \*/} \
{/\* 72 | 1 \*/ signed char ff3;} \
+{/\* XXX 7-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 56 \*/} \
{ \}}]
@@ -148,6 +152,7 @@ gdb_test "ptype /o union qwe" \
{/\* XXX 4-byte hole \*/} \
{/\* 8 | 8 \*/ signed char \*a2;} \
{/\* 16 | 4 \*/ int a3;} \
+{/\* XXX 4-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 24 \*/} \
{ \} fff1;} \
@@ -161,6 +166,7 @@ gdb_test "ptype /o union qwe" \
{/\* XXX 4-byte hole \*/} \
{/\* 24 | 8 \*/ signed char \*a2;} \
{/\* 32 | 4 \*/ int a3;} \
+{/\* XXX 4-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 24 \*/} \
{ \} f4;} \
@@ -184,6 +190,7 @@ gdb_test "ptype /o struct poi" \
{/\* XXX 4-byte hole \*/} \
{/\* 16 | 8 \*/ signed char \*a2;} \
{/\* 24 | 4 \*/ int a3;} \
+{/\* XXX 4-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 24 \*/} \
{ \} fff1;} \
@@ -197,9 +204,11 @@ gdb_test "ptype /o struct poi" \
{/\* XXX 4-byte hole \*/} \
{/\* 32 | 8 \*/ signed char \*a2;} \
{/\* 40 | 4 \*/ int a3;} \
+{/\* XXX 4-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 24 \*/} \
{ \} f4;} \
+{/\* XXX 32-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 40 \*/} \
{ \} fff2;} \
@@ -221,6 +230,7 @@ gdb_test "ptype /o struct poi" \
{/\* XXX 4-byte hole \*/} \
{/\* 112 | 8 \*/ signed char \*a2;} \
{/\* 120 | 4 \*/ int a3;} \
+{/\* XXX 4-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 24 \*/} \
{ \} f4;} \
@@ -228,6 +238,7 @@ gdb_test "ptype /o struct poi" \
{ /\* total size \(bytes\): 40 \*/} \
{ \} ff2;} \
{/\* 152 | 1 \*/ signed char ff3;} \
+{/\* XXX 7-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 56 \*/} \
{ \} f4;} \
@@ -262,6 +273,7 @@ gdb_test "ptype /o struct tyu" \
{/\* 8 | 8 \*/ int64_t a5;} \
{/\* 16:27 | 4 \*/ int a6 : 5;} \
{/\* 16:56 | 8 \*/ int64_t a7 : 3;} \
+{/\* XXX 7-byte padding \*/} \
{} \
{ /\* total size \(bytes\): 24 \*/} \
{ \}}]