From 7cf57bc5be656c62cc6b80280a9eddad2b8ded3f Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 31 Jan 2023 07:46:56 -0700 Subject: [PATCH] Move struct value to value.h 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'. Approved-By: Simon Marchi --- gdb/value.c | 225 --------------------------------------------------- gdb/value.h | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 223 insertions(+), 230 deletions(-) diff --git a/gdb/value.c b/gdb/value.c index be981b1d3a0..0d68a90f537 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. */ - ULONGEST 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,204 +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_in_history (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; - - /* True if this a value recorded in value history; false otherwise. */ - bool m_in_history : 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; - - /* This is only non-zero for values of TYPE_CODE_ARRAY and if the size of - the array in inferior memory is greater than max_value_size. If these - conditions are met then, when the value is loaded from the inferior - GDB will only load a portion of the array into memory, and - limited_length will be set to indicate the length in octets that were - loaded from the inferior. */ - ULONGEST m_limited_length = 0; -}; - value::~value () { if (VALUE_LVAL (this) == lval_computed) diff --git a/gdb/value.h b/gdb/value.h index c002ad09b45..2c2d7738e94 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. */ + ULONGEST 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,204 @@ 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_in_history (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; + + /* True if this a value recorded in value history; false otherwise. */ + bool m_in_history : 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; + + /* This is only non-zero for values of TYPE_CODE_ARRAY and if the size of + the array in inferior memory is greater than max_value_size. If these + conditions are met then, when the value is loaded from the inferior + GDB will only load a portion of the array into memory, and + limited_length will be set to indicate the length in octets that were + loaded from the inferior. */ + ULONGEST m_limited_length = 0; +}; + /* Type of the value. */ extern struct type *value_type (const struct value *); -- 2.30.2