aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2020-03-13 17:39:52 -0600
committerTom Tromey <tom@tromey.com>2020-03-13 18:03:41 -0600
commit64b653ca7058bfd4f91879dea628809d398b488e (patch)
tree83ea5b40798b6782b733992385d12020bdd9667d
parent6999f067c1b30c1a2c3e41a0f68f74e459652560 (diff)
downloadgdb-64b653ca7058bfd4f91879dea628809d398b488e.zip
gdb-64b653ca7058bfd4f91879dea628809d398b488e.tar.gz
gdb-64b653ca7058bfd4f91879dea628809d398b488e.tar.bz2
Introduce cp_print_value_fields and c_value_print_struct
This adds cp_print_value_fields and c_value_print_struct, value-based analogues of the corresponding val-printing functions. Note that the Modula-2 printing code also calls cp_print_val_fields, and so is updated to call the function function. gdb/ChangeLog 2020-03-13 Tom Tromey <tom@tromey.com> * m2-valprint.c (m2_value_print_inner): Use cp_print_value_fields. * cp-valprint.c (cp_print_value_fields): New function. * c-valprint.c (c_value_print_struct): New function. (c_value_print_inner): Use c_value_print_struct. * c-lang.h (cp_print_value_fields): Declare.
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/c-lang.h5
-rw-r--r--gdb/c-valprint.c36
-rw-r--r--gdb/cp-valprint.c279
-rw-r--r--gdb/m2-valprint.c4
5 files changed, 322 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 85894e7..0a6c2fe 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2020-03-13 Tom Tromey <tom@tromey.com>
+ * m2-valprint.c (m2_value_print_inner): Use
+ cp_print_value_fields.
+ * cp-valprint.c (cp_print_value_fields): New function.
+ * c-valprint.c (c_value_print_struct): New function.
+ (c_value_print_inner): Use c_value_print_struct.
+ * c-lang.h (cp_print_value_fields): Declare.
+
+2020-03-13 Tom Tromey <tom@tromey.com>
+
* c-valprint.c (c_value_print_array): New function.
(c_value_print_inner): Use it.
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 7638ccf..e513805 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -135,6 +135,11 @@ extern void c_type_print_base (struct type *, struct ui_file *,
extern void cp_print_class_member (const gdb_byte *, struct type *,
struct ui_file *, const char *);
+extern void cp_print_value_fields (struct value *,
+ struct ui_file *, int,
+ const struct value_print_options *,
+ struct type **, int);
+
extern void cp_print_value_fields (struct type *, struct type *,
LONGEST, CORE_ADDR,
struct ui_file *, int,
diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
index dd4ab72..0f40a86 100644
--- a/gdb/c-valprint.c
+++ b/gdb/c-valprint.c
@@ -540,6 +540,34 @@ c_val_print_struct (struct type *type, const gdb_byte *valaddr,
NULL, 0);
}
+/* c_value_print helper for TYPE_CODE_STRUCT and TYPE_CODE_UNION. */
+
+static void
+c_value_print_struct (struct value *val, struct ui_file *stream, int recurse,
+ const struct value_print_options *options)
+{
+ struct type *type = check_typedef (value_type (val));
+
+ if (TYPE_CODE (type) == TYPE_CODE_UNION && recurse && !options->unionprint)
+ fprintf_filtered (stream, "{...}");
+ else if (options->vtblprint && cp_is_vtbl_ptr_type (type))
+ {
+ /* Print the unmangled name if desired. */
+ /* Print vtable entry - we only get here if NOT using
+ -fvtable_thunks. (Otherwise, look under
+ TYPE_CODE_PTR.) */
+ struct gdbarch *gdbarch = get_type_arch (type);
+ int offset = TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8;
+ struct type *field_type = TYPE_FIELD_TYPE (type, VTBL_FNADDR_OFFSET);
+ const gdb_byte *valaddr = value_contents_for_printing (val);
+ CORE_ADDR addr = extract_typed_address (valaddr + offset, field_type);
+
+ print_function_pointer_address (options, gdbarch, addr, stream);
+ }
+ else
+ cp_print_value_fields (val, stream, recurse, options, NULL, 0);
+}
+
/* c_val_print helper for TYPE_CODE_UNION. */
static void
@@ -746,7 +774,6 @@ c_value_print_inner (struct value *val, struct ui_file *stream, int recurse,
const struct value_print_options *options)
{
struct type *type = value_type (val);
- CORE_ADDR address = value_address (val);
const gdb_byte *valaddr = value_contents_for_printing (val);
type = check_typedef (type);
@@ -765,13 +792,8 @@ c_value_print_inner (struct value *val, struct ui_file *stream, int recurse,
break;
case TYPE_CODE_UNION:
- c_val_print_union (type, valaddr, 0, address, stream,
- recurse, val, options);
- break;
-
case TYPE_CODE_STRUCT:
- c_val_print_struct (type, valaddr, 0, address, stream,
- recurse, val, options);
+ c_value_print_struct (val, stream, recurse, options);
break;
case TYPE_CODE_INT:
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 569b0a5..e186d48 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -329,6 +329,7 @@ cp_print_value_fields (struct type *type, struct type *real_type,
{
CORE_ADDR addr;
+ i_offset += value_embedded_offset (val);
addr = extract_typed_address (valaddr + i_offset, i_type);
print_function_pointer_address (opts,
get_type_arch (type),
@@ -390,6 +391,282 @@ cp_print_value_fields (struct type *type, struct type *real_type,
fprintf_filtered (stream, "}");
}
+/* Mutually recursive subroutines of cp_print_value and c_value_print
+ to print out a structure's fields: cp_print_value_fields and
+ cp_print_value.
+
+ VAL, ADDRESS, STREAM, RECURSE, and OPTIONS have the same meanings
+ as in cp_print_value and c_value_print.
+
+ DONT_PRINT is an array of baseclass types that we should not print,
+ or zero if called from top level. */
+
+void
+cp_print_value_fields (struct value *val, struct ui_file *stream,
+ int recurse, const struct value_print_options *options,
+ struct type **dont_print_vb,
+ int dont_print_statmem)
+{
+ int i, len, n_baseclasses;
+ int fields_seen = 0;
+ static int last_set_recurse = -1;
+
+ struct type *type = check_typedef (value_type (val));
+ CORE_ADDR address = value_address (val);
+
+ if (recurse == 0)
+ {
+ /* Any object can be left on obstacks only during an unexpected
+ error. */
+
+ if (obstack_object_size (&dont_print_statmem_obstack) > 0)
+ {
+ obstack_free (&dont_print_statmem_obstack, NULL);
+ obstack_begin (&dont_print_statmem_obstack,
+ 32 * sizeof (CORE_ADDR));
+ }
+ if (obstack_object_size (&dont_print_stat_array_obstack) > 0)
+ {
+ obstack_free (&dont_print_stat_array_obstack, NULL);
+ obstack_begin (&dont_print_stat_array_obstack,
+ 32 * sizeof (struct type *));
+ }
+ }
+
+ fprintf_filtered (stream, "{");
+ len = TYPE_NFIELDS (type);
+ n_baseclasses = TYPE_N_BASECLASSES (type);
+
+ /* First, print out baseclasses such that we don't print
+ duplicates of virtual baseclasses. */
+
+ if (n_baseclasses > 0)
+ cp_print_value (type, type, 0, address, stream,
+ recurse + 1, val, options,
+ dont_print_vb);
+
+ /* Second, print out data fields */
+
+ /* If there are no data fields, skip this part */
+ if (len == n_baseclasses || !len)
+ fprintf_styled (stream, metadata_style.style (), "<No data fields>");
+ else
+ {
+ size_t statmem_obstack_initial_size = 0;
+ size_t stat_array_obstack_initial_size = 0;
+ struct type *vptr_basetype = NULL;
+ int vptr_fieldno;
+
+ if (dont_print_statmem == 0)
+ {
+ statmem_obstack_initial_size =
+ obstack_object_size (&dont_print_statmem_obstack);
+
+ if (last_set_recurse != recurse)
+ {
+ stat_array_obstack_initial_size =
+ obstack_object_size (&dont_print_stat_array_obstack);
+
+ last_set_recurse = recurse;
+ }
+ }
+
+ vptr_fieldno = get_vptr_fieldno (type, &vptr_basetype);
+ for (i = n_baseclasses; i < len; i++)
+ {
+ const gdb_byte *valaddr = value_contents_for_printing (val);
+
+ /* If requested, skip printing of static fields. */
+ if (!options->static_field_print
+ && field_is_static (&TYPE_FIELD (type, i)))
+ continue;
+
+ if (fields_seen)
+ {
+ fputs_filtered (",", stream);
+ if (!options->prettyformat)
+ fputs_filtered (" ", stream);
+ }
+ else if (n_baseclasses > 0)
+ {
+ if (options->prettyformat)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ fputs_filtered ("members of ", stream);
+ fputs_filtered (TYPE_NAME (type), stream);
+ fputs_filtered (":", stream);
+ }
+ }
+ fields_seen = 1;
+
+ if (options->prettyformat)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ }
+ else
+ {
+ wrap_here (n_spaces (2 + 2 * recurse));
+ }
+
+ annotate_field_begin (TYPE_FIELD_TYPE (type, i));
+
+ if (field_is_static (&TYPE_FIELD (type, i)))
+ {
+ fputs_filtered ("static ", stream);
+ fprintf_symbol_filtered (stream,
+ TYPE_FIELD_NAME (type, i),
+ current_language->la_language,
+ DMGL_PARAMS | DMGL_ANSI);
+ }
+ else
+ fputs_styled (TYPE_FIELD_NAME (type, i),
+ variable_name_style.style (), stream);
+ annotate_field_name_end ();
+
+ /* We tweak various options in a few cases below. */
+ value_print_options options_copy = *options;
+ value_print_options *opts = &options_copy;
+
+ /* Do not print leading '=' in case of anonymous
+ unions. */
+ if (strcmp (TYPE_FIELD_NAME (type, i), ""))
+ fputs_filtered (" = ", stream);
+ else
+ {
+ /* If this is an anonymous field then we want to consider it
+ as though it is at its parent's depth when it comes to the
+ max print depth. */
+ if (opts->max_depth != -1 && opts->max_depth < INT_MAX)
+ ++opts->max_depth;
+ }
+ annotate_field_value ();
+
+ if (!field_is_static (&TYPE_FIELD (type, i))
+ && TYPE_FIELD_PACKED (type, i))
+ {
+ struct value *v;
+
+ /* Bitfields require special handling, especially due to
+ byte order problems. */
+ if (TYPE_FIELD_IGNORE (type, i))
+ {
+ fputs_styled ("<optimized out or zero length>",
+ metadata_style.style (), stream);
+ }
+ else if (value_bits_synthetic_pointer (val,
+ TYPE_FIELD_BITPOS (type,
+ i),
+ TYPE_FIELD_BITSIZE (type,
+ i)))
+ {
+ fputs_styled (_("<synthetic pointer>"),
+ metadata_style.style (), stream);
+ }
+ else
+ {
+ opts->deref_ref = 0;
+
+ v = value_field_bitfield (type, i, valaddr,
+ value_embedded_offset (val), val);
+
+ common_val_print (v, stream, recurse + 1,
+ opts, current_language);
+ }
+ }
+ else
+ {
+ if (TYPE_FIELD_IGNORE (type, i))
+ {
+ fputs_styled ("<optimized out or zero length>",
+ metadata_style.style (), stream);
+ }
+ else if (field_is_static (&TYPE_FIELD (type, i)))
+ {
+ try
+ {
+ struct value *v = value_static_field (type, i);
+
+ cp_print_static_field (TYPE_FIELD_TYPE (type, i),
+ v, stream, recurse + 1,
+ opts);
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ fprintf_styled (stream, metadata_style.style (),
+ _("<error reading variable: %s>"),
+ ex.what ());
+ }
+ }
+ else if (i == vptr_fieldno && type == vptr_basetype)
+ {
+ int i_offset = TYPE_FIELD_BITPOS (type, i) / 8;
+ struct type *i_type = TYPE_FIELD_TYPE (type, i);
+
+ if (valprint_check_validity (stream, i_type, i_offset, val))
+ {
+ CORE_ADDR addr;
+
+ addr = extract_typed_address (valaddr + i_offset, i_type);
+ print_function_pointer_address (opts,
+ get_type_arch (type),
+ addr, stream);
+ }
+ }
+ else
+ {
+ struct value *v = value_primitive_field (val, 0, i, type);
+ opts->deref_ref = 0;
+ common_val_print (v, stream, recurse + 1, opts,
+ current_language);
+ }
+ }
+ annotate_field_end ();
+ }
+
+ if (dont_print_statmem == 0)
+ {
+ size_t obstack_final_size =
+ obstack_object_size (&dont_print_statmem_obstack);
+
+ if (obstack_final_size > statmem_obstack_initial_size)
+ {
+ /* In effect, a pop of the printed-statics stack. */
+ size_t shrink_bytes
+ = statmem_obstack_initial_size - obstack_final_size;
+ obstack_blank_fast (&dont_print_statmem_obstack, shrink_bytes);
+ }
+
+ if (last_set_recurse != recurse)
+ {
+ obstack_final_size =
+ obstack_object_size (&dont_print_stat_array_obstack);
+
+ if (obstack_final_size > stat_array_obstack_initial_size)
+ {
+ void *free_to_ptr =
+ (char *) obstack_next_free (&dont_print_stat_array_obstack)
+ - (obstack_final_size
+ - stat_array_obstack_initial_size);
+
+ obstack_free (&dont_print_stat_array_obstack,
+ free_to_ptr);
+ }
+ last_set_recurse = -1;
+ }
+ }
+
+ if (options->prettyformat)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+ } /* if there are data fields */
+
+ fprintf_filtered (stream, "}");
+}
+
/* Like cp_print_value_fields, but find the runtime type of the object
and pass it as the `real_type' argument to cp_print_value_fields.
This function is a hack to work around the fact that
@@ -436,7 +713,7 @@ cp_print_value_fields_rtti (struct type *type,
dont_print_vb, dont_print_statmem);
}
-/* Special val_print routine to avoid printing multiple copies of
+/* Special value_print routine to avoid printing multiple copies of
virtual baseclasses. */
static void
diff --git a/gdb/m2-valprint.c b/gdb/m2-valprint.c
index 63d8c15..facd15e 100644
--- a/gdb/m2-valprint.c
+++ b/gdb/m2-valprint.c
@@ -605,9 +605,7 @@ m2_value_print_inner (struct value *val, struct ui_file *stream, int recurse,
else if (m2_is_unbounded_array (type))
m2_print_unbounded_array (val, stream, recurse, options);
else
- cp_print_value_fields (type, type, 0,
- address, stream, recurse, val,
- options, NULL, 0);
+ cp_print_value_fields (val, stream, recurse, options, NULL, 0);
break;
case TYPE_CODE_SET: