Share DLL code between gdb and gdbserver
[deliverable/binutils-gdb.git] / gdb / typeprint.c
index 87da8e3e932ad297bfad9cf632802ea5d8d37b6b..eb47d9129f9bd6bddd1c5961d1f353a13ca20b88 100644 (file)
@@ -1,6 +1,6 @@
 /* Language independent support for printing types for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2020 Free Software Foundation, Inc.
+   Copyright (C) 1986-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -44,6 +44,7 @@ const struct type_print_options type_print_raw_options =
   1,                           /* print_methods */
   1,                           /* print_typedefs */
   0,                           /* print_offsets */
+  0,                           /* print_in_hex */
   0,                           /* print_nested_type_limit  */
   NULL,                                /* local_typedefs */
   NULL,                                /* global_table */
@@ -58,6 +59,7 @@ static struct type_print_options default_ptype_flags =
   1,                           /* print_methods */
   1,                           /* print_typedefs */
   0,                           /* print_offsets */
+  0,                           /* print_in_hex */
   0,                           /* print_nested_type_limit  */
   NULL,                                /* local_typedefs */
   NULL,                                /* global_table */
@@ -68,8 +70,15 @@ static struct type_print_options default_ptype_flags =
 
 /* See typeprint.h.  */
 
-const int print_offset_data::indentation = 23;
+const int print_offset_data::indentation = 27;
 
+/* See typeprint.h.  */
+
+print_offset_data::print_offset_data (const struct type_print_options *flags)
+{
+  if (flags != nullptr)
+    print_in_hex = flags->print_in_hex;
+}
 
 /* See typeprint.h.  */
 
@@ -95,11 +104,11 @@ print_offset_data::maybe_print_hole (struct ui_file *stream,
       unsigned int hole_bit = hole % TARGET_CHAR_BIT;
 
       if (hole_bit > 0)
-       fprintf_filtered (stream, "/* XXX %2u-bit %s   */\n", hole_bit,
+       fprintf_filtered (stream, "/* XXX %2u-bit %-7s    */\n", hole_bit,
                          for_what);
 
       if (hole_byte > 0)
-       fprintf_filtered (stream, "/* XXX %2u-byte %s  */\n", hole_byte,
+       fprintf_filtered (stream, "/* XXX %2u-byte %-7s   */\n", hole_byte,
                          for_what);
     }
 }
@@ -110,19 +119,21 @@ void
 print_offset_data::update (struct type *type, unsigned int field_idx,
                           struct ui_file *stream)
 {
-  if (field_is_static (&TYPE_FIELD (type, field_idx)))
+  if (field_is_static (&type->field (field_idx)))
     {
       print_spaces_filtered (indentation, stream);
       return;
     }
 
-  struct type *ftype = check_typedef (TYPE_FIELD_TYPE (type, field_idx));
-  if (TYPE_CODE (type) == TYPE_CODE_UNION)
+  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.  */
-      fprintf_filtered (stream, "/*              %4s */",
-                       pulongest (TYPE_LENGTH (ftype)));
+      fprintf_filtered (stream, "/*                %6s */",
+                       (print_in_hex ?
+                        hex_string_custom (TYPE_LENGTH (ftype), 4) :
+                        pulongest (TYPE_LENGTH (ftype))));
       return;
     }
 
@@ -140,20 +151,23 @@ print_offset_data::update (struct type *type, unsigned int field_idx,
 
       unsigned real_bitpos = bitpos + offset_bitpos;
 
-      fprintf_filtered (stream, "/* %4u:%2u", real_bitpos / TARGET_CHAR_BIT,
+      fprintf_filtered (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.  */
-      fprintf_filtered (stream, "/* %4u",
+      fprintf_filtered (stream, (print_in_hex ?  "/* 0x%04x" : "/* %6u"),
                        (bitpos + offset_bitpos) / TARGET_CHAR_BIT);
 
-      fprintf_filtered (stream, "   ");
+      fprintf_filtered (stream, "     ");
     }
 
-  fprintf_filtered (stream, "   |  %4u */", fieldsize_byte);
+  fprintf_filtered (stream, (print_in_hex ? " |  0x%04x */" : " |  %6u */"),
+                   fieldsize_byte);
 
   end_bitpos = bitpos + fieldsize_bit;
 }
@@ -209,7 +223,7 @@ typedef_hash_table::recursively_update (struct type *t)
       struct decl_field *tdef = &TYPE_TYPEDEF_FIELD (t, i);
       void **slot;
 
-      slot = htab_find_slot (m_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.  */
@@ -242,7 +256,7 @@ typedef_hash_table::add_template_parameters (struct type *t)
       tf->name = TYPE_TEMPLATE_ARGUMENT (t, i)->linkage_name ();
       tf->type = SYMBOL_TYPE (TYPE_TEMPLATE_ARGUMENT (t, i));
 
-      slot = htab_find_slot (m_table, tf, INSERT);
+      slot = htab_find_slot (m_table.get (), tf, INSERT);
       if (*slot == NULL)
        *slot = tf;
     }
@@ -251,16 +265,9 @@ typedef_hash_table::add_template_parameters (struct type *t)
 /* See typeprint.h.  */
 
 typedef_hash_table::typedef_hash_table ()
+  : m_table (htab_create_alloc (10, hash_typedef_field, eq_typedef_field,
+                               NULL, xcalloc, xfree))
 {
-  m_table = htab_create_alloc (10, hash_typedef_field, eq_typedef_field,
-                              NULL, xcalloc, xfree);
-}
-
-/* Free a typedef field table.  */
-
-typedef_hash_table::~typedef_hash_table ()
-{
-  htab_delete (m_table);
 }
 
 /* Helper function for typedef_hash_table::copy.  */
@@ -282,10 +289,10 @@ copy_typedef_hash_element (void **slot, void *nt)
 
 typedef_hash_table::typedef_hash_table (const typedef_hash_table &table)
 {
-  m_table = htab_create_alloc (10, hash_typedef_field, eq_typedef_field,
-                              NULL, xcalloc, xfree);
-  htab_traverse_noresize (table.m_table, copy_typedef_hash_element,
-                         m_table);
+  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,
@@ -307,7 +314,7 @@ typedef_hash_table::find_global_typedef (const struct type_print_options *flags,
   tf.name = NULL;
   tf.type = t;
 
-  slot = htab_find_slot (flags->global_typedefs->m_table, &tf, INSERT);
+  slot = htab_find_slot (flags->global_typedefs->m_table.get (), &tf, INSERT);
   if (*slot != NULL)
     {
       new_tf = (struct decl_field *) *slot;
@@ -346,8 +353,8 @@ typedef_hash_table::find_typedef (const struct type_print_options *flags,
 
       tf.name = NULL;
       tf.type = t;
-      found = (struct decl_field *) htab_find (flags->local_typedefs->m_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;
@@ -365,16 +372,7 @@ typedef_hash_table::find_typedef (const struct type_print_options *flags,
 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
@@ -484,6 +482,12 @@ whatis_exp (const char *exp, int show)
                      }
                    break;
                  }
+               case 'x':
+                 flags.print_in_hex = 1;
+                 break;
+               case 'd':
+                 flags.print_in_hex = 0;
+                 break;
                default:
                  error (_("unrecognized flag '%c'"), *exp);
                }
@@ -506,30 +510,24 @@ 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);
 
          /* If the expression is actually a type, then there's no
             value to fetch the dynamic type from.  */
          val = NULL;
        }
-      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);
-       }
     }
   else
     {
@@ -540,17 +538,17 @@ whatis_exp (const char *exp, int show)
   get_user_print_options (&opts);
   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->code () == TYPE_CODE_PTR) || TYPE_IS_REFERENCE (type))
+         && (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);
     }
 
   if (flags.print_offsets
-      && (TYPE_CODE (type) == TYPE_CODE_STRUCT
-         || TYPE_CODE (type) == TYPE_CODE_UNION))
-    fprintf_filtered (gdb_stdout, "/* offset    |  size */  ");
+      && (type->code () == TYPE_CODE_STRUCT
+         || type->code () == TYPE_CODE_UNION))
+    fprintf_filtered (gdb_stdout, "/* offset      |    size */  ");
 
   printf_filtered ("type = ");
 
@@ -570,7 +568,7 @@ whatis_exp (const char *exp, int show)
       printf_filtered ("/* real type = ");
       type_print (real_type, "", gdb_stdout, -1);
       if (! full)
-        printf_filtered (" (incomplete object)");
+       printf_filtered (" (incomplete object)");
       printf_filtered (" */\n");    
     }
 
@@ -615,11 +613,11 @@ 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)
@@ -638,7 +636,7 @@ 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:
@@ -653,6 +651,10 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream)
       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:
@@ -678,6 +680,17 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *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 ();
+
+  fprintf_filtered (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.
    Uses the same sort of type lookup mechanism as ptype_command()
    and whatis_command().  */
@@ -685,28 +698,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);
     }
 }
 \f
@@ -784,6 +783,35 @@ show_print_type_nested_types  (struct ui_file *file, int from_tty,
     }
 }
 
+/* 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)
+{
+  fprintf_filtered (file, _("\
+Display of struct members offsets and sizes in hexadecimal is %s\n"),
+                   value);
+}
+
 void _initialize_typeprint ();
 void
 _initialize_typeprint ()
@@ -805,7 +833,11 @@ Available FLAGS are:\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\n\
-  /o    print offsets and sizes of fields in a struct (like pahole)"));
+  /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,
@@ -846,6 +878,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 <not allocated> status to stream STREAM.  */
This page took 0.030035 seconds and 4 git commands to generate.