From patchwork Thu Feb 9 21:38:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 64583 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E51B13888C7C for ; Thu, 9 Feb 2023 21:43:03 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from qproxy6-pub.mail.unifiedlayer.com (qproxy6-pub.mail.unifiedlayer.com [69.89.23.12]) by sourceware.org (Postfix) with ESMTPS id 48F6F384B02A for ; Thu, 9 Feb 2023 21:39:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 48F6F384B02A Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tromey.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tromey.com Received: from gproxy1-pub.mail.unifiedlayer.com (unknown [69.89.25.95]) by qproxy6.mail.unifiedlayer.com (Postfix) with ESMTP id 5DE2C803428D for ; Thu, 9 Feb 2023 21:39:10 +0000 (UTC) Received: from cmgw10.mail.unifiedlayer.com (unknown [10.0.90.125]) by progateway3.mail.pro1.eigbox.com (Postfix) with ESMTP id 51F9A10046FD8 for ; Thu, 9 Feb 2023 21:38:40 +0000 (UTC) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with ESMTP id QEcqpwJueOscKQEcqpW9DL; Thu, 09 Feb 2023 21:38:40 +0000 X-Authority-Reason: nr=8 X-Authority-Analysis: v=2.4 cv=Y5c9DjSN c=1 sm=1 tr=0 ts=63e567e0 a=ApxJNpeYhEAb1aAlGBBbmA==:117 a=ApxJNpeYhEAb1aAlGBBbmA==:17 a=dLZJa+xiwSxG16/P+YVxDGlgEgI=:19 a=IkcTkHD0fZMA:10:nop_charset_1 a=m04uMKEZRckA:10:nop_rcvd_month_year a=Qbun_eYptAEA:10:endurance_base64_authed_username_1 a=aQERtVHYdmW6PhkYK8UA:9 a=8eK45udfRx268ukT:21 a=QEXdDO2ut3YA:10:nop_charset_2 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=To:In-Reply-To:References:Message-Id:Content-Transfer-Encoding: Content-Type:MIME-Version:Subject:Date:From:Sender:Reply-To:Cc: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=B3eUXeQguPe8hUk6K1v+lfsgUadPpveayuOL0cGMIUI=; b=pqu1GTtoxX7m+sC0Ud7uR1fGs9 oIT2tCL4P8K1g/9lkZSQ3HNC3AVfpDpQ572yNTtEl1BugKdUvTEYAXqkma4dg+JgxTvEVgQGoJuLX OGMNk2XV3pV5xEH9ifRRqHrKd; Received: from 75-166-130-93.hlrn.qwest.net ([75.166.130.93]:52822 helo=[192.168.0.21]) by box5379.bluehost.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1pQEcq-001ZcE-0J for gdb-patches@sourceware.org; Thu, 09 Feb 2023 14:38:40 -0700 From: Tom Tromey Date: Thu, 09 Feb 2023 14:38:24 -0700 Subject: [PATCH 03/47] Move struct value to value.h MIME-Version: 1.0 Message-Id: <20230209-submit-value-fixups-2023-v1-3-55dc2794dbb9@tromey.com> References: <20230209-submit-value-fixups-2023-v1-0-55dc2794dbb9@tromey.com> In-Reply-To: <20230209-submit-value-fixups-2023-v1-0-55dc2794dbb9@tromey.com> To: gdb-patches@sourceware.org X-Mailer: b4 0.12.0 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 75.166.130.93 X-Source-L: No X-Exim-ID: 1pQEcq-001ZcE-0J X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 75-166-130-93.hlrn.qwest.net ([192.168.0.21]) [75.166.130.93]:52822 X-Source-Auth: tom+tromey.com X-Email-Count: 4 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-Spam-Status: No, score=-3027.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, JMQ_SPF_NEUTRAL, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" This moves struct value to value.h. For now, all members remain public, but this is a temporary state -- by the end of the series we'll add 'private'. --- gdb/value.c | 213 ----------------------------------------------------------- gdb/value.h | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 211 insertions(+), 218 deletions(-) diff --git a/gdb/value.c b/gdb/value.c index b5e5a46573d..7ba46e20e7b 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -66,33 +66,6 @@ struct internal_function void *cookie; }; -/* Defines an [OFFSET, OFFSET + LENGTH) range. */ - -struct range -{ - /* Lowest offset in the range. */ - LONGEST offset; - - /* Length of the range. */ - LONGEST length; - - /* Returns true if THIS is strictly less than OTHER, useful for - searching. We keep ranges sorted by offset and coalesce - overlapping and contiguous ranges, so this just compares the - starting offset. */ - - bool operator< (const range &other) const - { - return offset < other.offset; - } - - /* Returns true if THIS is equal to OTHER. */ - bool operator== (const range &other) const - { - return offset == other.offset && length == other.length; - } -}; - /* Returns true if the ranges defined by [offset1, offset1+len1) and [offset2, offset2+len2) overlap. */ @@ -174,192 +147,6 @@ ranges_contain (const std::vector &ranges, LONGEST offset, static struct cmd_list_element *functionlist; -/* Note that the fields in this structure are arranged to save a bit - of memory. */ - -struct value -{ - explicit value (struct type *type_) - : m_modifiable (1), - m_lazy (1), - m_initialized (1), - m_stack (0), - m_is_zero (false), - m_type (type_), - m_enclosing_type (type_) - { - } - - ~value (); - - DISABLE_COPY_AND_ASSIGN (value); - - /* Type of value; either not an lval, or one of the various - different possible kinds of lval. */ - enum lval_type m_lval = not_lval; - - /* Is it modifiable? Only relevant if lval != not_lval. */ - unsigned int m_modifiable : 1; - - /* If zero, contents of this value are in the contents field. If - nonzero, contents are in inferior. If the lval field is lval_memory, - the contents are in inferior memory at location.address plus offset. - The lval field may also be lval_register. - - WARNING: This field is used by the code which handles watchpoints - (see breakpoint.c) to decide whether a particular value can be - watched by hardware watchpoints. If the lazy flag is set for - some member of a value chain, it is assumed that this member of - the chain doesn't need to be watched as part of watching the - value itself. This is how GDB avoids watching the entire struct - or array when the user wants to watch a single struct member or - array element. If you ever change the way lazy flag is set and - reset, be sure to consider this use as well! */ - unsigned int m_lazy : 1; - - /* If value is a variable, is it initialized or not. */ - unsigned int m_initialized : 1; - - /* If value is from the stack. If this is set, read_stack will be - used instead of read_memory to enable extra caching. */ - unsigned int m_stack : 1; - - /* True if this is a zero value, created by 'value_zero'; false - otherwise. */ - bool m_is_zero : 1; - - /* Location of value (if lval). */ - union - { - /* If lval == lval_memory, this is the address in the inferior */ - CORE_ADDR address; - - /*If lval == lval_register, the value is from a register. */ - struct - { - /* Register number. */ - int regnum; - /* Frame ID of "next" frame to which a register value is relative. - If the register value is found relative to frame F, then the - frame id of F->next will be stored in next_frame_id. */ - struct frame_id next_frame_id; - } reg; - - /* Pointer to internal variable. */ - struct internalvar *internalvar; - - /* Pointer to xmethod worker. */ - struct xmethod_worker *xm_worker; - - /* If lval == lval_computed, this is a set of function pointers - to use to access and describe the value, and a closure pointer - for them to use. */ - struct - { - /* Functions to call. */ - const struct lval_funcs *funcs; - - /* Closure for those functions to use. */ - void *closure; - } computed; - } m_location {}; - - /* Describes offset of a value within lval of a structure in target - addressable memory units. Note also the member embedded_offset - below. */ - LONGEST m_offset = 0; - - /* Only used for bitfields; number of bits contained in them. */ - LONGEST m_bitsize = 0; - - /* Only used for bitfields; position of start of field. For - little-endian targets, it is the position of the LSB. For - big-endian targets, it is the position of the MSB. */ - LONGEST m_bitpos = 0; - - /* The number of references to this value. When a value is created, - the value chain holds a reference, so REFERENCE_COUNT is 1. If - release_value is called, this value is removed from the chain but - the caller of release_value now has a reference to this value. - The caller must arrange for a call to value_free later. */ - int m_reference_count = 1; - - /* Only used for bitfields; the containing value. This allows a - single read from the target when displaying multiple - bitfields. */ - value_ref_ptr m_parent; - - /* Type of the value. */ - struct type *m_type; - - /* If a value represents a C++ object, then the `type' field gives - the object's compile-time type. If the object actually belongs - to some class derived from `type', perhaps with other base - classes and additional members, then `type' is just a subobject - of the real thing, and the full object is probably larger than - `type' would suggest. - - If `type' is a dynamic class (i.e. one with a vtable), then GDB - can actually determine the object's run-time type by looking at - the run-time type information in the vtable. When this - information is available, we may elect to read in the entire - object, for several reasons: - - - When printing the value, the user would probably rather see the - full object, not just the limited portion apparent from the - compile-time type. - - - If `type' has virtual base classes, then even printing `type' - alone may require reaching outside the `type' portion of the - object to wherever the virtual base class has been stored. - - When we store the entire object, `enclosing_type' is the run-time - type -- the complete object -- and `embedded_offset' is the - offset of `type' within that larger type, in target addressable memory - units. The value_contents() macro takes `embedded_offset' into account, - so most GDB code continues to see the `type' portion of the value, just - as the inferior would. - - If `type' is a pointer to an object, then `enclosing_type' is a - pointer to the object's run-time type, and `pointed_to_offset' is - the offset in target addressable memory units from the full object - to the pointed-to object -- that is, the value `embedded_offset' would - have if we followed the pointer and fetched the complete object. - (I don't really see the point. Why not just determine the - run-time type when you indirect, and avoid the special case? The - contents don't matter until you indirect anyway.) - - If we're not doing anything fancy, `enclosing_type' is equal to - `type', and `embedded_offset' is zero, so everything works - normally. */ - struct type *m_enclosing_type; - LONGEST m_embedded_offset = 0; - LONGEST m_pointed_to_offset = 0; - - /* Actual contents of the value. Target byte-order. - - May be nullptr if the value is lazy or is entirely optimized out. - Guaranteed to be non-nullptr otherwise. */ - gdb::unique_xmalloc_ptr m_contents; - - /* Unavailable ranges in CONTENTS. We mark unavailable ranges, - rather than available, since the common and default case is for a - value to be available. This is filled in at value read time. - The unavailable ranges are tracked in bits. Note that a contents - bit that has been optimized out doesn't really exist in the - program, so it can't be marked unavailable either. */ - std::vector m_unavailable; - - /* Likewise, but for optimized out contents (a chunk of the value of - a variable that does not actually exist in the program). If LVAL - is lval_register, this is a register ($pc, $sp, etc., never a - program variable) that has not been saved in the frame. Not - saved registers and optimized-out program variables values are - treated pretty much the same, except not-saved registers have a - different string representation and related error strings. */ - std::vector m_optimized_out; -}; - value::~value () { if (VALUE_LVAL (this) == lval_computed) diff --git a/gdb/value.h b/gdb/value.h index f022510ded1..ea549a8cb81 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -84,12 +84,32 @@ struct value_print_options; extern bool overload_resolution; -/* The structure which defines the type of a value. It should never - be possible for a program lval value to survive over a call to the - inferior (i.e. to be put into the history list or an internal - variable). */ +/* Defines an [OFFSET, OFFSET + LENGTH) range. */ -struct value; +struct range +{ + /* Lowest offset in the range. */ + LONGEST offset; + + /* Length of the range. */ + LONGEST length; + + /* Returns true if THIS is strictly less than OTHER, useful for + searching. We keep ranges sorted by offset and coalesce + overlapping and contiguous ranges, so this just compares the + starting offset. */ + + bool operator< (const range &other) const + { + return offset < other.offset; + } + + /* Returns true if THIS is equal to OTHER. */ + bool operator== (const range &other) const + { + return offset == other.offset && length == other.length; + } +}; /* Increase VAL's reference count. */ @@ -119,6 +139,192 @@ struct value_ref_policy typedef gdb::ref_ptr value_ref_ptr; +/* Note that the fields in this structure are arranged to save a bit + of memory. */ + +struct value +{ + explicit value (struct type *type_) + : m_modifiable (1), + m_lazy (1), + m_initialized (1), + m_stack (0), + m_is_zero (false), + m_type (type_), + m_enclosing_type (type_) + { + } + + ~value (); + + DISABLE_COPY_AND_ASSIGN (value); + + /* Type of value; either not an lval, or one of the various + different possible kinds of lval. */ + enum lval_type m_lval = not_lval; + + /* Is it modifiable? Only relevant if lval != not_lval. */ + unsigned int m_modifiable : 1; + + /* If zero, contents of this value are in the contents field. If + nonzero, contents are in inferior. If the lval field is lval_memory, + the contents are in inferior memory at location.address plus offset. + The lval field may also be lval_register. + + WARNING: This field is used by the code which handles watchpoints + (see breakpoint.c) to decide whether a particular value can be + watched by hardware watchpoints. If the lazy flag is set for + some member of a value chain, it is assumed that this member of + the chain doesn't need to be watched as part of watching the + value itself. This is how GDB avoids watching the entire struct + or array when the user wants to watch a single struct member or + array element. If you ever change the way lazy flag is set and + reset, be sure to consider this use as well! */ + unsigned int m_lazy : 1; + + /* If value is a variable, is it initialized or not. */ + unsigned int m_initialized : 1; + + /* If value is from the stack. If this is set, read_stack will be + used instead of read_memory to enable extra caching. */ + unsigned int m_stack : 1; + + /* True if this is a zero value, created by 'value_zero'; false + otherwise. */ + bool m_is_zero : 1; + + /* Location of value (if lval). */ + union + { + /* If lval == lval_memory, this is the address in the inferior */ + CORE_ADDR address; + + /*If lval == lval_register, the value is from a register. */ + struct + { + /* Register number. */ + int regnum; + /* Frame ID of "next" frame to which a register value is relative. + If the register value is found relative to frame F, then the + frame id of F->next will be stored in next_frame_id. */ + struct frame_id next_frame_id; + } reg; + + /* Pointer to internal variable. */ + struct internalvar *internalvar; + + /* Pointer to xmethod worker. */ + struct xmethod_worker *xm_worker; + + /* If lval == lval_computed, this is a set of function pointers + to use to access and describe the value, and a closure pointer + for them to use. */ + struct + { + /* Functions to call. */ + const struct lval_funcs *funcs; + + /* Closure for those functions to use. */ + void *closure; + } computed; + } m_location {}; + + /* Describes offset of a value within lval of a structure in target + addressable memory units. Note also the member embedded_offset + below. */ + LONGEST m_offset = 0; + + /* Only used for bitfields; number of bits contained in them. */ + LONGEST m_bitsize = 0; + + /* Only used for bitfields; position of start of field. For + little-endian targets, it is the position of the LSB. For + big-endian targets, it is the position of the MSB. */ + LONGEST m_bitpos = 0; + + /* The number of references to this value. When a value is created, + the value chain holds a reference, so REFERENCE_COUNT is 1. If + release_value is called, this value is removed from the chain but + the caller of release_value now has a reference to this value. + The caller must arrange for a call to value_free later. */ + int m_reference_count = 1; + + /* Only used for bitfields; the containing value. This allows a + single read from the target when displaying multiple + bitfields. */ + value_ref_ptr m_parent; + + /* Type of the value. */ + struct type *m_type; + + /* If a value represents a C++ object, then the `type' field gives + the object's compile-time type. If the object actually belongs + to some class derived from `type', perhaps with other base + classes and additional members, then `type' is just a subobject + of the real thing, and the full object is probably larger than + `type' would suggest. + + If `type' is a dynamic class (i.e. one with a vtable), then GDB + can actually determine the object's run-time type by looking at + the run-time type information in the vtable. When this + information is available, we may elect to read in the entire + object, for several reasons: + + - When printing the value, the user would probably rather see the + full object, not just the limited portion apparent from the + compile-time type. + + - If `type' has virtual base classes, then even printing `type' + alone may require reaching outside the `type' portion of the + object to wherever the virtual base class has been stored. + + When we store the entire object, `enclosing_type' is the run-time + type -- the complete object -- and `embedded_offset' is the + offset of `type' within that larger type, in target addressable memory + units. The value_contents() macro takes `embedded_offset' into account, + so most GDB code continues to see the `type' portion of the value, just + as the inferior would. + + If `type' is a pointer to an object, then `enclosing_type' is a + pointer to the object's run-time type, and `pointed_to_offset' is + the offset in target addressable memory units from the full object + to the pointed-to object -- that is, the value `embedded_offset' would + have if we followed the pointer and fetched the complete object. + (I don't really see the point. Why not just determine the + run-time type when you indirect, and avoid the special case? The + contents don't matter until you indirect anyway.) + + If we're not doing anything fancy, `enclosing_type' is equal to + `type', and `embedded_offset' is zero, so everything works + normally. */ + struct type *m_enclosing_type; + LONGEST m_embedded_offset = 0; + LONGEST m_pointed_to_offset = 0; + + /* Actual contents of the value. Target byte-order. + + May be nullptr if the value is lazy or is entirely optimized out. + Guaranteed to be non-nullptr otherwise. */ + gdb::unique_xmalloc_ptr m_contents; + + /* Unavailable ranges in CONTENTS. We mark unavailable ranges, + rather than available, since the common and default case is for a + value to be available. This is filled in at value read time. + The unavailable ranges are tracked in bits. Note that a contents + bit that has been optimized out doesn't really exist in the + program, so it can't be marked unavailable either. */ + std::vector m_unavailable; + + /* Likewise, but for optimized out contents (a chunk of the value of + a variable that does not actually exist in the program). If LVAL + is lval_register, this is a register ($pc, $sp, etc., never a + program variable) that has not been saved in the frame. Not + saved registers and optimized-out program variables values are + treated pretty much the same, except not-saved registers have a + different string representation and related error strings. */ + std::vector m_optimized_out; +}; + /* Type of the value. */ extern struct type *value_type (const struct value *);