| Index: gdb/value.c
|
| diff --git a/gdb/value.c b/gdb/value.c
|
| index 2a210d75a53e8aca081b131d8164f5789c8bb14e..218d4d5cbadf035deac53abf00cd8fe40233fb3c 100644
|
| --- a/gdb/value.c
|
| +++ b/gdb/value.c
|
| @@ -41,6 +41,7 @@
|
| #include "python/python.h"
|
| #include <ctype.h>
|
| #include "tracepoint.h"
|
| +#include "cp-abi.h"
|
|
|
| /* Prototypes for exported functions. */
|
|
|
| @@ -167,6 +168,9 @@ ranges_contain (VEC(range_s) *ranges, int offset, int length)
|
|
|
| static struct cmd_list_element *functionlist;
|
|
|
| +/* Note that the fields in this structure are arranged to save a bit
|
| + of memory. */
|
| +
|
| struct value
|
| {
|
| /* Type of value; either not an lval, or one of the various
|
| @@ -174,7 +178,37 @@ struct value
|
| enum lval_type lval;
|
|
|
| /* Is it modifiable? Only relevant if lval != not_lval. */
|
| - int modifiable;
|
| + unsigned int 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 lazy : 1;
|
| +
|
| + /* If nonzero, this is the value of a variable which does not
|
| + actually exist in the program. */
|
| + unsigned int optimized_out : 1;
|
| +
|
| + /* If value is a variable, is it initialized or not. */
|
| + unsigned int 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 stack : 1;
|
| +
|
| + /* If the value has been released. */
|
| + unsigned int released : 1;
|
|
|
| /* Location of value (if lval). */
|
| union
|
| @@ -215,6 +249,13 @@ struct value
|
| gdbarch_bits_big_endian=1 targets, it is the position of the MSB. */
|
| int bitpos;
|
|
|
| + /* 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 reference_count;
|
| +
|
| /* Only used for bitfields; the containing value. This allows a
|
| single read from the target when displaying multiple
|
| bitfields. */
|
| @@ -280,33 +321,6 @@ struct value
|
| /* Register number if the value is from a register. */
|
| short regnum;
|
|
|
| - /* 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! */
|
| - char lazy;
|
| -
|
| - /* If nonzero, this is the value of a variable which does not
|
| - actually exist in the program. */
|
| - char optimized_out;
|
| -
|
| - /* If value is a variable, is it initialized or not. */
|
| - int initialized;
|
| -
|
| - /* If value is from the stack. If this is set, read_stack will be
|
| - used instead of read_memory to enable extra caching. */
|
| - int stack;
|
| -
|
| /* Actual contents of the value. Target byte-order. NULL or not
|
| valid if lazy is nonzero. */
|
| gdb_byte *contents;
|
| @@ -315,13 +329,6 @@ struct value
|
| rather than available, since the common and default case is for a
|
| value to be available. This is filled in at value read time. */
|
| VEC(range_s) *unavailable;
|
| -
|
| - /* 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 reference_count;
|
| };
|
|
|
| int
|
| @@ -799,6 +806,14 @@ value_parent (struct value *value)
|
| return value->parent;
|
| }
|
|
|
| +/* See value.h. */
|
| +
|
| +void
|
| +set_value_parent (struct value *value, struct value *parent)
|
| +{
|
| + value->parent = parent;
|
| +}
|
| +
|
| gdb_byte *
|
| value_contents_raw (struct value *value)
|
| {
|
| @@ -819,6 +834,50 @@ value_enclosing_type (struct value *value)
|
| return value->enclosing_type;
|
| }
|
|
|
| +/* Look at value.h for description. */
|
| +
|
| +struct type *
|
| +value_actual_type (struct value *value, int resolve_simple_types,
|
| + int *real_type_found)
|
| +{
|
| + struct value_print_options opts;
|
| + struct type *result;
|
| +
|
| + get_user_print_options (&opts);
|
| +
|
| + if (real_type_found)
|
| + *real_type_found = 0;
|
| + result = value_type (value);
|
| + if (opts.objectprint)
|
| + {
|
| + /* If result's target type is TYPE_CODE_STRUCT, proceed to
|
| + fetch its rtti type. */
|
| + if ((TYPE_CODE (result) == TYPE_CODE_PTR
|
| + || TYPE_CODE (result) == TYPE_CODE_REF)
|
| + && TYPE_CODE (check_typedef (TYPE_TARGET_TYPE (result)))
|
| + == TYPE_CODE_STRUCT)
|
| + {
|
| + struct type *real_type;
|
| +
|
| + real_type = value_rtti_indirect_type (value, NULL, NULL, NULL);
|
| + if (real_type)
|
| + {
|
| + if (real_type_found)
|
| + *real_type_found = 1;
|
| + result = real_type;
|
| + }
|
| + }
|
| + else if (resolve_simple_types)
|
| + {
|
| + if (real_type_found)
|
| + *real_type_found = 1;
|
| + result = value_enclosing_type (value);
|
| + }
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| static void
|
| require_not_optimized_out (const struct value *value)
|
| {
|
| @@ -1094,7 +1153,10 @@ value_address (const struct value *value)
|
| if (value->lval == lval_internalvar
|
| || value->lval == lval_internalvar_component)
|
| return 0;
|
| - return value->location.address + value->offset;
|
| + if (value->parent != NULL)
|
| + return value_address (value->parent) + value->offset;
|
| + else
|
| + return value->location.address + value->offset;
|
| }
|
|
|
| CORE_ADDR
|
| @@ -1205,6 +1267,7 @@ value_free_to_mark (struct value *mark)
|
| for (val = all_values; val && val != mark; val = next)
|
| {
|
| next = val->next;
|
| + val->released = 1;
|
| value_free (val);
|
| }
|
| all_values = val;
|
| @@ -1223,6 +1286,7 @@ free_all_values (void)
|
| for (val = all_values; val; val = next)
|
| {
|
| next = val->next;
|
| + val->released = 1;
|
| value_free (val);
|
| }
|
|
|
| @@ -1255,6 +1319,7 @@ release_value (struct value *val)
|
| {
|
| all_values = val->next;
|
| val->next = NULL;
|
| + val->released = 1;
|
| return;
|
| }
|
|
|
| @@ -1264,11 +1329,26 @@ release_value (struct value *val)
|
| {
|
| v->next = val->next;
|
| val->next = NULL;
|
| + val->released = 1;
|
| break;
|
| }
|
| }
|
| }
|
|
|
| +/* If the value is not already released, release it.
|
| + If the value is already released, increment its reference count.
|
| + That is, this function ensures that the value is released from the
|
| + value chain and that the caller owns a reference to it. */
|
| +
|
| +void
|
| +release_value_or_incref (struct value *val)
|
| +{
|
| + if (val->released)
|
| + value_incref (val);
|
| + else
|
| + release_value (val);
|
| +}
|
| +
|
| /* Release all values up to mark */
|
| struct value *
|
| value_release_to_mark (struct value *mark)
|
| @@ -1277,12 +1357,15 @@ value_release_to_mark (struct value *mark)
|
| struct value *next;
|
|
|
| for (val = next = all_values; next; next = next->next)
|
| - if (next->next == mark)
|
| - {
|
| - all_values = next->next;
|
| - next->next = NULL;
|
| - return val;
|
| - }
|
| + {
|
| + if (next->next == mark)
|
| + {
|
| + all_values = next->next;
|
| + next->next = NULL;
|
| + return val;
|
| + }
|
| + next->released = 1;
|
| + }
|
| all_values = 0;
|
| return val;
|
| }
|
| @@ -1549,7 +1632,14 @@ struct internalvar
|
| struct value *value;
|
|
|
| /* The call-back routine used with INTERNALVAR_MAKE_VALUE. */
|
| - internalvar_make_value make_value;
|
| + struct
|
| + {
|
| + /* The functions to call. */
|
| + const struct internalvar_funcs *functions;
|
| +
|
| + /* The function's user-data. */
|
| + void *data;
|
| + } make_value;
|
|
|
| /* The internal function used with INTERNALVAR_FUNCTION. */
|
| struct
|
| @@ -1628,6 +1718,29 @@ lookup_only_internalvar (const char *name)
|
| return NULL;
|
| }
|
|
|
| +/* Complete NAME by comparing it to the names of internal variables.
|
| + Returns a vector of newly allocated strings, or NULL if no matches
|
| + were found. */
|
| +
|
| +VEC (char_ptr) *
|
| +complete_internalvar (const char *name)
|
| +{
|
| + VEC (char_ptr) *result = NULL;
|
| + struct internalvar *var;
|
| + int len;
|
| +
|
| + len = strlen (name);
|
| +
|
| + for (var = internalvars; var; var = var->next)
|
| + if (strncmp (var->name, name, len) == 0)
|
| + {
|
| + char *r = xstrdup (var->name);
|
| +
|
| + VEC_safe_push (char_ptr, result, r);
|
| + }
|
| +
|
| + return result;
|
| +}
|
|
|
| /* Create an internal variable with name NAME and with a void value.
|
| NAME should not normally include a dollar sign. */
|
| @@ -1648,18 +1761,39 @@ create_internalvar (const char *name)
|
| /* Create an internal variable with name NAME and register FUN as the
|
| function that value_of_internalvar uses to create a value whenever
|
| this variable is referenced. NAME should not normally include a
|
| - dollar sign. */
|
| + dollar sign. DATA is passed uninterpreted to FUN when it is
|
| + called. CLEANUP, if not NULL, is called when the internal variable
|
| + is destroyed. It is passed DATA as its only argument. */
|
|
|
| struct internalvar *
|
| -create_internalvar_type_lazy (char *name, internalvar_make_value fun)
|
| +create_internalvar_type_lazy (const char *name,
|
| + const struct internalvar_funcs *funcs,
|
| + void *data)
|
| {
|
| struct internalvar *var = create_internalvar (name);
|
|
|
| var->kind = INTERNALVAR_MAKE_VALUE;
|
| - var->u.make_value = fun;
|
| + var->u.make_value.functions = funcs;
|
| + var->u.make_value.data = data;
|
| return var;
|
| }
|
|
|
| +/* See documentation in value.h. */
|
| +
|
| +int
|
| +compile_internalvar_to_ax (struct internalvar *var,
|
| + struct agent_expr *expr,
|
| + struct axs_value *value)
|
| +{
|
| + if (var->kind != INTERNALVAR_MAKE_VALUE
|
| + || var->u.make_value.functions->compile_to_ax == NULL)
|
| + return 0;
|
| +
|
| + var->u.make_value.functions->compile_to_ax (var, expr, value,
|
| + var->u.make_value.data);
|
| + return 1;
|
| +}
|
| +
|
| /* Look up an internal variable with name NAME. NAME should not
|
| normally include a dollar sign.
|
|
|
| @@ -1732,7 +1866,8 @@ value_of_internalvar (struct gdbarch *gdbarch, struct internalvar *var)
|
| break;
|
|
|
| case INTERNALVAR_MAKE_VALUE:
|
| - val = (*var->u.make_value) (gdbarch, var);
|
| + val = (*var->u.make_value.functions->make_value) (gdbarch, var,
|
| + var->u.make_value.data);
|
| break;
|
|
|
| default:
|
| @@ -1928,6 +2063,11 @@ clear_internalvar (struct internalvar *var)
|
| xfree (var->u.string);
|
| break;
|
|
|
| + case INTERNALVAR_MAKE_VALUE:
|
| + if (var->u.make_value.functions->destroy != NULL)
|
| + var->u.make_value.functions->destroy (var->u.make_value.data);
|
| + break;
|
| +
|
| default:
|
| break;
|
| }
|
| @@ -2522,11 +2662,24 @@ value_primitive_field (struct value *arg1, int offset,
|
| /* This field is actually a base subobject, so preserve the
|
| entire object's contents for later references to virtual
|
| bases, etc. */
|
| + int boffset;
|
|
|
| /* Lazy register values with offsets are not supported. */
|
| if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
|
| value_fetch_lazy (arg1);
|
|
|
| + /* We special case virtual inheritance here because this
|
| + requires access to the contents, which we would rather avoid
|
| + for references to ordinary fields of unavailable values. */
|
| + if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno))
|
| + boffset = baseclass_offset (arg_type, fieldno,
|
| + value_contents (arg1),
|
| + value_embedded_offset (arg1),
|
| + value_address (arg1),
|
| + arg1);
|
| + else
|
| + boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
|
| +
|
| if (value_lazy (arg1))
|
| v = allocate_value_lazy (value_enclosing_type (arg1));
|
| else
|
| @@ -2537,8 +2690,7 @@ value_primitive_field (struct value *arg1, int offset,
|
| }
|
| v->type = type;
|
| v->offset = value_offset (arg1);
|
| - v->embedded_offset = (offset + value_embedded_offset (arg1)
|
| - + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8);
|
| + v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
|
| }
|
| else
|
| {
|
| @@ -2902,7 +3054,7 @@ pack_long (gdb_byte *buf, struct type *type, LONGEST num)
|
|
|
| /* Pack NUM into BUF using a target format of TYPE. */
|
|
|
| -void
|
| +static void
|
| pack_unsigned_long (gdb_byte *buf, struct type *type, ULONGEST num)
|
| {
|
| int len;
|
| @@ -3107,11 +3259,30 @@ coerce_ref_if_computed (const struct value *arg)
|
| return funcs->coerce_ref (arg);
|
| }
|
|
|
| +/* Look at value.h for description. */
|
| +
|
| +struct value *
|
| +readjust_indirect_value_type (struct value *value, struct type *enc_type,
|
| + struct type *original_type,
|
| + struct value *original_value)
|
| +{
|
| + /* Re-adjust type. */
|
| + deprecated_set_value_type (value, TYPE_TARGET_TYPE (original_type));
|
| +
|
| + /* Add embedding info. */
|
| + set_value_enclosing_type (value, enc_type);
|
| + set_value_embedded_offset (value, value_pointed_to_offset (original_value));
|
| +
|
| + /* We may be pointing to an object of some derived type. */
|
| + return value_full_object (value, NULL, 0, 0, 0);
|
| +}
|
| +
|
| struct value *
|
| coerce_ref (struct value *arg)
|
| {
|
| struct type *value_type_arg_tmp = check_typedef (value_type (arg));
|
| struct value *retval;
|
| + struct type *enc_type;
|
|
|
| retval = coerce_ref_if_computed (arg);
|
| if (retval)
|
| @@ -3120,9 +3291,14 @@ coerce_ref (struct value *arg)
|
| if (TYPE_CODE (value_type_arg_tmp) != TYPE_CODE_REF)
|
| return arg;
|
|
|
| - return value_at_lazy (TYPE_TARGET_TYPE (value_type_arg_tmp),
|
| - unpack_pointer (value_type (arg),
|
| - value_contents (arg)));
|
| + enc_type = check_typedef (value_enclosing_type (arg));
|
| + enc_type = TYPE_TARGET_TYPE (enc_type);
|
| +
|
| + retval = value_at_lazy (enc_type,
|
| + unpack_pointer (value_type (arg),
|
| + value_contents (arg)));
|
| + return readjust_indirect_value_type (retval, enc_type,
|
| + value_type_arg_tmp, arg);
|
| }
|
|
|
| struct value *
|
| @@ -3153,7 +3329,7 @@ coerce_array (struct value *arg)
|
|
|
| int
|
| using_struct_return (struct gdbarch *gdbarch,
|
| - struct type *func_type, struct type *value_type)
|
| + struct value *function, struct type *value_type)
|
| {
|
| enum type_code code = TYPE_CODE (value_type);
|
|
|
| @@ -3166,7 +3342,7 @@ using_struct_return (struct gdbarch *gdbarch,
|
| return 0;
|
|
|
| /* Probe the architecture for the return-value convention. */
|
| - return (gdbarch_return_value (gdbarch, func_type, value_type,
|
| + return (gdbarch_return_value (gdbarch, function, value_type,
|
| NULL, NULL, NULL)
|
| != RETURN_VALUE_REGISTER_CONVENTION);
|
| }
|
|
|