From patchwork Sun Dec 8 18:29:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 36637 Received: (qmail 36851 invoked by alias); 8 Dec 2019 18:52:41 -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 36797 invoked by uid 89); 8 Dec 2019 18:52:40 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.6 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= X-HELO: gateway36.websitewelcome.com Received: from gateway36.websitewelcome.com (HELO gateway36.websitewelcome.com) (192.185.187.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 08 Dec 2019 18:52:39 +0000 Received: from cm11.websitewelcome.com (cm11.websitewelcome.com [100.42.49.5]) by gateway36.websitewelcome.com (Postfix) with ESMTP id A3F1B4028F153 for ; Sun, 8 Dec 2019 11:40:31 -0600 (CST) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id e1JriY9SNiJ43e1JrizFM7; 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=6sb5LmWv2WOwUZa+ymFFSAEzLh+TkgBSspb7GZZ4pRM=; b=sMntXJk7TKi/kvdk+m0OnhHpQX xHPfK2n4EJIPdKr/3W3UQDxc9aHgr/aDxtPwK1vdXpVOwrk0nY/EgrJSXx/ifmW+LvAzcqDYcDSBE ENtsrF42ggvNF+QjtLbc5VMUd; 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 1ie1Jr-0045L6-1X; Sun, 08 Dec 2019 11:30:11 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 45/55] Introduce cp_print_value Date: Sun, 8 Dec 2019 11:29:48 -0700 Message-Id: <20191208182958.10181-46-tom@tromey.com> In-Reply-To: <20191208182958.10181-1-tom@tromey.com> References: <20191208182958.10181-1-tom@tromey.com> This adds cp_print_value, a value-based analogue of cp_print_val, and changes cp_print_value_fields to use it. gdb/ChangeLog 2019-12-08 Tom Tromey * cp-valprint.c (cp_print_value_fields): Update. (cp_print_value): New function. Change-Id: I8902ff3702eddd2ac2bfbfbd6a485b94b56eaba6 --- gdb/ChangeLog | 5 ++ gdb/cp-valprint.c | 168 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 169 insertions(+), 4 deletions(-) diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c index 77dbaae891f..143d77cb223 100644 --- a/gdb/cp-valprint.c +++ b/gdb/cp-valprint.c @@ -54,6 +54,10 @@ static void cp_print_value (struct type *, struct type *, const struct value_print_options *, struct type **); +static void cp_print_value (struct value *, struct ui_file *, + int, const struct value_print_options *, + struct type **); + /* GCC versions after 2.4.5 use this. */ const char vtbl_ptr_name[] = "__vtbl_ptr_type"; @@ -410,7 +414,6 @@ cp_print_value_fields (struct value *val, struct ui_file *stream, static int last_set_recurse = -1; struct type *type = check_typedef (value_type (val)); - CORE_ADDR address = value_address (val); if (recurse == 0) { @@ -439,9 +442,7 @@ cp_print_value_fields (struct value *val, struct ui_file *stream, duplicates of virtual baseclasses. */ if (n_baseclasses > 0) - cp_print_value (type, type, 0, address, stream, - recurse + 1, val, options, - dont_print_vb); + cp_print_value (val, stream, recurse + 1, options, dont_print_vb); /* Second, print out data fields */ @@ -601,6 +602,7 @@ cp_print_value_fields (struct value *val, struct ui_file *stream, { 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), @@ -874,6 +876,164 @@ cp_print_value (struct type *type, struct type *real_type, } } +/* Special val_print routine to avoid printing multiple copies of + virtual baseclasses. */ + +static void +cp_print_value (struct value *val, struct ui_file *stream, + int recurse, const struct value_print_options *options, + struct type **dont_print_vb) +{ + struct type *type = check_typedef (value_type (val)); + CORE_ADDR address = value_address (val); + struct type **last_dont_print + = (struct type **) obstack_next_free (&dont_print_vb_obstack); + struct obstack tmp_obstack = dont_print_vb_obstack; + int i, n_baseclasses = TYPE_N_BASECLASSES (type); + const gdb_byte *valaddr = value_contents_for_printing (val); + + if (dont_print_vb == 0) + { + /* If we're at top level, carve out a completely fresh chunk of + the obstack and use that until this particular invocation + returns. */ + /* Bump up the high-water mark. Now alpha is omega. */ + obstack_finish (&dont_print_vb_obstack); + } + + for (i = 0; i < n_baseclasses; i++) + { + LONGEST boffset = 0; + int skip = 0; + struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i)); + const char *basename = TYPE_NAME (baseclass); + struct value *base_val = NULL; + + if (BASETYPE_VIA_VIRTUAL (type, i)) + { + struct type **first_dont_print + = (struct type **) obstack_base (&dont_print_vb_obstack); + + int j = (struct type **) + obstack_next_free (&dont_print_vb_obstack) - first_dont_print; + + while (--j >= 0) + if (baseclass == first_dont_print[j]) + goto flush_it; + + obstack_ptr_grow (&dont_print_vb_obstack, baseclass); + } + + try + { + boffset = baseclass_offset (type, i, valaddr, + value_embedded_offset (val), + address, val); + } + catch (const gdb_exception_error &ex) + { + if (ex.error == NOT_AVAILABLE_ERROR) + skip = -1; + else + skip = 1; + } + + if (skip == 0) + { + if (BASETYPE_VIA_VIRTUAL (type, i)) + { + /* The virtual base class pointer might have been + clobbered by the user program. Make sure that it + still points to a valid memory location. */ + + if (boffset < 0 || boffset >= TYPE_LENGTH (type)) + { + gdb::byte_vector buf (TYPE_LENGTH (baseclass)); + + if (target_read_memory (address + boffset, buf.data (), + TYPE_LENGTH (baseclass)) != 0) + skip = 1; + base_val = value_from_contents_and_address (baseclass, + buf.data (), + address + boffset); + baseclass = value_type (base_val); + boffset = 0; + } + else + { + base_val = val; + } + } + else + { + base_val = val; + } + } + + /* Now do the printing. */ + if (options->prettyformat) + { + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 * recurse, stream); + } + fputs_filtered ("<", stream); + /* Not sure what the best notation is in the case where there is + no baseclass name. */ + fputs_filtered (basename ? basename : "", stream); + fputs_filtered ("> = ", stream); + + if (skip < 0) + val_print_unavailable (stream); + else if (skip > 0) + val_print_invalid_address (stream); + else + { + int result = 0; + + if (options->max_depth > -1 + && recurse >= options->max_depth) + { + const struct language_defn *language = current_language; + gdb_assert (language->la_struct_too_deep_ellipsis != NULL); + fputs_filtered (language->la_struct_too_deep_ellipsis, stream); + } + else + { + /* Attempt to run an extension language pretty-printer on the + baseclass if possible. */ + if (!options->raw) + result + = apply_ext_lang_val_pretty_printer (baseclass, boffset, + value_address (base_val), + stream, recurse, + base_val, options, + current_language); + + if (!result) + cp_print_value_fields (value_primitive_field (val, 0, i, type), + stream, recurse, options, + ((struct type **) + obstack_base (&dont_print_vb_obstack)), + 0); + } + } + fputs_filtered (", ", stream); + + flush_it: + ; + } + + if (dont_print_vb == 0) + { + /* Free the space used to deal with the printing + of this type from top level. */ + obstack_free (&dont_print_vb_obstack, last_dont_print); + /* Reset watermark so that we can continue protecting + ourselves from whatever we were protecting ourselves. */ + dont_print_vb_obstack = tmp_obstack; + } +} + /* Print value of a static member. To avoid infinite recursion when printing a class that contains a static instance of the class, we keep the addresses of all printed static member classes in an