From patchwork Sun Dec 8 18:29:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 36622 Received: (qmail 104965 invoked by alias); 8 Dec 2019 18:31:14 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 101786 invoked by uid 89); 8 Dec 2019 18:30:29 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=synthetic X-HELO: gateway34.websitewelcome.com Received: from gateway34.websitewelcome.com (HELO gateway34.websitewelcome.com) (192.185.150.114) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 08 Dec 2019 18:30:13 +0000 Received: from cm10.websitewelcome.com (cm10.websitewelcome.com [100.42.49.4]) by gateway34.websitewelcome.com (Postfix) with ESMTP id 1418B306E2 for ; Sun, 8 Dec 2019 12:30:11 -0600 (CST) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id e1JriMgkJHunhe1Jriex5A; Sun, 08 Dec 2019 12:30:11 -0600 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=TtAJv3QVHAV+o4MoXp4GB4PTabtjEdQOyYT7qCMXk4A=; b=t1pg8Dsj2MEQEglmQ1xRDxaofy TrocGpl2JQISbkdUtrXCNBDYRQIuNxxR/W/SVE9n16CAtvdZu3CWMnyzNhZnxwDDXOBRIOS48XZNx gCq808VEX7Gey4UVIHhHElTy7; Received: from 75-166-123-50.hlrn.qwest.net ([75.166.123.50]:53626 helo=bapiya.Home) by box5379.bluehost.com with esmtpa (Exim 4.92) (envelope-from ) id 1ie1Jq-0045L6-Rz; Sun, 08 Dec 2019 11:30:10 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 44/55] Introduce cp_print_value_fields and c_value_print_struct Date: Sun, 8 Dec 2019 11:29:47 -0700 Message-Id: <20191208182958.10181-45-tom@tromey.com> In-Reply-To: <20191208182958.10181-1-tom@tromey.com> References: <20191208182958.10181-1-tom@tromey.com> 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 2019-12-08 Tom Tromey * 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. Change-Id: Iac162891972988b968a736ba14720a4a4acbf92e --- gdb/ChangeLog | 9 ++ gdb/c-lang.h | 5 + gdb/c-valprint.c | 36 ++++-- gdb/cp-valprint.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++ gdb/m2-valprint.c | 4 +- 5 files changed, 319 insertions(+), 10 deletions(-) diff --git a/gdb/c-lang.h b/gdb/c-lang.h index 8523a0b68c5..96244531149 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 eaf7ef2eafe..8637ba976af 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 9a26ab322a4..77dbaae891f 100644 --- a/gdb/cp-valprint.c +++ b/gdb/cp-valprint.c @@ -324,6 +324,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), @@ -385,6 +386,280 @@ cp_print_value_fields (struct type *type, struct type *real_type, fprintf_filtered (stream, "}"); } +/* Mutually recursive subroutines of cp_print_value and c_val_print to + print out a structure's fields: cp_print_value_fields and + cp_print_value. + + TYPE, VALADDR, ADDRESS, STREAM, RECURSE, and OPTIONS have the same + meanings as in cp_print_value and c_val_print. + + 2nd argument REAL_TYPE is used to carry over the type of the + derived class across the recursion to base classes. + + 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 (), ""); + 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); + 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 ("", + metadata_style.style (), stream); + } + else if (value_bits_synthetic_pointer (val, + TYPE_FIELD_BITPOS (type, + i), + TYPE_FIELD_BITSIZE (type, + i))) + { + fputs_styled (_(""), + 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 ("", + 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 (), + _(""), + 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 diff --git a/gdb/m2-valprint.c b/gdb/m2-valprint.c index 12f62ad1e83..1f3907c41ab 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: