+/* See typeprint.h. */
+
+void
+print_offset_data::maybe_print_hole (struct ui_file *stream,
+ unsigned int bitpos,
+ const char *for_what)
+{
+ /* We check for END_BITPOS > 0 because there is a specific
+ scenario when 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 END_BITPOS > 0 here, GDB will report
+ a hole before the first field, which is not accurate. */
+ if (end_bitpos > 0 && end_bitpos < bitpos)
+ {
+ /* If 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 - end_bitpos;
+ unsigned int hole_byte = hole / TARGET_CHAR_BIT;
+ unsigned int hole_bit = hole % TARGET_CHAR_BIT;
+
+ if (hole_bit > 0)
+ {
+ fprintf_styled (stream, highlight_style.style (),
+ "/* XXX %2u-bit %-7s */", hole_bit, for_what);
+ gdb_puts ("\n", stream);
+ }
+
+ if (hole_byte > 0)
+ {
+ fprintf_styled (stream, highlight_style.style (),
+ "/* XXX %2u-byte %-7s */", hole_byte, for_what);
+ gdb_puts ("\n", stream);
+ }
+ }
+}
+
+/* See typeprint.h. */
+
+void
+print_offset_data::update (struct type *type, unsigned int field_idx,
+ struct ui_file *stream)
+{
+ if (field_is_static (&type->field (field_idx)))
+ {
+ print_spaces (indentation, stream);
+ return;
+ }
+
+ struct type *ftype = check_typedef (type->field (field_idx).type ());
+ if (type->code () == TYPE_CODE_UNION)
+ {
+ /* Since union fields don't have the concept of offsets, we just
+ print their sizes. */
+ gdb_printf (stream, "/* %6s */",
+ (print_in_hex ?
+ hex_string_custom (TYPE_LENGTH (ftype), 4) :
+ pulongest (TYPE_LENGTH (ftype))));
+ return;
+ }
+
+ unsigned int bitpos = type->field (field_idx).loc_bitpos ();
+ unsigned int fieldsize_byte = TYPE_LENGTH (ftype);
+ unsigned int fieldsize_bit = fieldsize_byte * TARGET_CHAR_BIT;
+
+ maybe_print_hole (stream, bitpos, "hole");
+
+ if (TYPE_FIELD_PACKED (type, field_idx)
+ || offset_bitpos % TARGET_CHAR_BIT != 0)
+ {
+ /* We're dealing with a bitfield. Print the bit offset. */
+ fieldsize_bit = TYPE_FIELD_BITSIZE (type, field_idx);
+
+ unsigned real_bitpos = bitpos + offset_bitpos;
+
+ gdb_printf (stream,
+ (print_in_hex ? "/* 0x%04x: 0x%x" : "/* %6u:%2u "),
+ real_bitpos / TARGET_CHAR_BIT,
+ real_bitpos % TARGET_CHAR_BIT);
+ }
+ else
+ {
+ /* The position of the field, relative to the beginning of the
+ struct. */
+ gdb_printf (stream, (print_in_hex ? "/* 0x%04x" : "/* %6u"),
+ (bitpos + offset_bitpos) / TARGET_CHAR_BIT);
+
+ gdb_printf (stream, " ");
+ }
+
+ gdb_printf (stream, (print_in_hex ? " | 0x%04x */" : " | %6u */"),
+ fieldsize_byte);
+
+ end_bitpos = bitpos + fieldsize_bit;
+}
+
+/* See typeprint.h. */
+
+void
+print_offset_data::finish (struct type *type, int level,
+ struct ui_file *stream)
+{
+ unsigned int bitpos = TYPE_LENGTH (type) * TARGET_CHAR_BIT;
+ maybe_print_hole (stream, bitpos, "padding");
+
+ gdb_puts ("\n", stream);
+ print_spaces (level + 4 + print_offset_data::indentation, stream);
+ gdb_printf (stream, "/* total size (bytes): %4s */\n",
+ pulongest (TYPE_LENGTH (type)));
+}
+
+\f