X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Ftypeprint.c;h=3356bdde2e782bcf1551a39762b23625b1dcbbbd;hb=8c9ae6df3c244a7a738085ab461cb098df1d46f6;hp=9d9d6f5a49a8e7d5038dc0dba6223e8ced253b7c;hpb=883fd55ab1049333364479a7f5b0c7e61a310bac;p=binutils-gdb.git diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 9d9d6f5a49a..3356bdde2e7 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -1,6 +1,6 @@ /* Language independent support for printing types for GDB, the GNU debugger. - Copyright (C) 1986-2017 Free Software Foundation, Inc. + Copyright (C) 1986-2022 Free Software Foundation, Inc. This file is part of GDB. @@ -18,7 +18,7 @@ along with this program. If not, see . */ #include "defs.h" -#include "gdb_obstack.h" +#include "gdbsupport/gdb_obstack.h" #include "bfd.h" /* Binary File Description */ #include "symtab.h" #include "gdbtypes.h" @@ -36,12 +36,15 @@ #include "cli/cli-utils.h" #include "extension.h" #include "completer.h" +#include "cli/cli-style.h" const struct type_print_options type_print_raw_options = { 1, /* raw */ 1, /* print_methods */ 1, /* print_typedefs */ + 0, /* print_offsets */ + 0, /* print_in_hex */ 0, /* print_nested_type_limit */ NULL, /* local_typedefs */ NULL, /* global_table */ @@ -55,6 +58,8 @@ static struct type_print_options default_ptype_flags = 0, /* raw */ 1, /* print_methods */ 1, /* print_typedefs */ + 0, /* print_offsets */ + 0, /* print_in_hex */ 0, /* print_nested_type_limit */ NULL, /* local_typedefs */ NULL, /* global_table */ @@ -63,18 +68,132 @@ static struct type_print_options default_ptype_flags = -/* A hash table holding typedef_field objects. This is more - complicated than an ordinary hash because it must also track the - lifetime of some -- but not all -- of the contained objects. */ +/* See typeprint.h. */ + +const int print_offset_data::indentation = 27; -struct typedef_hash_table +/* See typeprint.h. */ + +print_offset_data::print_offset_data (const struct type_print_options *flags) { - /* The actual hash table. */ - htab_t table; + if (flags != nullptr) + print_in_hex = flags->print_in_hex; +} - /* Storage for typedef_field objects that must be synthesized. */ - struct obstack storage; -}; +/* 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))); +} + + /* A hash function for a typedef_field. */ @@ -82,9 +201,8 @@ static hashval_t hash_typedef_field (const void *p) { const struct decl_field *tf = (const struct decl_field *) p; - struct type *t = check_typedef (tf->type); - return htab_hash_string (TYPE_SAFE_NAME (t)); + return htab_hash_string (TYPE_SAFE_NAME (tf->type)); } /* An equality function for a typedef field. */ @@ -98,23 +216,19 @@ eq_typedef_field (const void *a, const void *b) return types_equal (tfa->type, tfb->type); } -/* Add typedefs from T to the hash table TABLE. */ +/* See typeprint.h. */ void -recursively_update_typedef_hash (struct typedef_hash_table *table, - struct type *t) +typedef_hash_table::recursively_update (struct type *t) { int i; - if (table == NULL) - return; - for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (t); ++i) { struct decl_field *tdef = &TYPE_TYPEDEF_FIELD (t, i); void **slot; - slot = htab_find_slot (table->table, tdef, INSERT); + slot = htab_find_slot (m_table.get (), tdef, INSERT); /* Only add a given typedef name once. Really this shouldn't happen; but it is safe enough to do the updates breadth-first and thus use the most specific typedef. */ @@ -124,83 +238,44 @@ recursively_update_typedef_hash (struct typedef_hash_table *table, /* Recurse into superclasses. */ for (i = 0; i < TYPE_N_BASECLASSES (t); ++i) - recursively_update_typedef_hash (table, TYPE_BASECLASS (t, i)); + recursively_update (TYPE_BASECLASS (t, i)); } -/* Add template parameters from T to the typedef hash TABLE. */ +/* See typeprint.h. */ void -add_template_parameters (struct typedef_hash_table *table, struct type *t) +typedef_hash_table::add_template_parameters (struct type *t) { int i; - if (table == NULL) - return; - for (i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (t); ++i) { struct decl_field *tf; void **slot; /* We only want type-valued template parameters in the hash. */ - if (SYMBOL_CLASS (TYPE_TEMPLATE_ARGUMENT (t, i)) != LOC_TYPEDEF) + if (TYPE_TEMPLATE_ARGUMENT (t, i)->aclass () != LOC_TYPEDEF) continue; - tf = XOBNEW (&table->storage, struct decl_field); - tf->name = SYMBOL_LINKAGE_NAME (TYPE_TEMPLATE_ARGUMENT (t, i)); - tf->type = SYMBOL_TYPE (TYPE_TEMPLATE_ARGUMENT (t, i)); + tf = XOBNEW (&m_storage, struct decl_field); + tf->name = TYPE_TEMPLATE_ARGUMENT (t, i)->linkage_name (); + tf->type = TYPE_TEMPLATE_ARGUMENT (t, i)->type (); - slot = htab_find_slot (table->table, tf, INSERT); + slot = htab_find_slot (m_table.get (), tf, INSERT); if (*slot == NULL) *slot = tf; } } -/* Create a new typedef-lookup hash table. */ - -struct typedef_hash_table * -create_typedef_hash (void) -{ - struct typedef_hash_table *result; - - result = XNEW (struct typedef_hash_table); - result->table = htab_create_alloc (10, hash_typedef_field, eq_typedef_field, - NULL, xcalloc, xfree); - obstack_init (&result->storage); - - return result; -} - -/* Free a typedef field table. */ - -void -free_typedef_hash (struct typedef_hash_table *table) -{ - if (table != NULL) - { - htab_delete (table->table); - obstack_free (&table->storage, NULL); - xfree (table); - } -} - -/* A cleanup for freeing a typedef_hash_table. */ - -static void -do_free_typedef_hash (void *arg) -{ - free_typedef_hash ((struct typedef_hash_table *) arg); -} - -/* Return a new cleanup that frees TABLE. */ +/* See typeprint.h. */ -struct cleanup * -make_cleanup_free_typedef_hash (struct typedef_hash_table *table) +typedef_hash_table::typedef_hash_table () + : m_table (htab_create_alloc (10, hash_typedef_field, eq_typedef_field, + NULL, xcalloc, xfree)) { - return make_cleanup (do_free_typedef_hash, table); } -/* Helper function for copy_typedef_hash. */ +/* Helper function for typedef_hash_table::copy. */ static int copy_typedef_hash_element (void **slot, void *nt) @@ -215,42 +290,14 @@ copy_typedef_hash_element (void **slot, void *nt) return 1; } -/* Copy a typedef hash. */ - -struct typedef_hash_table * -copy_typedef_hash (struct typedef_hash_table *table) -{ - struct typedef_hash_table *result; - - if (table == NULL) - return NULL; - - result = create_typedef_hash (); - htab_traverse_noresize (table->table, copy_typedef_hash_element, - result->table); - return result; -} - -/* A cleanup to free the global typedef hash. */ - -static void -do_free_global_table (void *arg) -{ - struct type_print_options *flags = (struct type_print_options *) arg; - - free_typedef_hash (flags->global_typedefs); - free_ext_lang_type_printers (flags->global_printers); -} - -/* Create the global typedef hash. */ +/* See typeprint.h. */ -static struct cleanup * -create_global_typedef_table (struct type_print_options *flags) +typedef_hash_table::typedef_hash_table (const typedef_hash_table &table) { - gdb_assert (flags->global_typedefs == NULL && flags->global_printers == NULL); - flags->global_typedefs = create_typedef_hash (); - flags->global_printers = start_ext_lang_type_printers (); - return make_cleanup (do_free_global_table, flags); + m_table.reset (htab_create_alloc (10, hash_typedef_field, eq_typedef_field, + NULL, xcalloc, xfree)); + htab_traverse_noresize (table.m_table.get (), copy_typedef_hash_element, + m_table.get ()); } /* Look up the type T in the global typedef hash. If it is found, @@ -258,9 +305,9 @@ create_global_typedef_table (struct type_print_options *flags) type-printers, if any, given by start_script_type_printers and return the result. A NULL return means that the name was not found. */ -static const char * -find_global_typedef (const struct type_print_options *flags, - struct type *t) +const char * +typedef_hash_table::find_global_typedef (const struct type_print_options *flags, + struct type *t) { char *applied; void **slot; @@ -272,7 +319,7 @@ find_global_typedef (const struct type_print_options *flags, tf.name = NULL; tf.type = t; - slot = htab_find_slot (flags->global_typedefs->table, &tf, INSERT); + slot = htab_find_slot (flags->global_typedefs->m_table.get (), &tf, INSERT); if (*slot != NULL) { new_tf = (struct decl_field *) *slot; @@ -281,7 +328,7 @@ find_global_typedef (const struct type_print_options *flags, /* Put an entry into the hash table now, in case apply_ext_lang_type_printers recurses. */ - new_tf = XOBNEW (&flags->global_typedefs->storage, struct decl_field); + new_tf = XOBNEW (&flags->global_typedefs->m_storage, struct decl_field); new_tf->name = NULL; new_tf->type = t; @@ -291,22 +338,19 @@ find_global_typedef (const struct type_print_options *flags, if (applied != NULL) { - new_tf->name - = (const char *) obstack_copy0 (&flags->global_typedefs->storage, - applied, strlen (applied)); + new_tf->name = obstack_strdup (&flags->global_typedefs->m_storage, + applied); xfree (applied); } return new_tf->name; } -/* Look up the type T in the typedef hash table in with FLAGS. If T - is in the table, return its short (class-relative) typedef name. - Otherwise return NULL. If the table is NULL, this always returns - NULL. */ +/* See typeprint.h. */ const char * -find_typedef_in_hash (const struct type_print_options *flags, struct type *t) +typedef_hash_table::find_typedef (const struct type_print_options *flags, + struct type *t) { if (flags->local_typedefs != NULL) { @@ -314,8 +358,8 @@ find_typedef_in_hash (const struct type_print_options *flags, struct type *t) tf.name = NULL; tf.type = t; - found = (struct decl_field *) htab_find (flags->local_typedefs->table, - &tf); + htab_t table = flags->local_typedefs->m_table.get (); + found = (struct decl_field *) htab_find (table, &tf); if (found != NULL) return found->name; @@ -333,16 +377,7 @@ find_typedef_in_hash (const struct type_print_options *flags, struct type *t) void typedef_print (struct type *type, struct symbol *newobj, struct ui_file *stream) { - LA_PRINT_TYPEDEF (type, newobj, stream); -} - -/* The default way to print a typedef. */ - -void -default_print_typedef (struct type *type, struct symbol *new_symbol, - struct ui_file *stream) -{ - error (_("Language not supported.")); + current_language->print_typedef (type, newobj, stream); } /* Print a description of a type TYPE in the form of a declaration of a @@ -356,7 +391,8 @@ void type_print (struct type *type, const char *varstring, struct ui_file *stream, int show) { - LA_PRINT_TYPE (type, varstring, stream, show, 0, &default_ptype_flags); + current_language->print_type (type, varstring, stream, show, 0, + &default_ptype_flags); } /* Print TYPE to a string, returning it. The caller is responsible for @@ -365,17 +401,16 @@ type_print (struct type *type, const char *varstring, struct ui_file *stream, std::string type_to_string (struct type *type) { - TRY + try { string_file stb; type_print (type, "", &stb, -1); - return std::move (stb.string ()); + return stb.release (); } - CATCH (except, RETURN_MASK_ALL) + catch (const gdb_exception &except) { } - END_CATCH return {}; } @@ -385,7 +420,8 @@ type_to_string (struct type *type) void type_print_unknown_return_type (struct ui_file *stream) { - fprintf_filtered (stream, _("")); + fprintf_styled (stream, metadata_style.style (), + _("")); } /* See typeprint.h. */ @@ -404,7 +440,6 @@ static void whatis_exp (const char *exp, int show) { struct value *val; - struct cleanup *old_chain; struct type *real_type = NULL; struct type *type; int full = 0; @@ -413,8 +448,6 @@ whatis_exp (const char *exp, int show) struct value_print_options opts; struct type_print_options flags = default_ptype_flags; - old_chain = make_cleanup (null_cleanup, NULL); - if (exp) { if (*exp == '/') @@ -440,6 +473,27 @@ whatis_exp (const char *exp, int show) case 'T': flags.print_typedefs = 1; break; + case 'o': + { + /* Filter out languages which don't implement the + feature. */ + if (show > 0 + && (current_language->la_language == language_c + || current_language->la_language == language_cplus + || current_language->la_language == language_rust)) + { + flags.print_offsets = 1; + flags.print_typedefs = 0; + flags.print_methods = 0; + } + break; + } + case 'x': + flags.print_in_hex = 1; + break; + case 'd': + flags.print_in_hex = 0; + break; default: error (_("unrecognized flag '%c'"), *exp); } @@ -462,25 +516,23 @@ whatis_exp (const char *exp, int show) "whatis" prints the type of the expression without stripping any typedef level. "ptype" always strips all levels of typedefs. */ - if (show == -1 && expr->elts[0].opcode == OP_TYPE) + val = evaluate_type (expr.get ()); + type = value_type (val); + + if (show == -1 && expr->first_opcode () == OP_TYPE) { /* The user expression names a type directly. */ - type = expr->elts[1].type; /* If this is a typedef, then find its immediate target. Use check_typedef to resolve stubs, but ignore its result because we do not want to dig past all typedefs. */ check_typedef (type); - if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) + if (type->code () == TYPE_CODE_TYPEDEF) type = TYPE_TARGET_TYPE (type); - } - else - { - /* The user expression names a type indirectly by naming an - object or expression of that type. Find that - indirectly-named type. */ - val = evaluate_type (expr.get ()); - type = value_type (val); + + /* If the expression is actually a type, then there's no + value to fetch the dynamic type from. */ + val = NULL; } } else @@ -490,33 +542,44 @@ whatis_exp (const char *exp, int show) } get_user_print_options (&opts); - if (opts.objectprint) + if (val != NULL && opts.objectprint) { - if (((TYPE_CODE (type) == TYPE_CODE_PTR) || TYPE_IS_REFERENCE (type)) - && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT)) - real_type = value_rtti_indirect_type (val, &full, &top, &using_enc); - else if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + if (type->is_pointer_or_reference () + && (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_STRUCT)) + real_type = value_rtti_indirect_type (val, &full, &top, &using_enc); + else if (type->code () == TYPE_CODE_STRUCT) real_type = value_rtti_type (val, &full, &top, &using_enc); } - printf_filtered ("type = "); + if (flags.print_offsets + && (type->code () == TYPE_CODE_STRUCT + || type->code () == TYPE_CODE_UNION)) + gdb_printf ("/* offset | size */ "); + + gdb_printf ("type = "); + std::unique_ptr table_holder; + std::unique_ptr printer_holder; if (!flags.raw) - create_global_typedef_table (&flags); + { + table_holder.reset (new typedef_hash_table); + flags.global_typedefs = table_holder.get (); + + printer_holder.reset (new ext_lang_type_printers); + flags.global_printers = printer_holder.get (); + } if (real_type) { - printf_filtered ("/* real type = "); + gdb_printf ("/* real type = "); type_print (real_type, "", gdb_stdout, -1); if (! full) - printf_filtered (" (incomplete object)"); - printf_filtered (" */\n"); + gdb_printf (" (incomplete object)"); + gdb_printf (" */\n"); } - LA_PRINT_TYPE (type, "", gdb_stdout, show, 0, &flags); - printf_filtered ("\n"); - - do_cleanups (old_chain); + current_language->print_type (type, "", gdb_stdout, show, 0, &flags); + gdb_printf ("\n"); } static void @@ -556,21 +619,21 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream) type = check_typedef (type); - switch (TYPE_CODE (type)) + switch (type->code ()) { case TYPE_CODE_ENUM: - len = TYPE_NFIELDS (type); + len = type->num_fields (); for (i = 0; i < len; i++) { - if (TYPE_FIELD_ENUMVAL (type, i) == val) + if (type->field (i).loc_enumval () == val) { break; } } if (i < len) { - fputs_filtered (TYPE_FIELD_NAME (type, i), stream); + gdb_puts (type->field (i).name (), stream); } else { @@ -579,21 +642,25 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream) break; case TYPE_CODE_INT: - print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0, val); + print_longest (stream, type->is_unsigned () ? 'u' : 'd', 0, val); break; case TYPE_CODE_CHAR: - LA_PRINT_CHAR ((unsigned char) val, type, stream); + current_language->printchar ((unsigned char) val, type, stream); break; case TYPE_CODE_BOOL: - fprintf_filtered (stream, val ? "TRUE" : "FALSE"); + gdb_printf (stream, val ? "TRUE" : "FALSE"); break; case TYPE_CODE_RANGE: print_type_scalar (TYPE_TARGET_TYPE (type), val, stream); return; + case TYPE_CODE_FIXED_POINT: + print_type_fixed_point (type, stream); + break; + case TYPE_CODE_UNDEF: case TYPE_CODE_PTR: case TYPE_CODE_ARRAY: @@ -617,7 +684,17 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream) default: error (_("Invalid type code in symbol table.")); } - gdb_flush (stream); +} + +/* See typeprint.h. */ + +void +print_type_fixed_point (struct type *type, struct ui_file *stream) +{ + std::string small_img = type->fixed_point_scaling_factor ().str (); + + gdb_printf (stream, "%s-byte fixed point (small = %s)", + pulongest (TYPE_LENGTH (type)), small_img.c_str ()); } /* Dump details of a type specified either directly or indirectly. @@ -627,28 +704,14 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream) void maintenance_print_type (const char *type_name, int from_tty) { - struct value *val; - struct type *type; - if (type_name != NULL) { expression_up expr = parse_expression (type_name); - if (expr->elts[0].opcode == OP_TYPE) - { - /* The user expression names a type directly, just use that type. */ - type = expr->elts[1].type; - } - else - { - /* The user expression may name a type indirectly by naming an - object of that type. Find that indirectly named type. */ - val = evaluate_type (expr.get ()); - type = value_type (val); - } - if (type != NULL) - { - recursive_dump_type (type, 0); - } + struct value *val = evaluate_type (expr.get ()); + struct type *type = value_type (val); + + if (type != nullptr) + recursive_dump_type (type, 0); } } @@ -657,21 +720,7 @@ struct cmd_list_element *setprinttypelist; struct cmd_list_element *showprinttypelist; -static void -set_print_type (const char *arg, int from_tty) -{ - printf_unfiltered ( - "\"set print type\" must be followed by the name of a subcommand.\n"); - help_list (setprintlist, "set print type ", all_commands, gdb_stdout); -} - -static void -show_print_type (const char *args, int from_tty) -{ - cmd_show_list (showprinttypelist, from_tty, ""); -} - -static int print_methods = 1; +static bool print_methods = true; static void set_print_type_methods (const char *args, @@ -684,11 +733,11 @@ static void show_print_type_methods (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("Printing of methods defined in a class in %s\n"), - value); + gdb_printf (file, _("Printing of methods defined in a class in %s\n"), + value); } -static int print_typedefs = 1; +static bool print_typedefs = true; static void set_print_type_typedefs (const char *args, @@ -701,8 +750,8 @@ static void show_print_type_typedefs (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("Printing of typedefs defined in a class in %s\n"), - value); + gdb_printf (file, _("Printing of typedefs defined in a class in %s\n"), + value); } /* Limit on the number of nested type definitions to print or -1 to print @@ -729,19 +778,49 @@ show_print_type_nested_types (struct ui_file *file, int from_tty, { if (*value == '0') { - fprintf_filtered (file, - _("Will not print nested types defined in a class\n")); + gdb_printf (file, + _("Will not print nested types defined in a class\n")); } else { - fprintf_filtered (file, - _("Will print %s nested types defined in a class\n"), - value); + gdb_printf (file, + _("Will print %s nested types defined in a class\n"), + value); } } +/* When printing structs, offsets and sizes of members can be displayed using + decimal notation or hexadecimal notation. By default, Decimal notation is + used. */ + +static bool print_offsets_and_sizes_in_hex = false; + +/* Set the flags that instructs if sizes and offsets of struct members are + displayed in hexadecimal or decimal notation. */ + +static void +set_print_offsets_and_sizes_in_hex (const char *args, + int from_tty, struct cmd_list_element *c) +{ + default_ptype_flags.print_in_hex = print_offsets_and_sizes_in_hex; +} + +/* Display whether struct members sizes and offsets are printed + using decimal or hexadecimal notation. */ + +static void +show_print_offsets_and_sizes_in_hex (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + gdb_printf (file, _("\ +Display of struct members offsets and sizes in hexadecimal is %s\n"), + value); +} + +void _initialize_typeprint (); void -_initialize_typeprint (void) +_initialize_typeprint () { struct cmd_list_element *c; @@ -759,7 +838,12 @@ Available FLAGS are:\n\ /m do not print methods defined in a class\n\ /M print methods defined in a class\n\ /t do not print typedefs defined in a class\n\ - /T print typedefs defined in a class")); + /T print typedefs defined in a class\n\ + /o print offsets and sizes of fields in a struct (like pahole)\n\ + /x use hexadecimal notation when displaying sizes and offsets\n\ + of struct members\n\ + /d use decimal notation when displaying sizes and offsets\n\ + of struct members ")); set_cmd_completer (c, expression_completer); c = add_com ("whatis", class_vars, whatis_command, @@ -767,12 +851,11 @@ Available FLAGS are:\n\ Only one level of typedefs is unrolled. See also \"ptype\".")); set_cmd_completer (c, expression_completer); - add_prefix_cmd ("type", no_class, show_print_type, - _("Generic command for showing type-printing settings."), - &showprinttypelist, "show print type ", 0, &showprintlist); - add_prefix_cmd ("type", no_class, set_print_type, - _("Generic command for setting how types print."), - &setprinttypelist, "show print type ", 0, &setprintlist); + add_setshow_prefix_cmd ("type", no_class, + _("Generic command for showing type-printing settings."), + _("Generic command for setting how types print."), + &setprinttypelist, &showprinttypelist, + &setprintlist, &showprintlist); add_setshow_boolean_cmd ("methods", no_class, &print_methods, _("\ @@ -798,6 +881,14 @@ Show the number of recursive nested type definitions to print."), NULL, set_print_type_nested_types, show_print_type_nested_types, &setprinttypelist, &showprinttypelist); + + add_setshow_boolean_cmd ("hex", no_class, &print_offsets_and_sizes_in_hex, + _("\ +Set printing of struct members sizes and offsets using hex notation."), _("\ +Show whether sizes and offsets of struct members are printed using hex \ +notation."), nullptr, set_print_offsets_and_sizes_in_hex, + show_print_offsets_and_sizes_in_hex, + &setprinttypelist, &showprinttypelist); } /* Print status to stream STREAM. */ @@ -805,7 +896,7 @@ Show the number of recursive nested type definitions to print."), NULL, void val_print_not_allocated (struct ui_file *stream) { - fprintf_filtered (stream, _("")); + fprintf_styled (stream, metadata_style.style (), _("")); } /* Print status to stream STREAM. */ @@ -813,5 +904,5 @@ val_print_not_allocated (struct ui_file *stream) void val_print_not_associated (struct ui_file *stream) { - fprintf_filtered (stream, _("")); + fprintf_styled (stream, metadata_style.style (), _("")); }