[RFC, patch] ptype bitfields show bitpos and bitsize

Leutwein Tobias (BEG-PT/ESB1)
2012-01-25T11:18:33Z

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);