[RFC, patch] ptype bitfields show bitpos and bitsize

Leutwein Tobias (BEG-PT/ESB1) Tobias.Leutwein@de.bosch.com
Wed Jan 25 11:22:00 GMT 2012


Hello,

I have made some changes to the GDB sources to get more information's about bitfield variables through the ptype command.

Example (at gdb sources root directory):

gcc -g ./gdb/testsuite/gdb.base/bitfields.c -o ./zzz

gdb/gdb zzz

(gdb) ptype flags
type = struct fields {
    unsigned char uc;
    int s1 : 1;
    unsigned int u1 : 1;
    int s2 : 2;
    unsigned int u2 : 2;
    int s3 : 3;
    unsigned int u3 : 3;
    int s9 : 9;
    unsigned int u9 : 9;
    signed char sc;
}

(gdb) ptype flags.s9
type = int, bitpos = 20, bitsize = 9

(gdb) ptype flags.u9
type = unsigned int, bitsize = 9

(gdb) ptype flags.uc
type = unsigned char


At the code I have added a new object la_print_type_through_value  to the struct language_defn at file language.h. Maybe it would also be possible to change la_print_type, so that it's doing the same.

Because this is my first request of change, I don't know if I do it the right way.

If the changes are ok, is it possible that someone checks it in?

Regards
Tobias




diff -ur 7.4_orig/gdb/ada-lang.c 7.4_ptype/gdb/ada-lang.c
--- 7.4_orig/gdb/ada-lang.c     2012-01-06 04:34:45.000000000 +0100
+++ 7.4_ptype/gdb/ada-lang.c    2012-01-24 17:26:54.080750700 +0100
@@ -12337,6 +12337,7 @@
   ada_printstr,                 /* Function to print string constant */
   emit_char,                    /* Function to print single char (not used) */
   ada_print_type,               /* Print a type using appropriate syntax */
+  ada_print_type_through_value, /* Print a type using appropriate syntax */
   ada_print_typedef,            /* Print a typedef using appropriate syntax */
   ada_val_print,                /* Print a value using appropriate syntax */
   ada_value_print,              /* Print a top-level value */
diff -ur 7.4_orig/gdb/ada-lang.h 7.4_ptype/gdb/ada-lang.h
--- 7.4_orig/gdb/ada-lang.h     2012-01-04 09:16:55.000000000 +0100
+++ 7.4_ptype/gdb/ada-lang.h    2012-01-25 07:55:58.546684800 +0100
@@ -160,6 +160,8 @@
                         /* Defined in ada-typeprint.c */
 extern void ada_print_type (struct type *, const char *, struct ui_file *, int,
                             int);
+extern void ada_print_type_through_value (struct value *, const char *, struct ui_file *, int,
+                            int);

 extern void ada_print_typedef (struct type *type, struct symbol *new_symbol,
                               struct ui_file *stream);
diff -ur 7.4_orig/gdb/ada-typeprint.c 7.4_ptype/gdb/ada-typeprint.c
--- 7.4_orig/gdb/ada-typeprint.c        2012-01-04 09:16:55.000000000 +0100
+++ 7.4_ptype/gdb/ada-typeprint.c       2012-01-25 07:56:28.999809800 +0100
@@ -871,3 +871,25 @@
   ada_print_type (type, "", stream, 0, 0);
   fprintf_filtered (stream, "\n");
 }
+
+
+/* Print a description of a value value_p.
+   Output goes to STREAM (via stdio).
+   If VARSTRING is a non-empty string, print as an Ada variable/field
+       declaration.
+   SHOW+1 is the maximum number of levels of internal type structure
+      to show (this applies to record types, enumerated types, and
+      array types).
+   SHOW is the number of levels of internal type structure to show
+      when there is a type name for the SHOWth deepest level (0th is
+      outer level).
+   When SHOW<0, no inner structure is shown.
+   LEVEL indicates level of recursion (for nested definitions).  */
+
+void
+ada_print_type_through_value (struct value *value_p, const char *varstring, struct ui_file *stream,
+               int show, int level)
+{
+       struct type *type_p = value_type(value_p);
+       ada_print_type(type_p, varstring, stream, show, level);
+}
diff -ur 7.4_orig/gdb/c-lang.c 7.4_ptype/gdb/c-lang.c
--- 7.4_orig/gdb/c-lang.c       2012-01-04 09:16:59.000000000 +0100
+++ 7.4_ptype/gdb/c-lang.c      2012-01-25 07:51:37.249809800 +0100
@@ -844,6 +844,7 @@
   c_printstr,                  /* Function to print string constant */
   c_emit_char,                 /* Print a single char */
   c_print_type,                        /* Print a type using appropriate syntax */
+  c_print_type_through_value,                  /* Print a type using appropriate syntax */
   c_print_typedef,             /* Print a typedef using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
@@ -967,6 +968,7 @@
   c_printstr,                  /* Function to print string constant */
   c_emit_char,                 /* Print a single char */
   c_print_type,                        /* Print a type using appropriate syntax */
+  c_print_type_through_value,                  /* Print a type using appropriate syntax */
   c_print_typedef,             /* Print a typedef using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
@@ -1008,6 +1010,7 @@
   c_printstr,                  /* Function to print string constant */
   c_emit_char,                 /* Print a single char */
   c_print_type,                        /* Print a type using appropriate syntax */
+  c_print_type_through_value,                  /* Print a type using appropriate syntax */
   c_print_typedef,             /* Print a typedef using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
@@ -1054,6 +1057,7 @@
   c_printstr,                  /* Function to print string constant */
   c_emit_char,                 /* Print a single char */
   c_print_type,                        /* Print a type using appropriate syntax */
+  c_print_type_through_value,                  /* Print a type using appropriate syntax */
   c_print_typedef,             /* Print a typedef using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
diff -ur 7.4_orig/gdb/c-lang.h 7.4_ptype/gdb/c-lang.h
--- 7.4_orig/gdb/c-lang.h       2012-01-04 09:17:00.000000000 +0100
+++ 7.4_ptype/gdb/c-lang.h      2012-01-25 07:42:25.687309800 +0100
@@ -66,6 +66,8 @@
 /* Defined in c-typeprint.c */
 extern void c_print_type (struct type *, const char *,
                          struct ui_file *, int, int);
+extern void c_print_type_through_value (struct value *,
+              const char *, struct ui_file *, int, int);

 extern void c_print_typedef (struct type *,
                             struct symbol *,
@@ -111,6 +113,8 @@

 extern void c_type_print_base (struct type *, struct ui_file *,
                               int, int);
+extern void c_type_print_base_through_value (struct value *,
+                       struct ui_file *, int, int);

 /* These are in cp-valprint.c */

diff -ur 7.4_orig/gdb/c-typeprint.c 7.4_ptype/gdb/c-typeprint.c
--- 7.4_orig/gdb/c-typeprint.c  2012-01-04 09:17:00.000000000 +0100
+++ 7.4_ptype/gdb/c-typeprint.c 2012-01-25 09:44:15.140434800 +0100
@@ -88,6 +88,56 @@
     }
 }

+
+/* Same as function as above, the only difference is, that "struct value"
+   instead of "struct type" is used. Through this change it is possible to show
+   the position and size of bitfield variables.
+
+   \param[in]  level    The depth to indent lines by.
+*/
+void
+c_print_type_through_value (struct value *value, const char *varstring, struct ui_file *stream,
+             int show, int level)
+{
+  enum type_code code;
+  int demangled_args;
+  int need_post_space;
+
+  struct type *type = value_type (value);
+
+  if (show > 0)
+    CHECK_TYPEDEF (type);
+
+  c_type_print_base_through_value (value, stream, show, level);
+  code = TYPE_CODE (type);
+  if ((varstring != NULL && *varstring != '\0')
+  /* Need a space if going to print stars or brackets;
+     but not if we will print just a type name.  */
+      || ((show > 0 || TYPE_NAME (type) == 0)
+         && (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
+       || code == TYPE_CODE_METHOD
+       || code == TYPE_CODE_ARRAY
+       || code == TYPE_CODE_MEMBERPTR
+       || code == TYPE_CODE_METHODPTR
+       || code == TYPE_CODE_REF)))
+    fputs_filtered (" ", stream);
+  need_post_space = (varstring != NULL && strcmp (varstring, "") != 0);
+  c_type_print_varspec_prefix (type, stream, show, 0, need_post_space);
+
+  if (varstring != NULL)
+    {
+      fputs_filtered (varstring, stream);
+
+      /* For demangled function names, we have the arglist as part of
+         the name, so don't print an additional pair of ()'s.  */
+
+      demangled_args = strchr (varstring, '(') != NULL;
+      c_type_print_varspec_suffix (type, stream, show,
+                                  0, demangled_args);
+    }
+}
+
+
 /* Print a typedef using C syntax.  TYPE is the underlying type.
    NEW_SYMBOL is the symbol naming the type.  STREAM is the stream on
    which to print.  */
@@ -1258,3 +1308,593 @@
       break;
     }
 }
+
+
+/* Print the name of the type (or the ultimate pointer target,
+   function value or array element), or the description of a
+   structure or union.
+
+   SHOW positive means print details about the type (e.g. enum values),
+   and print structure elements passing SHOW - 1 for show.
+   SHOW negative means just print the type name or struct tag if there is one.
+   If there is no name, print something sensible but concise like
+   "struct {...}".
+   SHOW zero means just print the type name or struct tag if there is one.
+   If there is no name, print something sensible but not as concise like
+   "struct {int x; int y;}".
+
+   LEVEL is the number of spaces to indent by.
+   We increase it for some recursive calls.
+
+   \remarks Like c_type_print_base but if it is a bitfield variable, the
+   position and size will be shown if is not equal to 0.
+*/
+void
+c_type_print_base_through_value (struct value *value, struct ui_file *stream, int show,
+                  int level)
+{
+  int i;
+  int len, real_len;
+  int lastval;
+  char *mangled_name;
+  char *demangled_name;
+  char *demangled_no_static;
+  enum
+    {
+      s_none, s_public, s_private, s_protected
+    }
+  section_type;
+  int need_access_label = 0;
+  int j, len2;
+
+  struct type *type = value_type (value);
+
+  QUIT;
+
+  wrap_here ("    ");
+  if (type == NULL)
+    {
+      fputs_filtered (_("<type unknown>"), stream);
+      return;
+    }
+
+  /* When SHOW is zero or less, and there is a valid type name, then
+     always just print the type name directly from the type.  */
+  /* If we have "typedef struct foo {. . .} bar;" do we want to print
+     it as "struct foo" or as "bar"?  Pick the latter, because C++
+     folk tend to expect things like "class5 *foo" rather than "struct
+     class5 *foo".  */
+
+  if (show <= 0
+      && TYPE_NAME (type) != NULL)
+    {
+      c_type_print_modifier (type, stream, 0, 1);
+//fprintf_filtered (stream, "Lw %s,%i 0x%x ", __FILE__, __LINE__, type);
+         fputs_filtered (TYPE_NAME (type), stream);
+      return;
+    }
+
+  CHECK_TYPEDEF (type);
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_TYPEDEF:
+      /* If we get here, the typedef doesn't have a name, and we
+        couldn't resolve TYPE_TARGET_TYPE.  Not much we can do.  */
+      gdb_assert (TYPE_NAME (type) == NULL);
+      gdb_assert (TYPE_TARGET_TYPE (type) == NULL);
+      fprintf_filtered (stream, _("<unnamed typedef>"));
+      break;
+
+    case TYPE_CODE_ARRAY:
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_MEMBERPTR:
+    case TYPE_CODE_REF:
+    case TYPE_CODE_FUNC:
+    case TYPE_CODE_METHOD:
+    case TYPE_CODE_METHODPTR:
+      c_type_print_base (TYPE_TARGET_TYPE (type),
+                        stream, show, level);
+      break;
+
+    case TYPE_CODE_STRUCT:
+      c_type_print_modifier (type, stream, 0, 1);
+      if (TYPE_DECLARED_CLASS (type))
+       fprintf_filtered (stream, "class ");
+      else
+       fprintf_filtered (stream, "struct ");
+      goto struct_union;
+
+    case TYPE_CODE_UNION:
+      c_type_print_modifier (type, stream, 0, 1);
+      fprintf_filtered (stream, "union ");
+
+    struct_union:
+
+      /* Print the tag if it exists.  The HP aCC compiler emits a
+         spurious "{unnamed struct}"/"{unnamed union}"/"{unnamed
+         enum}" tag for unnamed struct/union/enum's, which we don't
+         want to print.  */
+      if (TYPE_TAG_NAME (type) != NULL
+         && strncmp (TYPE_TAG_NAME (type), "{unnamed", 8))
+       {
+         fputs_filtered (TYPE_TAG_NAME (type), stream);
+         if (show > 0)
+           fputs_filtered (" ", stream);
+       }
+      wrap_here ("    ");
+      if (show < 0)
+       {
+         /* If we just printed a tag name, no need to print anything
+            else.  */
+         if (TYPE_TAG_NAME (type) == NULL)
+           fprintf_filtered (stream, "{...}");
+       }
+      else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
+       {
+         struct type *basetype;
+         int vptr_fieldno;
+
+         cp_type_print_derivation_info (stream, type);
+
+         fprintf_filtered (stream, "{\n");
+         if (TYPE_NFIELDS (type) == 0 && TYPE_NFN_FIELDS (type) == 0
+             && TYPE_TYPEDEF_FIELD_COUNT (type) == 0)
+           {
+             if (TYPE_STUB (type))
+               fprintfi_filtered (level + 4, stream,
+                                  _("<incomplete type>\n"));
+             else
+               fprintfi_filtered (level + 4, stream,
+                                  _("<no data fields>\n"));
+           }
+
+         /* Start off with no specific section type, so we can print
+            one for the first field we find, and use that section type
+            thereafter until we find another type.  */
+
+         section_type = s_none;
+
+         /* For a class, if all members are private, there's no need
+            for a "private:" label; similarly, for a struct or union
+            masquerading as a class, if all members are public, there's
+            no need for a "public:" label.  */
+
+         if (TYPE_DECLARED_CLASS (type))
+           {
+             QUIT;
+             len = TYPE_NFIELDS (type);
+             for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+               if (!TYPE_FIELD_PRIVATE (type, i))
+                 {
+                   need_access_label = 1;
+                   break;
+                 }
+             QUIT;
+             if (!need_access_label)
+               {
+                 len2 = TYPE_NFN_FIELDS (type);
+                 for (j = 0; j < len2; j++)
+                   {
+                     len = TYPE_FN_FIELDLIST_LENGTH (type, j);
+                     for (i = 0; i < len; i++)
+                       if (!TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type,
+                                                                       j), i))
+                         {
+                           need_access_label = 1;
+                           break;
+                         }
+                     if (need_access_label)
+                       break;
+                   }
+               }
+           }
+         else
+           {
+             QUIT;
+             len = TYPE_NFIELDS (type);
+             for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+               if (TYPE_FIELD_PRIVATE (type, i)
+                   || TYPE_FIELD_PROTECTED (type, i))
+                 {
+                   need_access_label = 1;
+                   break;
+                 }
+             QUIT;
+             if (!need_access_label)
+               {
+                 len2 = TYPE_NFN_FIELDS (type);
+                 for (j = 0; j < len2; j++)
+                   {
+                     QUIT;
+                     len = TYPE_FN_FIELDLIST_LENGTH (type, j);
+                     for (i = 0; i < len; i++)
+                       if (TYPE_FN_FIELD_PROTECTED (TYPE_FN_FIELDLIST1 (type,
+                                                                        j), i)
+                           || TYPE_FN_FIELD_PRIVATE (TYPE_FN_FIELDLIST1 (type,
+                                                                         j),
+                                                     i))
+                         {
+                           need_access_label = 1;
+                           break;
+                         }
+                     if (need_access_label)
+                       break;
+                   }
+               }
+           }
+
+         /* If there is a base class for this type,
+            do not print the field that it occupies.  */
+
+         len = TYPE_NFIELDS (type);
+         vptr_fieldno = get_vptr_fieldno (type, &basetype);
+         for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+           {
+             QUIT;
+
+             /* If we have a virtual table pointer, omit it.  Even if
+                virtual table pointers are not specifically marked in
+                the debug info, they should be artificial.  */
+             if ((i == vptr_fieldno && type == basetype)
+                 || TYPE_FIELD_ARTIFICIAL (type, i))
+               continue;
+
+             if (need_access_label)
+               {
+                 if (TYPE_FIELD_PROTECTED (type, i))
+                   {
+                     if (section_type != s_protected)
+                       {
+                         section_type = s_protected;
+                         fprintfi_filtered (level + 2, stream,
+                                            "protected:\n");
+                       }
+                   }
+                 else if (TYPE_FIELD_PRIVATE (type, i))
+                   {
+                     if (section_type != s_private)
+                       {
+                         section_type = s_private;
+                         fprintfi_filtered (level + 2, stream,
+                                            "private:\n");
+                       }
+                   }
+                 else
+                   {
+                     if (section_type != s_public)
+                       {
+                         section_type = s_public;
+                         fprintfi_filtered (level + 2, stream,
+                                            "public:\n");
+                       }
+                   }
+               }
+
+             print_spaces_filtered (level + 4, stream);
+             if (field_is_static (&TYPE_FIELD (type, i)))
+               fprintf_filtered (stream, "static ");
+             c_print_type (TYPE_FIELD_TYPE (type, i),
+                           TYPE_FIELD_NAME (type, i),
+                           stream, show - 1, level + 4);
+             if (!field_is_static (&TYPE_FIELD (type, i))
+                 && TYPE_FIELD_PACKED (type, i))
+               {
+                 /* It is a bitfield.  This code does not attempt
+                    to look at the bitpos and reconstruct filler,
+                    unnamed fields.  This would lead to misleading
+                    results if the compiler does not put out fields
+                    for such things (I don't know what it does).  */
+                 fprintf_filtered (stream, " : %d",
+                                   TYPE_FIELD_BITSIZE (type, i));
+               }
+             fprintf_filtered (stream, ";\n");
+           }
+
+         /* If there are both fields and methods, put a blank line
+            between them.  Make sure to count only method that we
+            will display; artificial methods will be hidden.  */
+         len = TYPE_NFN_FIELDS (type);
+         real_len = 0;
+         for (i = 0; i < len; i++)
+           {
+             struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+             int len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
+             int j;
+
+             for (j = 0; j < len2; j++)
+               if (!TYPE_FN_FIELD_ARTIFICIAL (f, j))
+                 real_len++;
+           }
+         if (real_len > 0 && section_type != s_none)
+           fprintf_filtered (stream, "\n");
+
+         /* C++: print out the methods.  */
+         for (i = 0; i < len; i++)
+           {
+             struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+             int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
+             char *method_name = TYPE_FN_FIELDLIST_NAME (type, i);
+             char *name = type_name_no_tag (type);
+             int is_constructor = name && strcmp (method_name,
+                                                  name) == 0;
+
+             for (j = 0; j < len2; j++)
+               {
+                 const char *mangled_name;
+                 char *demangled_name;
+                 struct cleanup *inner_cleanup;
+                 const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
+                 int is_full_physname_constructor =
+                   is_constructor_name (physname)
+                   || is_destructor_name (physname)
+                   || method_name[0] == '~';
+
+                 /* Do not print out artificial methods.  */
+                 if (TYPE_FN_FIELD_ARTIFICIAL (f, j))
+                   continue;
+
+                 inner_cleanup = make_cleanup (null_cleanup, NULL);
+
+                 QUIT;
+                 if (TYPE_FN_FIELD_PROTECTED (f, j))
+                   {
+                     if (section_type != s_protected)
+                       {
+                         section_type = s_protected;
+                         fprintfi_filtered (level + 2, stream,
+                                            "protected:\n");
+                       }
+                   }
+                 else if (TYPE_FN_FIELD_PRIVATE (f, j))
+                   {
+                     if (section_type != s_private)
+                       {
+                         section_type = s_private;
+                         fprintfi_filtered (level + 2, stream,
+                                            "private:\n");
+                       }
+                   }
+                 else
+                   {
+                     if (section_type != s_public)
+                       {
+                         section_type = s_public;
+                         fprintfi_filtered (level + 2, stream,
+                                            "public:\n");
+                       }
+                   }
+
+                 print_spaces_filtered (level + 4, stream);
+                 if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+                   fprintf_filtered (stream, "virtual ");
+                 else if (TYPE_FN_FIELD_STATIC_P (f, j))
+                   fprintf_filtered (stream, "static ");
+                 if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0)
+                   {
+                     /* Keep GDB from crashing here.  */
+                     fprintf_filtered (stream,
+                                       _("<undefined type> %s;\n"),
+                                       TYPE_FN_FIELD_PHYSNAME (f, j));
+                     break;
+                   }
+                 else if (!is_constructor      /* Constructors don't
+                                                  have declared
+                                                  types.  */
+                          && !is_full_physname_constructor  /* " " */
+                          && !is_type_conversion_operator (type, i, j))
+                   {
+                     type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
+                                 "", stream, -1);
+                     fputs_filtered (" ", stream);
+                   }
+                 if (TYPE_FN_FIELD_STUB (f, j))
+                   {
+                     char *tem;
+
+                     /* Build something we can demangle.  */
+                     tem = gdb_mangle_name (type, i, j);
+                     make_cleanup (xfree, tem);
+                     mangled_name = tem;
+                   }
+                 else
+                   mangled_name = TYPE_FN_FIELD_PHYSNAME (f, j);
+
+                 demangled_name =
+                   cplus_demangle (mangled_name,
+                                   DMGL_ANSI | DMGL_PARAMS);
+                 if (demangled_name == NULL)
+                   {
+                     /* In some cases (for instance with the HP
+                        demangling), if a function has more than 10
+                        arguments, the demangling will fail.
+                        Let's try to reconstruct the function
+                        signature from the symbol information.  */
+                     if (!TYPE_FN_FIELD_STUB (f, j))
+                       {
+                         int staticp = TYPE_FN_FIELD_STATIC_P (f, j);
+                         struct type *mtype = TYPE_FN_FIELD_TYPE (f, j);
+
+                         cp_type_print_method_args (mtype,
+                                                    "",
+                                                    method_name,
+                                                    staticp,
+                                                    stream);
+                       }
+                     else
+                       fprintf_filtered (stream,
+                                         _("<badly mangled name '%s'>"),
+                                         mangled_name);
+                   }
+                 else
+                   {
+                     char *p;
+                     char *demangled_no_class
+                       = remove_qualifiers (demangled_name);
+
+                     /* Get rid of the `static' appended by the
+                        demangler.  */
+                     p = strstr (demangled_no_class, " static");
+                     if (p != NULL)
+                       {
+                         int length = p - demangled_no_class;
+                         char *demangled_no_static;
+
+                         demangled_no_static
+                           = (char *) xmalloc (length + 1);
+                         strncpy (demangled_no_static,
+                                  demangled_no_class, length);
+                         *(demangled_no_static + length) = '\0';
+                         fputs_filtered (demangled_no_static, stream);
+                         xfree (demangled_no_static);
+                       }
+                     else
+                       fputs_filtered (demangled_no_class, stream);
+                     xfree (demangled_name);
+                   }
+
+                 do_cleanups (inner_cleanup);
+
+                 fprintf_filtered (stream, ";\n");
+               }
+           }
+
+         /* Print typedefs defined in this class.  */
+
+         if (TYPE_TYPEDEF_FIELD_COUNT (type) != 0)
+           {
+             if (TYPE_NFIELDS (type) != 0 || TYPE_NFN_FIELDS (type) != 0)
+               fprintf_filtered (stream, "\n");
+
+             for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); i++)
+               {
+                 struct type *target = TYPE_TYPEDEF_FIELD_TYPE (type, i);
+
+                 /* Dereference the typedef declaration itself.  */
+                 gdb_assert (TYPE_CODE (target) == TYPE_CODE_TYPEDEF);
+                 target = TYPE_TARGET_TYPE (target);
+
+                 print_spaces_filtered (level + 4, stream);
+                 fprintf_filtered (stream, "typedef ");
+                 c_print_type (target, TYPE_TYPEDEF_FIELD_NAME (type, i),
+                               stream, show - 1, level + 4);
+                 fprintf_filtered (stream, ";\n");
+               }
+           }
+
+         fprintfi_filtered (level, stream, "}");
+
+         if (TYPE_LOCALTYPE_PTR (type) && show >= 0)
+           fprintfi_filtered (level, stream, _(" (Local at %s:%d)\n"),
+                              TYPE_LOCALTYPE_FILE (type),
+                              TYPE_LOCALTYPE_LINE (type));
+       }
+      break;
+
+    case TYPE_CODE_ENUM:
+      c_type_print_modifier (type, stream, 0, 1);
+      fprintf_filtered (stream, "enum ");
+      /* Print the tag name if it exists.
+         The aCC compiler emits a spurious
+         "{unnamed struct}"/"{unnamed union}"/"{unnamed enum}"
+         tag for unnamed struct/union/enum's, which we don't
+         want to print. */
+      if (TYPE_TAG_NAME (type) != NULL
+         && strncmp (TYPE_TAG_NAME (type), "{unnamed", 8))
+       {
+         fputs_filtered (TYPE_TAG_NAME (type), stream);
+         if (show > 0)
+           fputs_filtered (" ", stream);
+       }
+
+      wrap_here ("    ");
+      if (show < 0)
+       {
+         /* If we just printed a tag name, no need to print anything
+            else.  */
+         if (TYPE_TAG_NAME (type) == NULL)
+           fprintf_filtered (stream, "{...}");
+       }
+      else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
+       {
+         fprintf_filtered (stream, "{");
+         len = TYPE_NFIELDS (type);
+         lastval = 0;
+         for (i = 0; i < len; i++)
+           {
+             QUIT;
+             if (i)
+               fprintf_filtered (stream, ", ");
+             wrap_here ("    ");
+             fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+             if (lastval != TYPE_FIELD_BITPOS (type, i))
+               {
+                 fprintf_filtered (stream, " = %d",
+                                   TYPE_FIELD_BITPOS (type, i));
+                 lastval = TYPE_FIELD_BITPOS (type, i);
+               }
+             lastval++;
+           }
+         fprintf_filtered (stream, "}");
+       }
+      break;
+
+    case TYPE_CODE_VOID:
+      fprintf_filtered (stream, "void");
+      break;
+
+    case TYPE_CODE_UNDEF:
+      fprintf_filtered (stream, _("struct <unknown>"));
+      break;
+
+    case TYPE_CODE_ERROR:
+      fprintf_filtered (stream, "%s", TYPE_ERROR_NAME (type));
+      break;
+
+    case TYPE_CODE_RANGE:
+      /* This should not occur */
+      fprintf_filtered (stream, _("<range type>"));
+      break;
+
+    case TYPE_CODE_NAMESPACE:
+      fputs_filtered ("namespace ", stream);
+      fputs_filtered (TYPE_TAG_NAME (type), stream);
+      break;
+
+    default:
+      /* Handle types not explicitly handled by the other cases, such
+         as fundamental types.  For these, just print whatever the
+         type name is, as recorded in the type itself.  If there is no
+         type name, then complain.  */
+      if (TYPE_NAME (type) != NULL)
+       {
+         c_type_print_modifier (type, stream, 0, 1);
+         fputs_filtered (TYPE_NAME (type), stream);
+         /* show the bit position of this value, if it is not equal to 0 */
+         {
+           int bitpos_i = value_bitpos(value);
+           if (bitpos_i != 0)
+           {
+             fprintf_filtered (stream, ", bitpos = %d", bitpos_i);
+           }
+         }
+         /* show the bit size of this value, if it is not equal to 0 */
+         {
+           int bitsize_i = value_bitsize(value);
+           if (bitsize_i != 0)
+           {
+             fprintf_filtered (stream, ", bitsize = %d", bitsize_i);
+           }
+         }
+       }
+      else
+       {
+         /* At least for dump_symtab, it is important that this not
+            be an error ().  */
+         fprintf_filtered (stream, _("<invalid type code %d>"),
+                           TYPE_CODE (type));
+       }
+      break;
+    }
+}
+
diff -ur 7.4_orig/gdb/d-lang.c 7.4_ptype/gdb/d-lang.c
--- 7.4_orig/gdb/d-lang.c       2012-01-04 09:17:00.000000000 +0100
+++ 7.4_ptype/gdb/d-lang.c      2012-01-24 17:36:13.158875700 +0100
@@ -252,8 +252,8 @@
   c_printstr,                  /* Function to print string constant.  */
   c_emit_char,                 /* Print a single char.  */
   c_print_type,                        /* Print a type using appropriate syntax.  */
-  c_print_typedef,             /* Print a typedef using appropriate
-                                  syntax.  */
+  c_print_type_through_value,                  /* Print a type using appropriate syntax */
+  c_print_typedef,             /* Print a typedef using appropriate syntax.  */
   d_val_print,                 /* Print a value using appropriate syntax.  */
   c_value_print,               /* Print a top-level value.  */
   NULL,                                /* Language specific skip_trampoline.  */
diff -ur 7.4_orig/gdb/eval.c 7.4_ptype/gdb/eval.c
--- 7.4_orig/gdb/eval.c 2012-01-09 21:27:48.000000000 +0100
+++ 7.4_ptype/gdb/eval.c        2012-01-24 17:26:54.127625700 +0100
@@ -155,8 +155,9 @@
 evaluate_type (struct expression *exp)
 {
   int pc = 0;
-
-  return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
+  /* the parameter noside changed from EVAL_AVOID_SIDE_EFFECTS to EVAL_NORMAL
+  to get bitpos an bitsize of bitfield variables */
+  return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_NORMAL);
 }

 /* Evaluate a subexpression, avoiding all memory references and
diff -ur 7.4_orig/gdb/f-lang.c 7.4_ptype/gdb/f-lang.c
--- 7.4_orig/gdb/f-lang.c       2012-01-04 09:17:02.000000000 +0100
+++ 7.4_ptype/gdb/f-lang.c      2012-01-24 17:26:54.127625700 +0100
@@ -290,6 +290,7 @@
   f_printstr,                  /* function to print string constant */
   f_emit_char,                 /* Function to print a single character */
   f_print_type,                        /* Print a type using appropriate syntax */
+  f_print_type_through_value,  /* Print a type using appropriate syntax */
   default_print_typedef,       /* Print a typedef using appropriate syntax */
   f_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* FIXME */
diff -ur 7.4_orig/gdb/f-lang.h 7.4_ptype/gdb/f-lang.h
--- 7.4_orig/gdb/f-lang.h       2012-01-04 09:17:02.000000000 +0100
+++ 7.4_ptype/gdb/f-lang.h      2012-01-25 07:56:50.906059800 +0100
@@ -27,6 +27,8 @@

 extern void f_print_type (struct type *, const char *, struct ui_file *, int,
                          int);
+extern void f_print_type_through_value (struct value *, const char *, struct ui_file *, int,
+                         int);

 extern int f_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
                        struct ui_file *, int,
diff -ur 7.4_orig/gdb/f-typeprint.c 7.4_ptype/gdb/f-typeprint.c
--- 7.4_orig/gdb/f-typeprint.c  2012-01-04 09:17:02.000000000 +0100
+++ 7.4_ptype/gdb/f-typeprint.c 2012-01-25 09:45:59.671684800 +0100
@@ -82,6 +82,18 @@
    }
 }

+
+/* LEVEL is the depth to indent lines by.  */
+
+void
+f_print_type_through_value (struct value *value_p, const char *varstring, struct ui_file *stream,
+             int show, int level)
+{
+  struct type *type_p = value_type(value_p);
+  f_print_type (type_p, varstring, stream, show, level);
+}
+
+
 /* Print any asterisks or open-parentheses needed before the
    variable name (to describe its type).

diff -ur 7.4_orig/gdb/jv-lang.c 7.4_ptype/gdb/jv-lang.c
--- 7.4_orig/gdb/jv-lang.c      2012-01-08 22:02:45.000000000 +0100
+++ 7.4_ptype/gdb/jv-lang.c     2012-01-24 17:26:54.143250700 +0100
@@ -1178,6 +1178,7 @@
   java_printstr,               /* Function to print string constant */
   java_emit_char,              /* Function to print a single character */
   java_print_type,             /* Print a type using appropriate syntax */
+  java_print_type_through_value,       /* Print a type using appropriate syntax */
   default_print_typedef,       /* Print a typedef using appropriate syntax */
   java_val_print,              /* Print a value using appropriate syntax */
   java_value_print,            /* Print a top-level value */
diff -ur 7.4_orig/gdb/jv-lang.h 7.4_ptype/gdb/jv-lang.h
--- 7.4_orig/gdb/jv-lang.h      2012-01-04 09:17:05.000000000 +0100
+++ 7.4_ptype/gdb/jv-lang.h     2012-01-25 07:57:42.843559800 +0100
@@ -71,6 +71,8 @@
 /* Defined in jv-typeprint.c */
 extern void java_print_type (struct type *, const char *,
                             struct ui_file *, int, int);
+extern void java_print_type_through_value (struct value *, const char *,
+                                struct ui_file *, int, int);

 extern char *java_demangle_type_signature (char *);

diff -ur 7.4_orig/gdb/jv-typeprint.c 7.4_ptype/gdb/jv-typeprint.c
--- 7.4_orig/gdb/jv-typeprint.c 2012-01-04 09:17:05.000000000 +0100
+++ 7.4_ptype/gdb/jv-typeprint.c        2012-01-25 07:58:44.296684800 +0100
@@ -352,3 +352,12 @@
   demangled_args = varstring != NULL && strchr (varstring, '(') != NULL;
   c_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
 }
+
+
+void
+java_print_type_through_value (struct value *value_p, const char *varstring, struct ui_file *stream,
+                int show, int level)
+{
+       struct type *type_p = value_type(value_p);
+       java_print_type (type_p, varstring, stream, show, level);
+}
diff -ur 7.4_orig/gdb/language.c 7.4_ptype/gdb/language.c
--- 7.4_orig/gdb/language.c     2012-01-04 19:57:01.000000000 +0100
+++ 7.4_ptype/gdb/language.c    2012-01-25 07:43:58.093559800 +0100
@@ -847,6 +847,13 @@
           "function unk_lang_print_type called."));
 }

+static void
+unk_lang_print_type_through_value (struct value *value, const char *varstring, struct ui_file *stream,
+                    int show, int level)
+{
+  error (_("internal error - unimplemented function unk_lang_print_type_through_value called."));
+}
+
 static int
 unk_lang_val_print (struct type *type, const gdb_byte *valaddr,
                    int embedded_offset, CORE_ADDR address,
@@ -914,6 +921,7 @@
   unk_lang_printstr,
   unk_lang_emit_char,
   unk_lang_print_type,         /* Print a type using appropriate syntax */
+  unk_lang_print_type_through_value,           /* Print a type using appropriate syntax */
   default_print_typedef,       /* Print a typedef using appropriate syntax */
   unk_lang_val_print,          /* Print a value using appropriate syntax */
   unk_lang_value_print,                /* Print a top-level value */
@@ -957,6 +965,7 @@
   unk_lang_printstr,
   unk_lang_emit_char,
   unk_lang_print_type,         /* Print a type using appropriate syntax */
+  unk_lang_print_type_through_value,           /* Print a type using appropriate syntax */
   default_print_typedef,       /* Print a typedef using appropriate syntax */
   unk_lang_val_print,          /* Print a value using appropriate syntax */
   unk_lang_value_print,                /* Print a top-level value */
@@ -998,6 +1007,7 @@
   unk_lang_printstr,
   unk_lang_emit_char,
   unk_lang_print_type,         /* Print a type using appropriate syntax */
+  unk_lang_print_type_through_value,           /* Print a type using appropriate syntax */
   default_print_typedef,       /* Print a typedef using appropriate syntax */
   unk_lang_val_print,          /* Print a value using appropriate syntax */
   unk_lang_value_print,                /* Print a top-level value */
diff -ur 7.4_orig/gdb/language.h 7.4_ptype/gdb/language.h
--- 7.4_orig/gdb/language.h     2012-01-04 19:57:01.000000000 +0100
+++ 7.4_ptype/gdb/language.h    2012-01-25 07:54:04.187309800 +0100
@@ -202,6 +202,12 @@
     void (*la_print_type) (struct type *, const char *, struct ui_file *, int,
                           int);

+    /* Print a type (through value structure) using syntax appropriate for
+       this language. */
+
+    void (*la_print_type_through_value) (struct value *, const char *, struct ui_file *, int,
+                          int);
+
     /* Print a typedef using syntax appropriate for this language.
        TYPE is the underlying type.  NEW_SYMBOL is the symbol naming
        the type.  STREAM is the output stream on which to print.  */
@@ -433,6 +439,8 @@

 #define LA_PRINT_TYPE(type,varstring,stream,show,level) \
   (current_language->la_print_type(type,varstring,stream,show,level))
+#define LA_PRINT_TYPE_THROUGH_VALUE(value,varstring,stream,show,level) \
+  (current_language->la_print_type_through_value(value,varstring,stream,show,level))

 #define LA_PRINT_TYPEDEF(type,new_symbol,stream) \
   (current_language->la_print_typedef(type,new_symbol,stream))
diff -ur 7.4_orig/gdb/m2-lang.c 7.4_ptype/gdb/m2-lang.c
--- 7.4_orig/gdb/m2-lang.c      2012-01-04 09:17:05.000000000 +0100
+++ 7.4_ptype/gdb/m2-lang.c     2012-01-24 17:26:54.158875700 +0100
@@ -382,6 +382,7 @@
   m2_printstr,                 /* function to print string constant */
   m2_emit_char,                        /* Function to print a single character */
   m2_print_type,               /* Print a type using appropriate syntax */
+  m2_print_type_through_value, /* Print a type using appropriate syntax */
   m2_print_typedef,            /* Print a typedef using appropriate syntax */
   m2_val_print,                        /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
diff -ur 7.4_orig/gdb/m2-lang.h 7.4_ptype/gdb/m2-lang.h
--- 7.4_orig/gdb/m2-lang.h      2012-01-04 09:17:05.000000000 +0100
+++ 7.4_ptype/gdb/m2-lang.h     2012-01-25 07:59:26.234184800 +0100
@@ -25,6 +25,8 @@
 /* Defined in m2-typeprint.c */
 extern void m2_print_type (struct type *, const char *, struct ui_file *, int,
                           int);
+extern void m2_print_type_through_value (struct value *, const char *, struct ui_file *, int,
+                          int);

 extern void m2_print_typedef (struct type *, struct symbol *,
                              struct ui_file *);
diff -ur 7.4_orig/gdb/m2-typeprint.c 7.4_ptype/gdb/m2-typeprint.c
--- 7.4_orig/gdb/m2-typeprint.c 2012-01-04 09:17:05.000000000 +0100
+++ 7.4_ptype/gdb/m2-typeprint.c        2012-01-25 07:59:46.406059800 +0100
@@ -151,6 +151,16 @@
     }
 }

+
+void
+m2_print_type_through_value (struct value *value_p, const char *varstring, struct ui_file *stream,
+              int show, int level)
+{
+       struct type *type_p = value_type(value_p);
+       m2_print_type (type_p, varstring, stream, show, level);
+}
+
+
 /* Print a typedef using M2 syntax.  TYPE is the underlying type.
    NEW_SYMBOL is the symbol naming the type.  STREAM is the stream on
    which to print.  */
diff -ur 7.4_orig/gdb/objc-lang.c 7.4_ptype/gdb/objc-lang.c
--- 7.4_orig/gdb/objc-lang.c    2012-01-04 09:17:08.000000000 +0100
+++ 7.4_ptype/gdb/objc-lang.c   2012-01-24 17:26:54.174500700 +0100
@@ -521,6 +521,7 @@
   objc_printstr,               /* Function to print string constant */
   objc_emit_char,
   c_print_type,                        /* Print a type using appropriate syntax */
+  c_print_type_through_value,  /* Print a type using appropriate syntax */
   c_print_typedef,             /* Print a typedef using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
diff -ur 7.4_orig/gdb/opencl-lang.c 7.4_ptype/gdb/opencl-lang.c
--- 7.4_orig/gdb/opencl-lang.c  2012-01-04 09:17:09.000000000 +0100
+++ 7.4_ptype/gdb/opencl-lang.c 2012-01-25 08:27:31.734184800 +0100
@@ -1005,6 +1005,7 @@
   c_printstr,                  /* Function to print string constant */
   c_emit_char,                 /* Print a single char */
   c_print_type,                        /* Print a type using appropriate syntax */
+  c_print_type_through_value,  /* Print a type using appropriate syntax */
   c_print_typedef,             /* Print a typedef using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
diff -ur 7.4_orig/gdb/p-lang.c 7.4_ptype/gdb/p-lang.c
--- 7.4_orig/gdb/p-lang.c       2012-01-04 09:17:09.000000000 +0100
+++ 7.4_ptype/gdb/p-lang.c      2012-01-24 17:26:54.174500700 +0100
@@ -441,6 +441,7 @@
   pascal_printstr,             /* Function to print string constant */
   pascal_emit_char,            /* Print a single char */
   pascal_print_type,           /* Print a type using appropriate syntax */
+  pascal_print_type_through_value,     /* Print a type using appropriate syntax */
   pascal_print_typedef,                /* Print a typedef using appropriate syntax */
   pascal_val_print,            /* Print a value using appropriate syntax */
   pascal_value_print,          /* Print a top-level value */
diff -ur 7.4_orig/gdb/p-lang.h 7.4_ptype/gdb/p-lang.h
--- 7.4_orig/gdb/p-lang.h       2012-01-04 09:17:09.000000000 +0100
+++ 7.4_ptype/gdb/p-lang.h      2012-01-25 07:45:15.077934800 +0100
@@ -32,6 +32,9 @@
 extern void pascal_print_type (struct type *, const char *, struct ui_file *,
                               int, int);

+extern void pascal_print_type_through_value (struct value *, const char *,
+                      struct ui_file *, int, int);
+
 extern void pascal_print_typedef (struct type *, struct symbol *,
                                  struct ui_file *);

diff -ur 7.4_orig/gdb/p-typeprint.c 7.4_ptype/gdb/p-typeprint.c
--- 7.4_orig/gdb/p-typeprint.c  2012-01-04 09:17:09.000000000 +0100
+++ 7.4_ptype/gdb/p-typeprint.c 2012-01-25 07:47:32.593559800 +0100
@@ -89,6 +89,18 @@

 }

+
+/* LEVEL is the depth to indent lines by.  */
+
+void
+pascal_print_type_through_value (struct value *value_p, const char *varstring, struct ui_file *stream,
+                  int show, int level)
+{
+       struct type *type_p = value_type(value_p);
+       pascal_print_type (type_p, varstring, stream, show, level);
+}
+
+
 /* Print a typedef using Pascal syntax.  TYPE is the underlying type.
    NEW_SYMBOL is the symbol naming the type.  STREAM is the stream on
    which to print.  */
diff -ur 7.4_orig/gdb/typeprint.c 7.4_ptype/gdb/typeprint.c
--- 7.4_orig/gdb/typeprint.c    2012-01-04 09:27:57.000000000 +0100
+++ 7.4_ptype/gdb/typeprint.c   2012-01-24 17:29:30.315125700 +0100
@@ -79,6 +79,20 @@
   LA_PRINT_TYPE (type, varstring, stream, show, 0);
 }

+/* Print a description of a type TYPE in the form of a declaration of a
+   variable named VARSTRING.  (VARSTRING is demangled if necessary.)
+   Output goes to STREAM (via stdio).
+   If SHOW is positive, we show the contents of the outermost level
+   of structure even if there is a type name that could be used instead.
+   If SHOW is negative, we never show the details of elements' types.  */
+
+void
+type_print_through_value (struct value *value, char *varstring, struct ui_file *stream,
+           int show)
+{
+  LA_PRINT_TYPE_THROUGH_VALUE (value, varstring, stream, show, 0);
+}
+
 /* Print TYPE to a string, returning it.  The caller is responsible for
    freeing the string.  */

@@ -164,7 +178,10 @@
       printf_filtered (" */\n");
     }

-  type_print (type, "", gdb_stdout, show);
+  /* To see the positon and size of bitfields changed from
+     type_print (type, "", gdb_stdout, show);
+     to: */
+  type_print_through_value (val, "", gdb_stdout, show);
   printf_filtered ("\n");

   if (exp)
diff -ur 7.4_orig/gdb/value.h 7.4_ptype/gdb/value.h
--- 7.4_orig/gdb/value.h        2012-01-04 09:27:58.000000000 +0100
+++ 7.4_ptype/gdb/value.h       2012-01-24 17:29:30.330750700 +0100
@@ -779,6 +779,8 @@

 extern void type_print (struct type *type, char *varstring,
                        struct ui_file *stream, int show);
+extern void type_print_through_value (struct value *value, char *varstring,
+                       struct ui_file *stream, int show);

 extern char *type_to_string (struct type *type);



More information about the Gdb-patches mailing list