/* Low level packing and unpacking of values for GDB, the GNU Debugger.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2017 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "arch-utils.h"
-#include <string.h>
#include "symtab.h"
#include "gdbtypes.h"
#include "value.h"
#include "language.h"
#include "demangle.h"
#include "doublest.h"
-#include "gdb_assert.h"
#include "regcache.h"
#include "block.h"
#include "dfp.h"
#include "objfiles.h"
#include "valprint.h"
#include "cli/cli-decode.h"
-#include "exceptions.h"
#include "extension.h"
#include <ctype.h>
#include "tracepoint.h"
#include "cp-abi.h"
#include "user-regs.h"
+#include <algorithm>
/* Prototypes for exported functions. */
struct range
{
/* Lowest offset in the range. */
- int offset;
+ LONGEST offset;
/* Length of the range. */
- int length;
+ LONGEST length;
};
typedef struct range range_s;
[offset2, offset2+len2) overlap. */
static int
-ranges_overlap (int offset1, int len1,
- int offset2, int len2)
+ranges_overlap (LONGEST offset1, LONGEST len1,
+ LONGEST offset2, LONGEST len2)
{
ULONGEST h, l;
- l = max (offset1, offset2);
- h = min (offset1 + len1, offset2 + len2);
+ l = std::max (offset1, offset2);
+ h = std::min (offset1 + len1, offset2 + len2);
return (l < h);
}
OFFSET+LENGTH). */
static int
-ranges_contain (VEC(range_s) *ranges, int offset, int length)
+ranges_contain (VEC(range_s) *ranges, LONGEST offset, LONGEST length)
{
range_s what;
- int i;
+ LONGEST i;
what.offset = offset;
what.length = length;
reset, be sure to consider this use as well! */
unsigned int lazy : 1;
- /* If nonzero, this is the value of a variable that does not
- actually exist in the program. If nonzero, and LVAL is
- lval_register, this is a register ($pc, $sp, etc., never a
- program variable) that has not been saved in the frame. All
- optimized-out values are treated pretty much the same, except
- registers have a different string representation and related
- error strings. */
- unsigned int optimized_out : 1;
-
/* If value is a variable, is it initialized or not. */
unsigned int initialized : 1;
/* If the value has been released. */
unsigned int released : 1;
- /* Register number if the value is from a register. */
- short regnum;
-
/* Location of value (if lval). */
union
{
- /* If lval == lval_memory, this is the address in the inferior.
- If lval == lval_register, this is the byte offset into the
- registers structure. */
+ /* 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. */
} computed;
} location;
- /* Describes offset of a value within lval of a structure in bytes.
- If lval == lval_memory, this is an offset to the address. If
- lval == lval_register, this is a further offset from
- location.address within the registers structure. Note also the
- member embedded_offset below. */
- int offset;
+ /* Describes offset of a value within lval of a structure in target
+ addressable memory units. Note also the member embedded_offset
+ below. */
+ LONGEST offset;
/* Only used for bitfields; number of bits contained in them. */
- int bitsize;
+ LONGEST bitsize;
/* Only used for bitfields; position of start of field. For
gdbarch_bits_big_endian=0 targets, it is the position of the LSB. For
gdbarch_bits_big_endian=1 targets, it is the position of the MSB. */
- int bitpos;
+ LONGEST 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
bitfields. */
struct value *parent;
- /* Frame register value is relative to. This will be described in
- the lval enum above as "lval_register". */
- struct frame_id frame_id;
-
/* Type of the value. */
struct type *type;
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 bytes. 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.
+ 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 bytes 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.)
+ 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 *enclosing_type;
- int embedded_offset;
- int pointed_to_offset;
+ LONGEST embedded_offset;
+ LONGEST pointed_to_offset;
/* Values are stored in a chain, so that they can be deleted easily
over calls to the inferior. Values assigned to internal
/* 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. */
+ 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. */
VEC(range_s) *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. */
+ VEC(range_s) *optimized_out;
};
+/* See value.h. */
+
+struct gdbarch *
+get_value_arch (const struct value *value)
+{
+ return get_type_arch (value_type (value));
+}
+
int
-value_bits_available (const struct value *value, int offset, int length)
+value_bits_available (const struct value *value, LONGEST offset, LONGEST length)
{
gdb_assert (!value->lazy);
}
int
-value_bytes_available (const struct value *value, int offset, int length)
+value_bytes_available (const struct value *value,
+ LONGEST offset, LONGEST length)
{
return value_bits_available (value,
offset * TARGET_CHAR_BIT,
length * TARGET_CHAR_BIT);
}
+int
+value_bits_any_optimized_out (const struct value *value, int bit_offset, int bit_length)
+{
+ gdb_assert (!value->lazy);
+
+ return ranges_contain (value->optimized_out, bit_offset, bit_length);
+}
+
int
value_entirely_available (struct value *value)
{
return 0;
}
-int
-value_entirely_unavailable (struct value *value)
+/* Returns true if VALUE is entirely covered by RANGES. If the value
+ is lazy, it'll be read now. Note that RANGE is a pointer to
+ pointer because reading the value might change *RANGE. */
+
+static int
+value_entirely_covered_by_range_vector (struct value *value,
+ VEC(range_s) **ranges)
{
- /* We can only tell whether the whole value is available when we try
- to read it. */
+ /* We can only tell whether the whole value is optimized out /
+ unavailable when we try to read it. */
if (value->lazy)
value_fetch_lazy (value);
- if (VEC_length (range_s, value->unavailable) == 1)
+ if (VEC_length (range_s, *ranges) == 1)
{
- struct range *t = VEC_index (range_s, value->unavailable, 0);
+ struct range *t = VEC_index (range_s, *ranges, 0);
if (t->offset == 0
&& t->length == (TARGET_CHAR_BIT
return 0;
}
-void
-mark_value_bits_unavailable (struct value *value, int offset, int length)
+int
+value_entirely_unavailable (struct value *value)
+{
+ return value_entirely_covered_by_range_vector (value, &value->unavailable);
+}
+
+int
+value_entirely_optimized_out (struct value *value)
+{
+ return value_entirely_covered_by_range_vector (value, &value->optimized_out);
+}
+
+/* Insert into the vector pointed to by VECTORP the bit range starting of
+ OFFSET bits, and extending for the next LENGTH bits. */
+
+static void
+insert_into_bit_range_vector (VEC(range_s) **vectorp,
+ LONGEST offset, LONGEST length)
{
range_s newr;
int i;
*/
- i = VEC_lower_bound (range_s, value->unavailable, &newr, range_lessthan);
+ i = VEC_lower_bound (range_s, *vectorp, &newr, range_lessthan);
if (i > 0)
{
- struct range *bef = VEC_index (range_s, value->unavailable, i - 1);
+ struct range *bef = VEC_index (range_s, *vectorp, i - 1);
if (ranges_overlap (bef->offset, bef->length, offset, length))
{
/* #1 */
- ULONGEST l = min (bef->offset, offset);
- ULONGEST h = max (bef->offset + bef->length, offset + length);
+ ULONGEST l = std::min (bef->offset, offset);
+ ULONGEST h = std::max (bef->offset + bef->length, offset + length);
bef->offset = l;
bef->length = h - l;
else
{
/* #3 */
- VEC_safe_insert (range_s, value->unavailable, i, &newr);
+ VEC_safe_insert (range_s, *vectorp, i, &newr);
}
}
else
{
/* #4 */
- VEC_safe_insert (range_s, value->unavailable, i, &newr);
+ VEC_safe_insert (range_s, *vectorp, i, &newr);
}
/* Check whether the ranges following the one we've just added or
touched can be folded in (#5 above). */
- if (i + 1 < VEC_length (range_s, value->unavailable))
+ if (i + 1 < VEC_length (range_s, *vectorp))
{
struct range *t;
struct range *r;
int next = i + 1;
/* Get the range we just touched. */
- t = VEC_index (range_s, value->unavailable, i);
+ t = VEC_index (range_s, *vectorp, i);
removed = 0;
i = next;
- for (; VEC_iterate (range_s, value->unavailable, i, r); i++)
+ for (; VEC_iterate (range_s, *vectorp, i, r); i++)
if (r->offset <= t->offset + t->length)
{
ULONGEST l, h;
- l = min (t->offset, r->offset);
- h = max (t->offset + t->length, r->offset + r->length);
+ l = std::min (t->offset, r->offset);
+ h = std::max (t->offset + t->length, r->offset + r->length);
t->offset = l;
t->length = h - l;
}
if (removed != 0)
- VEC_block_remove (range_s, value->unavailable, next, removed);
+ VEC_block_remove (range_s, *vectorp, next, removed);
}
}
void
-mark_value_bytes_unavailable (struct value *value, int offset, int length)
+mark_value_bits_unavailable (struct value *value,
+ LONGEST offset, LONGEST length)
+{
+ insert_into_bit_range_vector (&value->unavailable, offset, length);
+}
+
+void
+mark_value_bytes_unavailable (struct value *value,
+ LONGEST offset, LONGEST length)
{
mark_value_bits_unavailable (value,
offset * TARGET_CHAR_BIT,
static int
find_first_range_overlap (VEC(range_s) *ranges, int pos,
- int offset, int length)
+ LONGEST offset, LONGEST length)
{
range_s *r;
int i;
return 0;
}
-/* Helper function for value_available_contents_eq. The only difference is
- that this function is bit rather than byte based.
+/* Helper struct for find_first_range_overlap_and_match and
+ value_contents_bits_eq. Keep track of which slot of a given ranges
+ vector have we last looked at. */
+
+struct ranges_and_idx
+{
+ /* The ranges. */
+ VEC(range_s) *ranges;
+
+ /* The range we've last found in RANGES. Given ranges are sorted,
+ we can start the next lookup here. */
+ int idx;
+};
- Compare LENGTH bits of VAL1's contents starting at OFFSET1 bits with
- LENGTH bits of VAL2's contents starting at OFFSET2 bits. Return true
- if the available bits match. */
+/* Helper function for value_contents_bits_eq. Compare LENGTH bits of
+ RP1's ranges starting at OFFSET1 bits with LENGTH bits of RP2's
+ ranges starting at OFFSET2 bits. Return true if the ranges match
+ and fill in *L and *H with the overlapping window relative to
+ (both) OFFSET1 or OFFSET2. */
static int
-value_available_contents_bits_eq (const struct value *val1, int offset1,
- const struct value *val2, int offset2,
- int length)
+find_first_range_overlap_and_match (struct ranges_and_idx *rp1,
+ struct ranges_and_idx *rp2,
+ LONGEST offset1, LONGEST offset2,
+ LONGEST length, ULONGEST *l, ULONGEST *h)
{
- int idx1 = 0, idx2 = 0;
-
- /* See function description in value.h. */
- gdb_assert (!val1->lazy && !val2->lazy);
+ rp1->idx = find_first_range_overlap (rp1->ranges, rp1->idx,
+ offset1, length);
+ rp2->idx = find_first_range_overlap (rp2->ranges, rp2->idx,
+ offset2, length);
- while (length > 0)
+ if (rp1->idx == -1 && rp2->idx == -1)
+ {
+ *l = length;
+ *h = length;
+ return 1;
+ }
+ else if (rp1->idx == -1 || rp2->idx == -1)
+ return 0;
+ else
{
range_s *r1, *r2;
ULONGEST l1, h1;
ULONGEST l2, h2;
- idx1 = find_first_range_overlap (val1->unavailable, idx1,
- offset1, length);
- idx2 = find_first_range_overlap (val2->unavailable, idx2,
- offset2, length);
-
- /* The usual case is for both values to be completely available. */
- if (idx1 == -1 && idx2 == -1)
- return (memcmp_with_bit_offsets (val1->contents, offset1,
- val2->contents, offset2,
- length) == 0);
- /* The contents only match equal if the available set matches as
- well. */
- else if (idx1 == -1 || idx2 == -1)
- return 0;
-
- gdb_assert (idx1 != -1 && idx2 != -1);
-
- r1 = VEC_index (range_s, val1->unavailable, idx1);
- r2 = VEC_index (range_s, val2->unavailable, idx2);
+ r1 = VEC_index (range_s, rp1->ranges, rp1->idx);
+ r2 = VEC_index (range_s, rp2->ranges, rp2->idx);
/* Get the unavailable windows intersected by the incoming
ranges. The first and last ranges that overlap the argument
range may be wider than said incoming arguments ranges. */
- l1 = max (offset1, r1->offset);
- h1 = min (offset1 + length, r1->offset + r1->length);
+ l1 = std::max (offset1, r1->offset);
+ h1 = std::min (offset1 + length, r1->offset + r1->length);
- l2 = max (offset2, r2->offset);
- h2 = min (offset2 + length, r2->offset + r2->length);
+ l2 = std::max (offset2, r2->offset);
+ h2 = std::min (offset2 + length, offset2 + r2->length);
/* Make them relative to the respective start offsets, so we can
compare them for equality. */
l2 -= offset2;
h2 -= offset2;
- /* Different availability, no match. */
+ /* Different ranges, no match. */
if (l1 != l2 || h1 != h2)
return 0;
- /* Compare the _available_ contents. */
+ *h = h1;
+ *l = l1;
+ return 1;
+ }
+}
+
+/* Helper function for value_contents_eq. The only difference is that
+ this function is bit rather than byte based.
+
+ Compare LENGTH bits of VAL1's contents starting at OFFSET1 bits
+ with LENGTH bits of VAL2's contents starting at OFFSET2 bits.
+ Return true if the available bits match. */
+
+static int
+value_contents_bits_eq (const struct value *val1, int offset1,
+ const struct value *val2, int offset2,
+ int length)
+{
+ /* Each array element corresponds to a ranges source (unavailable,
+ optimized out). '1' is for VAL1, '2' for VAL2. */
+ struct ranges_and_idx rp1[2], rp2[2];
+
+ /* See function description in value.h. */
+ gdb_assert (!val1->lazy && !val2->lazy);
+
+ /* We shouldn't be trying to compare past the end of the values. */
+ gdb_assert (offset1 + length
+ <= TYPE_LENGTH (val1->enclosing_type) * TARGET_CHAR_BIT);
+ gdb_assert (offset2 + length
+ <= TYPE_LENGTH (val2->enclosing_type) * TARGET_CHAR_BIT);
+
+ memset (&rp1, 0, sizeof (rp1));
+ memset (&rp2, 0, sizeof (rp2));
+ rp1[0].ranges = val1->unavailable;
+ rp2[0].ranges = val2->unavailable;
+ rp1[1].ranges = val1->optimized_out;
+ rp2[1].ranges = val2->optimized_out;
+
+ while (length > 0)
+ {
+ ULONGEST l = 0, h = 0; /* init for gcc -Wall */
+ int i;
+
+ for (i = 0; i < 2; i++)
+ {
+ ULONGEST l_tmp, h_tmp;
+
+ /* The contents only match equal if the invalid/unavailable
+ contents ranges match as well. */
+ if (!find_first_range_overlap_and_match (&rp1[i], &rp2[i],
+ offset1, offset2, length,
+ &l_tmp, &h_tmp))
+ return 0;
+
+ /* We're interested in the lowest/first range found. */
+ if (i == 0 || l_tmp < l)
+ {
+ l = l_tmp;
+ h = h_tmp;
+ }
+ }
+
+ /* Compare the available/valid contents. */
if (memcmp_with_bit_offsets (val1->contents, offset1,
- val2->contents, offset2, l1) != 0)
+ val2->contents, offset2, l) != 0)
return 0;
- length -= h1;
- offset1 += h1;
- offset2 += h1;
+ length -= h;
+ offset1 += h;
+ offset2 += h;
}
return 1;
}
int
-value_available_contents_eq (const struct value *val1, int offset1,
- const struct value *val2, int offset2,
- int length)
+value_contents_eq (const struct value *val1, LONGEST offset1,
+ const struct value *val2, LONGEST offset2,
+ LONGEST length)
{
- return value_available_contents_bits_eq (val1, offset1 * TARGET_CHAR_BIT,
- val2, offset2 * TARGET_CHAR_BIT,
- length * TARGET_CHAR_BIT);
+ return value_contents_bits_eq (val1, offset1 * TARGET_CHAR_BIT,
+ val2, offset2 * TARGET_CHAR_BIT,
+ length * TARGET_CHAR_BIT);
}
/* Prototypes for local functions. */
description correctly. */
check_typedef (type);
- val = (struct value *) xzalloc (sizeof (struct value));
+ val = XCNEW (struct value);
val->contents = NULL;
val->next = all_values;
all_values = val;
val->enclosing_type = type;
VALUE_LVAL (val) = not_lval;
val->location.address = 0;
- VALUE_FRAME_ID (val) = null_frame_id;
val->offset = 0;
val->bitpos = 0;
val->bitsize = 0;
- VALUE_REGNUM (val) = -1;
val->lazy = 1;
- val->optimized_out = 0;
val->embedded_offset = 0;
val->pointed_to_offset = 0;
val->modifiable = 1;
return val;
}
+/* The maximum size, in bytes, that GDB will try to allocate for a value.
+ The initial value of 64k was not selected for any specific reason, it is
+ just a reasonable starting point. */
+
+static int max_value_size = 65536; /* 64k bytes */
+
+/* It is critical that the MAX_VALUE_SIZE is at least as big as the size of
+ LONGEST, otherwise GDB will not be able to parse integer values from the
+ CLI; for example if the MAX_VALUE_SIZE could be set to 1 then GDB would
+ be unable to parse "set max-value-size 2".
+
+ As we want a consistent GDB experience across hosts with different sizes
+ of LONGEST, this arbitrary minimum value was selected, so long as this
+ is bigger than LONGEST on all GDB supported hosts we're fine. */
+
+#define MIN_VALUE_FOR_MAX_VALUE_SIZE 16
+gdb_static_assert (sizeof (LONGEST) <= MIN_VALUE_FOR_MAX_VALUE_SIZE);
+
+/* Implement the "set max-value-size" command. */
+
+static void
+set_max_value_size (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ gdb_assert (max_value_size == -1 || max_value_size >= 0);
+
+ if (max_value_size > -1 && max_value_size < MIN_VALUE_FOR_MAX_VALUE_SIZE)
+ {
+ max_value_size = MIN_VALUE_FOR_MAX_VALUE_SIZE;
+ error (_("max-value-size set too low, increasing to %d bytes"),
+ max_value_size);
+ }
+}
+
+/* Implement the "show max-value-size" command. */
+
+static void
+show_max_value_size (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ if (max_value_size == -1)
+ fprintf_filtered (file, _("Maximum value size is unlimited.\n"));
+ else
+ fprintf_filtered (file, _("Maximum value size is %d bytes.\n"),
+ max_value_size);
+}
+
+/* Called before we attempt to allocate or reallocate a buffer for the
+ contents of a value. TYPE is the type of the value for which we are
+ allocating the buffer. If the buffer is too large (based on the user
+ controllable setting) then throw an error. If this function returns
+ then we should attempt to allocate the buffer. */
+
+static void
+check_type_length_before_alloc (const struct type *type)
+{
+ unsigned int length = TYPE_LENGTH (type);
+
+ if (max_value_size > -1 && length > max_value_size)
+ {
+ if (TYPE_NAME (type) != NULL)
+ error (_("value of type `%s' requires %u bytes, which is more "
+ "than max-value-size"), TYPE_NAME (type), length);
+ else
+ error (_("value requires %u bytes, which is more than "
+ "max-value-size"), length);
+ }
+}
+
/* Allocate the contents of VAL if it has not been allocated yet. */
static void
allocate_value_contents (struct value *val)
{
if (!val->contents)
- val->contents = (gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type));
+ {
+ check_type_length_before_alloc (val->enclosing_type);
+ val->contents
+ = (gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type));
+ }
}
/* Allocate a value and its contents for type TYPE. */
{
struct value *retval = allocate_value_lazy (type);
- set_value_optimized_out (retval, 1);
+ mark_value_bytes_optimized_out (retval, 0, TYPE_LENGTH (type));
set_value_lazy (retval, 0);
return retval;
}
/* Accessor methods. */
struct value *
-value_next (struct value *value)
+value_next (const struct value *value)
{
return value->next;
}
value->type = type;
}
-int
+LONGEST
value_offset (const struct value *value)
{
return value->offset;
}
void
-set_value_offset (struct value *value, int offset)
+set_value_offset (struct value *value, LONGEST offset)
{
value->offset = offset;
}
-int
+LONGEST
value_bitpos (const struct value *value)
{
return value->bitpos;
}
void
-set_value_bitpos (struct value *value, int bit)
+set_value_bitpos (struct value *value, LONGEST bit)
{
value->bitpos = bit;
}
-int
+LONGEST
value_bitsize (const struct value *value)
{
return value->bitsize;
}
void
-set_value_bitsize (struct value *value, int bit)
+set_value_bitsize (struct value *value, LONGEST bit)
{
value->bitsize = bit;
}
struct value *
-value_parent (struct value *value)
+value_parent (const struct value *value)
{
return value->parent;
}
gdb_byte *
value_contents_raw (struct value *value)
{
+ struct gdbarch *arch = get_value_arch (value);
+ int unit_size = gdbarch_addressable_memory_unit_size (arch);
+
allocate_value_contents (value);
- return value->contents + value->embedded_offset;
+ return value->contents + value->embedded_offset * unit_size;
}
gdb_byte *
}
struct type *
-value_enclosing_type (struct value *value)
+value_enclosing_type (const struct value *value)
{
return value->enclosing_type;
}
{
/* 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)
+ if ((TYPE_CODE (result) == TYPE_CODE_PTR || TYPE_IS_REFERENCE (result))
&& TYPE_CODE (check_typedef (TYPE_TARGET_TYPE (result)))
- == TYPE_CODE_STRUCT)
+ == TYPE_CODE_STRUCT
+ && !value_optimized_out (value))
{
struct type *real_type;
static void
require_not_optimized_out (const struct value *value)
{
- if (value->optimized_out)
+ if (!VEC_empty (range_s, value->optimized_out))
{
if (value->lval == lval_register)
error (_("register has not been saved in frame"));
return result;
}
-/* Copy LENGTH bytes of SRC value's (all) contents
+/* Copy ranges in SRC_RANGE that overlap [SRC_BIT_OFFSET,
+ SRC_BIT_OFFSET+BIT_LENGTH) ranges into *DST_RANGE, adjusted. */
+
+static void
+ranges_copy_adjusted (VEC (range_s) **dst_range, int dst_bit_offset,
+ VEC (range_s) *src_range, int src_bit_offset,
+ int bit_length)
+{
+ range_s *r;
+ int i;
+
+ for (i = 0; VEC_iterate (range_s, src_range, i, r); i++)
+ {
+ ULONGEST h, l;
+
+ l = std::max (r->offset, (LONGEST) src_bit_offset);
+ h = std::min (r->offset + r->length,
+ (LONGEST) src_bit_offset + bit_length);
+
+ if (l < h)
+ insert_into_bit_range_vector (dst_range,
+ dst_bit_offset + (l - src_bit_offset),
+ h - l);
+ }
+}
+
+/* Copy the ranges metadata in SRC that overlaps [SRC_BIT_OFFSET,
+ SRC_BIT_OFFSET+BIT_LENGTH) into DST, adjusted. */
+
+static void
+value_ranges_copy_adjusted (struct value *dst, int dst_bit_offset,
+ const struct value *src, int src_bit_offset,
+ int bit_length)
+{
+ ranges_copy_adjusted (&dst->unavailable, dst_bit_offset,
+ src->unavailable, src_bit_offset,
+ bit_length);
+ ranges_copy_adjusted (&dst->optimized_out, dst_bit_offset,
+ src->optimized_out, src_bit_offset,
+ bit_length);
+}
+
+/* Copy LENGTH target addressable memory units of SRC value's (all) contents
(value_contents_all) starting at SRC_OFFSET, into DST value's (all)
contents, starting at DST_OFFSET. If unavailable contents are
being copied from SRC, the corresponding DST contents are marked
DST_OFFSET+LENGTH) range are wholly available. */
void
-value_contents_copy_raw (struct value *dst, int dst_offset,
- struct value *src, int src_offset, int length)
+value_contents_copy_raw (struct value *dst, LONGEST dst_offset,
+ struct value *src, LONGEST src_offset, LONGEST length)
{
- range_s *r;
- int i;
- int src_bit_offset, dst_bit_offset, bit_length;
+ LONGEST src_bit_offset, dst_bit_offset, bit_length;
+ struct gdbarch *arch = get_value_arch (src);
+ int unit_size = gdbarch_addressable_memory_unit_size (arch);
/* A lazy DST would make that this copy operation useless, since as
soon as DST's contents were un-lazied (by a later value_contents
replaced. Make sure to remember to implement replacing if it
turns out actually necessary. */
gdb_assert (value_bytes_available (dst, dst_offset, length));
+ gdb_assert (!value_bits_any_optimized_out (dst,
+ TARGET_CHAR_BIT * dst_offset,
+ TARGET_CHAR_BIT * length));
/* Copy the data. */
- memcpy (value_contents_all_raw (dst) + dst_offset,
- value_contents_all_raw (src) + src_offset,
- length);
+ memcpy (value_contents_all_raw (dst) + dst_offset * unit_size,
+ value_contents_all_raw (src) + src_offset * unit_size,
+ length * unit_size);
/* Copy the meta-data, adjusted. */
- src_bit_offset = src_offset * TARGET_CHAR_BIT;
- dst_bit_offset = dst_offset * TARGET_CHAR_BIT;
- bit_length = length * TARGET_CHAR_BIT;
- for (i = 0; VEC_iterate (range_s, src->unavailable, i, r); i++)
- {
- ULONGEST h, l;
+ src_bit_offset = src_offset * unit_size * HOST_CHAR_BIT;
+ dst_bit_offset = dst_offset * unit_size * HOST_CHAR_BIT;
+ bit_length = length * unit_size * HOST_CHAR_BIT;
- l = max (r->offset, src_bit_offset);
- h = min (r->offset + r->length, src_bit_offset + bit_length);
-
- if (l < h)
- mark_value_bits_unavailable (dst,
- dst_bit_offset + (l - src_bit_offset),
- h - l);
- }
+ value_ranges_copy_adjusted (dst, dst_bit_offset,
+ src, src_bit_offset,
+ bit_length);
}
/* Copy LENGTH bytes of SRC value's (all) contents
(all) contents, starting at DST_OFFSET. If unavailable contents
are being copied from SRC, the corresponding DST contents are
marked unavailable accordingly. DST must not be lazy. If SRC is
- lazy, it will be fetched now. If SRC is not valid (is optimized
- out), an error is thrown.
+ lazy, it will be fetched now.
It is assumed the contents of DST in the [DST_OFFSET,
DST_OFFSET+LENGTH) range are wholly available. */
void
-value_contents_copy (struct value *dst, int dst_offset,
- struct value *src, int src_offset, int length)
+value_contents_copy (struct value *dst, LONGEST dst_offset,
+ struct value *src, LONGEST src_offset, LONGEST length)
{
- require_not_optimized_out (src);
-
if (src->lazy)
value_fetch_lazy (src);
}
int
-value_lazy (struct value *value)
+value_lazy (const struct value *value)
{
return value->lazy;
}
}
int
-value_stack (struct value *value)
+value_stack (const struct value *value)
{
return value->stack;
}
return value_contents_raw (value);
}
-/* Return non-zero if VAL1 and VAL2 have the same contents. Note that
- this function is different from value_equal; in C the operator ==
- can return 0 even if the two values being compared are equal. */
-
-int
-value_contents_equal (struct value *val1, struct value *val2)
-{
- struct type *type1;
- struct type *type2;
-
- type1 = check_typedef (value_type (val1));
- type2 = check_typedef (value_type (val2));
- if (TYPE_LENGTH (type1) != TYPE_LENGTH (type2))
- return 0;
-
- return (memcmp (value_contents (val1), value_contents (val2),
- TYPE_LENGTH (type1)) == 0);
-}
-
int
value_optimized_out (struct value *value)
{
/* We can only know if a value is optimized out once we have tried to
fetch it. */
- if (!value->optimized_out && value->lazy)
- value_fetch_lazy (value);
+ if (VEC_empty (range_s, value->optimized_out) && value->lazy)
+ {
+ TRY
+ {
+ value_fetch_lazy (value);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ /* Fall back to checking value->optimized_out. */
+ }
+ END_CATCH
+ }
- return value->optimized_out;
+ return !VEC_empty (range_s, value->optimized_out);
}
-int
-value_optimized_out_const (const struct value *value)
-{
- return value->optimized_out;
-}
+/* Mark contents of VALUE as optimized out, starting at OFFSET bytes, and
+ the following LENGTH bytes. */
void
-set_value_optimized_out (struct value *value, int val)
+mark_value_bytes_optimized_out (struct value *value, int offset, int length)
{
- value->optimized_out = val;
+ mark_value_bits_optimized_out (value,
+ offset * TARGET_CHAR_BIT,
+ length * TARGET_CHAR_BIT);
}
-int
-value_entirely_optimized_out (const struct value *value)
-{
- if (!value->optimized_out)
- return 0;
- if (value->lval != lval_computed
- || !value->location.computed.funcs->check_any_valid)
- return 1;
- return !value->location.computed.funcs->check_any_valid (value);
-}
+/* See value.h. */
-int
-value_bits_valid (const struct value *value, int offset, int length)
+void
+mark_value_bits_optimized_out (struct value *value,
+ LONGEST offset, LONGEST length)
{
- if (!value->optimized_out)
- return 1;
- if (value->lval != lval_computed
- || !value->location.computed.funcs->check_validity)
- return 0;
- return value->location.computed.funcs->check_validity (value, offset,
- length);
+ insert_into_bit_range_vector (&value->optimized_out, offset, length);
}
int
value_bits_synthetic_pointer (const struct value *value,
- int offset, int length)
+ LONGEST offset, LONGEST length)
{
if (value->lval != lval_computed
|| !value->location.computed.funcs->check_synthetic_pointer)
length);
}
-int
-value_embedded_offset (struct value *value)
+LONGEST
+value_embedded_offset (const struct value *value)
{
return value->embedded_offset;
}
void
-set_value_embedded_offset (struct value *value, int val)
+set_value_embedded_offset (struct value *value, LONGEST val)
{
value->embedded_offset = val;
}
-int
-value_pointed_to_offset (struct value *value)
+LONGEST
+value_pointed_to_offset (const struct value *value)
{
return value->pointed_to_offset;
}
void
-set_value_pointed_to_offset (struct value *value, int val)
+set_value_pointed_to_offset (struct value *value, LONGEST val)
{
value->pointed_to_offset = val;
}
CORE_ADDR
value_address (const struct value *value)
{
- if (value->lval == lval_internalvar
- || value->lval == lval_internalvar_component)
+ if (value->lval != lval_memory)
return 0;
if (value->parent != NULL)
return value_address (value->parent) + value->offset;
- else
- return value->location.address + value->offset;
+ if (NULL != TYPE_DATA_LOCATION (value_type (value)))
+ {
+ gdb_assert (PROP_CONST == TYPE_DATA_LOCATION_KIND (value_type (value)));
+ return TYPE_DATA_LOCATION_ADDR (value_type (value));
+ }
+
+ return value->location.address + value->offset;
}
CORE_ADDR
-value_raw_address (struct value *value)
+value_raw_address (const struct value *value)
{
- if (value->lval == lval_internalvar
- || value->lval == lval_internalvar_component)
+ if (value->lval != lval_memory)
return 0;
return value->location.address;
}
void
set_value_address (struct value *value, CORE_ADDR addr)
{
- gdb_assert (value->lval != lval_internalvar
- && value->lval != lval_internalvar_component);
+ gdb_assert (value->lval == lval_memory);
value->location.address = addr;
}
}
struct frame_id *
-deprecated_value_frame_id_hack (struct value *value)
+deprecated_value_next_frame_id_hack (struct value *value)
{
- return &value->frame_id;
+ gdb_assert (value->lval == lval_register);
+ return &value->location.reg.next_frame_id;
}
-short *
+int *
deprecated_value_regnum_hack (struct value *value)
{
- return &value->regnum;
+ gdb_assert (value->lval == lval_register);
+ return &value->location.reg.regnum;
}
int
-deprecated_value_modifiable (struct value *value)
+deprecated_value_modifiable (const struct value *value)
{
return value->modifiable;
}
if (funcs->free_closure)
funcs->free_closure (val);
}
+ else if (VALUE_LVAL (val) == lval_xcallable)
+ free_xmethod_worker (val->location.xm_worker);
xfree (val->contents);
VEC_free (range_s, val->unavailable);
/* Free all values allocated since MARK was obtained by value_mark
(except for those released). */
void
-value_free_to_mark (struct value *mark)
+value_free_to_mark (const struct value *mark)
{
struct value *val;
struct value *next;
/* Release all values up to mark */
struct value *
-value_release_to_mark (struct value *mark)
+value_release_to_mark (const struct value *mark)
{
struct value *val;
struct value *next;
val->offset = arg->offset;
val->bitpos = arg->bitpos;
val->bitsize = arg->bitsize;
- VALUE_FRAME_ID (val) = VALUE_FRAME_ID (arg);
- VALUE_REGNUM (val) = VALUE_REGNUM (arg);
val->lazy = arg->lazy;
- val->optimized_out = arg->optimized_out;
val->embedded_offset = value_embedded_offset (arg);
val->pointed_to_offset = arg->pointed_to_offset;
val->modifiable = arg->modifiable;
}
val->unavailable = VEC_copy (range_s, arg->unavailable);
+ val->optimized_out = VEC_copy (range_s, arg->optimized_out);
set_value_parent (val, arg->parent);
if (VALUE_LVAL (val) == lval_computed)
{
return val;
}
+/* Return a "const" and/or "volatile" qualified version of the value V.
+ If CNST is true, then the returned value will be qualified with
+ "const".
+ if VOLTL is true, then the returned value will be qualified with
+ "volatile". */
+
+struct value *
+make_cv_value (int cnst, int voltl, struct value *v)
+{
+ struct type *val_type = value_type (v);
+ struct type *enclosing_type = value_enclosing_type (v);
+ struct value *cv_val = value_copy (v);
+
+ deprecated_set_value_type (cv_val,
+ make_cv_type (cnst, voltl, val_type, NULL));
+ set_value_enclosing_type (cv_val,
+ make_cv_type (cnst, voltl, enclosing_type, NULL));
+
+ return cv_val;
+}
+
/* Return a version of ARG that is non-lvalue. */
struct value *
return arg;
}
+/* Write contents of V at ADDR and set its lval type to be LVAL_MEMORY. */
+
+void
+value_force_lval (struct value *v, CORE_ADDR addr)
+{
+ gdb_assert (VALUE_LVAL (v) == not_lval);
+
+ write_memory (addr, value_contents_raw (v), TYPE_LENGTH (value_type (v)));
+ v->lval = lval_memory;
+ v->location.address = addr;
+}
+
void
set_value_component_location (struct value *component,
const struct value *whole)
{
+ struct type *type;
+
+ gdb_assert (whole->lval != lval_xcallable);
+
if (whole->lval == lval_internalvar)
VALUE_LVAL (component) = lval_internalvar_component;
else
if (funcs->copy_closure)
component->location.computed.closure = funcs->copy_closure (whole);
}
+
+ /* If type has a dynamic resolved location property
+ update it's value address. */
+ type = value_type (whole);
+ if (NULL != TYPE_DATA_LOCATION (type)
+ && TYPE_DATA_LOCATION_KIND (type) == PROP_CONST)
+ set_value_address (component, TYPE_DATA_LOCATION_ADDR (type));
}
-\f
/* Access to the value history. */
/* Record a new value in the value history.
from. This is a bit dubious, because then *&$1 does not just return $1
but the current contents of that location. c'est la vie... */
val->modifiable = 0;
- release_value (val);
+
+ /* The value may have already been released, in which case we're adding a
+ new reference for its entry in the history. That is why we call
+ release_value_or_incref here instead of release_value. */
+ release_value_or_incref (val);
/* Here we treat value_history_count as origin-zero
and applying to the value being stored now. */
i = value_history_count % VALUE_HISTORY_CHUNK;
if (i == 0)
{
- struct value_history_chunk *new
- = (struct value_history_chunk *)
+ struct value_history_chunk *newobj = XCNEW (struct value_history_chunk);
- xmalloc (sizeof (struct value_history_chunk));
- memset (new->values, 0, sizeof new->values);
- new->next = value_history_chain;
- value_history_chain = new;
+ newobj->next = value_history_chain;
+ value_history_chain = newobj;
}
value_history_chain->values[i] = val;
}
}
\f
+enum internalvar_kind
+{
+ /* The internal variable is empty. */
+ INTERNALVAR_VOID,
+
+ /* The value of the internal variable is provided directly as
+ a GDB value object. */
+ INTERNALVAR_VALUE,
+
+ /* A fresh value is computed via a call-back routine on every
+ access to the internal variable. */
+ INTERNALVAR_MAKE_VALUE,
+
+ /* The internal variable holds a GDB internal convenience function. */
+ INTERNALVAR_FUNCTION,
+
+ /* The variable holds an integer value. */
+ INTERNALVAR_INTEGER,
+
+ /* The variable holds a GDB-provided string. */
+ INTERNALVAR_STRING,
+};
+
+union internalvar_data
+{
+ /* A value object used with INTERNALVAR_VALUE. */
+ struct value *value;
+
+ /* The call-back routine used with INTERNALVAR_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
+ {
+ struct internal_function *function;
+ /* True if this is the canonical name for the function. */
+ int canonical;
+ } fn;
+
+ /* An integer value used with INTERNALVAR_INTEGER. */
+ struct
+ {
+ /* If type is non-NULL, it will be used as the type to generate
+ a value for this internal variable. If type is NULL, a default
+ integer type for the architecture is used. */
+ struct type *type;
+ LONGEST val;
+ } integer;
+
+ /* A string value used with INTERNALVAR_STRING. */
+ char *string;
+};
+
/* Internal variables. These are variables within the debugger
that hold values assigned by debugger commands.
The user refers to them with a '$' prefix
enum internalvar_kind specifies the kind, and union internalvar_data
provides the data associated with this particular kind. */
- enum internalvar_kind
- {
- /* The internal variable is empty. */
- INTERNALVAR_VOID,
-
- /* The value of the internal variable is provided directly as
- a GDB value object. */
- INTERNALVAR_VALUE,
-
- /* A fresh value is computed via a call-back routine on every
- access to the internal variable. */
- INTERNALVAR_MAKE_VALUE,
-
- /* The internal variable holds a GDB internal convenience function. */
- INTERNALVAR_FUNCTION,
-
- /* The variable holds an integer value. */
- INTERNALVAR_INTEGER,
-
- /* The variable holds a GDB-provided string. */
- INTERNALVAR_STRING,
-
- } kind;
-
- union internalvar_data
- {
- /* A value object used with INTERNALVAR_VALUE. */
- struct value *value;
+ enum internalvar_kind kind;
- /* The call-back routine used with INTERNALVAR_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
- {
- struct internal_function *function;
- /* True if this is the canonical name for the function. */
- int canonical;
- } fn;
-
- /* An integer value used with INTERNALVAR_INTEGER. */
- struct
- {
- /* If type is non-NULL, it will be used as the type to generate
- a value for this internal variable. If type is NULL, a default
- integer type for the architecture is used. */
- struct type *type;
- LONGEST val;
- } integer;
-
- /* A string value used with INTERNALVAR_STRING. */
- char *string;
- } u;
+ union internalvar_data u;
};
static struct internalvar *internalvars;
struct internalvar* intvar;
/* Parse the expression - this is taken from set_command(). */
- struct expression *expr = parse_expression (args);
- register struct cleanup *old_chain =
- make_cleanup (free_current_contents, &expr);
+ expression_up expr = parse_expression (args);
/* Validate the expression.
Was the expression an assignment?
/* Only evaluate the expression if the lvalue is void.
This may still fail if the expresssion is invalid. */
if (intvar->kind == INTERNALVAR_VOID)
- evaluate_expression (expr);
-
- do_cleanups (old_chain);
+ evaluate_expression (expr.get ());
}
struct internalvar *
create_internalvar (const char *name)
{
- struct internalvar *var;
+ struct internalvar *var = XNEW (struct internalvar);
- var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
var->name = concat (name, (char *)NULL);
var->kind = INTERNALVAR_VOID;
var->next = internalvars;
}
void
-set_internalvar_component (struct internalvar *var, int offset, int bitpos,
- int bitsize, struct value *newval)
+set_internalvar_component (struct internalvar *var,
+ LONGEST offset, LONGEST bitpos,
+ LONGEST bitsize, struct value *newval)
{
gdb_byte *addr;
+ struct gdbarch *arch;
+ int unit_size;
switch (var->kind)
{
case INTERNALVAR_VALUE:
addr = value_contents_writeable (var->u.value);
+ arch = get_value_arch (var->u.value);
+ unit_size = gdbarch_addressable_memory_unit_size (arch);
if (bitsize)
modify_field (value_type (var->u.value), addr + offset,
value_as_long (newval), bitpos, bitsize);
else
- memcpy (addr + offset, value_contents (newval),
+ memcpy (addr + offset * unit_size, value_contents (newval),
TYPE_LENGTH (value_type (newval)));
break;
call error () until new_data is installed into the var->u to avoid
leaking memory. */
release_value (new_data.value);
+
+ /* Internal variables which are created from values with a dynamic
+ location don't need the location property of the origin anymore.
+ The resolved dynamic location is used prior then any other address
+ when accessing the value.
+ If we keep it, we would still refer to the origin value.
+ Remove the location property in case it exist. */
+ remove_dyn_prop (DYN_PROP_DATA_LOCATION, value_type (new_data.value));
+
break;
}
}
char *
-internalvar_name (struct internalvar *var)
+internalvar_name (const struct internalvar *var)
{
return var->name;
}
function_destroyer (struct cmd_list_element *self, void *ignore)
{
xfree ((char *) self->name);
- xfree (self->doc);
+ xfree ((char *) self->doc);
}
/* Add a new internal function. NAME is the name of the function; DOC
get_user_print_options (&opts);
for (var = internalvars; var; var = var->next)
{
- volatile struct gdb_exception ex;
if (!varseen)
{
}
printf_filtered (("$%s = "), var->name);
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
struct value *val;
val = value_of_internalvar (gdbarch, var);
value_print (val, gdb_stdout, &opts);
}
- if (ex.reason < 0)
- fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message);
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message);
+ }
+ END_CATCH
+
printf_filtered (("\n"));
}
if (!varseen)
}
}
\f
+/* Return the TYPE_CODE_XMETHOD value corresponding to WORKER. */
+
+struct value *
+value_of_xmethod (struct xmethod_worker *worker)
+{
+ if (worker->value == NULL)
+ {
+ struct value *v;
+
+ v = allocate_value (builtin_type (target_gdbarch ())->xmethod);
+ v->lval = lval_xcallable;
+ v->location.xm_worker = worker;
+ v->modifiable = 0;
+ worker->value = v;
+ }
+
+ return worker->value;
+}
+
+/* Return the type of the result of TYPE_CODE_XMETHOD value METHOD. */
+
+struct type *
+result_type_of_xmethod (struct value *method, int argc, struct value **argv)
+{
+ gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD
+ && method->lval == lval_xcallable && argc > 0);
+
+ return get_xmethod_result_type (method->location.xm_worker,
+ argv[0], argv + 1, argc - 1);
+}
+
+/* Call the xmethod corresponding to the TYPE_CODE_XMETHOD value METHOD. */
+
+struct value *
+call_xmethod (struct value *method, int argc, struct value **argv)
+{
+ gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD
+ && method->lval == lval_xcallable && argc > 0);
+
+ return invoke_xmethod (method->location.xm_worker,
+ argv[0], argv + 1, argc - 1);
+}
+\f
/* Extract a value as a C number (either long or double).
Knows how to convert fixed values to double, or
floating values to long.
ABI-specific code is a more reasonable place to handle it. */
if (TYPE_CODE (value_type (val)) != TYPE_CODE_PTR
- && TYPE_CODE (value_type (val)) != TYPE_CODE_REF
+ && !TYPE_IS_REFERENCE (value_type (val))
&& gdbarch_integer_to_address_p (gdbarch))
return gdbarch_integer_to_address (gdbarch, value_type (val),
value_contents (val));
return extract_signed_integer (valaddr, len, byte_order);
case TYPE_CODE_FLT:
- return extract_typed_floating (valaddr, type);
+ return (LONGEST) extract_typed_floating (valaddr, type);
case TYPE_CODE_DECFLOAT:
/* libdecnumber has a function to convert from decimal to integer, but
it doesn't work when the decimal number has a fractional part. */
- return decimal_to_doublest (valaddr, len, byte_order);
+ return (LONGEST) decimal_to_doublest (valaddr, len, byte_order);
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
+ case TYPE_CODE_RVALUE_REF:
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
return extract_typed_address (valaddr, type);
int nosign;
*invp = 0; /* Assume valid. */
- CHECK_TYPEDEF (type);
+ type = check_typedef (type);
code = TYPE_CODE (type);
len = TYPE_LENGTH (type);
nosign = TYPE_UNSIGNED (type);
{
const char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
/* TYPE_FIELD_NAME (type, fieldno); */
- struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0);
+ struct block_symbol sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0);
- if (sym == NULL)
+ if (sym.symbol == NULL)
{
/* With some compilers, e.g. HP aCC, static data members are
reported as non-debuggable symbols. */
else
{
retval = value_at_lazy (TYPE_FIELD_TYPE (type, fieldno),
- MSYMBOL_VALUE_ADDRESS (msym.minsym));
+ BMSYMBOL_VALUE_ADDRESS (msym));
}
}
else
- retval = value_of_variable (sym, NULL);
+ retval = value_of_variable (sym.symbol, sym.block);
break;
}
default:
void
set_value_enclosing_type (struct value *val, struct type *new_encl_type)
{
- if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val)))
- val->contents =
- (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type));
+ if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val)))
+ {
+ check_type_length_before_alloc (new_encl_type);
+ val->contents
+ = (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type));
+ }
val->enclosing_type = new_encl_type;
}
FIELDNO says which field. */
struct value *
-value_primitive_field (struct value *arg1, int offset,
+value_primitive_field (struct value *arg1, LONGEST offset,
int fieldno, struct type *arg_type)
{
struct value *v;
struct type *type;
+ struct gdbarch *arch = get_value_arch (arg1);
+ int unit_size = gdbarch_addressable_memory_unit_size (arch);
- CHECK_TYPEDEF (arg_type);
+ arg_type = check_typedef (arg_type);
type = TYPE_FIELD_TYPE (arg_type, fieldno);
/* Call check_typedef on our type to make sure that, if TYPE
bit. Assume that the address, offset, and embedded offset
are sufficiently aligned. */
- int bitpos = TYPE_FIELD_BITPOS (arg_type, fieldno);
- int container_bitsize = TYPE_LENGTH (type) * 8;
+ LONGEST bitpos = TYPE_FIELD_BITPOS (arg_type, fieldno);
+ LONGEST container_bitsize = TYPE_LENGTH (type) * 8;
- if (arg1->optimized_out)
- v = allocate_optimized_out_value (type);
+ v = allocate_value_lazy (type);
+ v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+ if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize
+ && TYPE_LENGTH (type) <= (int) sizeof (LONGEST))
+ v->bitpos = bitpos % container_bitsize;
else
- {
- v = allocate_value_lazy (type);
- v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno);
- if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize
- && TYPE_LENGTH (type) <= (int) sizeof (LONGEST))
- v->bitpos = bitpos % container_bitsize;
- else
- v->bitpos = bitpos % 8;
- v->offset = (value_embedded_offset (arg1)
- + offset
- + (bitpos - v->bitpos) / 8);
- set_value_parent (v, arg1);
- if (!value_lazy (arg1))
- value_fetch_lazy (v);
- }
+ v->bitpos = bitpos % 8;
+ v->offset = (value_embedded_offset (arg1)
+ + offset
+ + (bitpos - v->bitpos) / 8);
+ set_value_parent (v, arg1);
+ if (!value_lazy (arg1))
+ value_fetch_lazy (v);
}
else if (fieldno < TYPE_N_BASECLASSES (arg_type))
{
/* This field is actually a base subobject, so preserve the
entire object's contents for later references to virtual
bases, etc. */
- int boffset;
+ LONGEST boffset;
/* Lazy register values with offsets are not supported. */
if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
value_fetch_lazy (arg1);
- /* The optimized_out flag is only set correctly once a lazy value is
- loaded, having just loaded some lazy values we should check the
- optimized out case now. */
- if (arg1->optimized_out)
- v = allocate_optimized_out_value (type);
+ /* 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
- {
- /* 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;
+ boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
- if (value_lazy (arg1))
- v = allocate_value_lazy (value_enclosing_type (arg1));
- else
- {
- v = allocate_value (value_enclosing_type (arg1));
- value_contents_copy_raw (v, 0, arg1, 0,
- TYPE_LENGTH (value_enclosing_type (arg1)));
- }
- v->type = type;
- v->offset = value_offset (arg1);
- v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
+ if (value_lazy (arg1))
+ v = allocate_value_lazy (value_enclosing_type (arg1));
+ else
+ {
+ v = allocate_value (value_enclosing_type (arg1));
+ value_contents_copy_raw (v, 0, arg1, 0,
+ TYPE_LENGTH (value_enclosing_type (arg1)));
}
+ v->type = type;
+ v->offset = value_offset (arg1);
+ v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
+ }
+ else if (NULL != TYPE_DATA_LOCATION (type))
+ {
+ /* Field is a dynamic data member. */
+
+ gdb_assert (0 == offset);
+ /* We expect an already resolved data location. */
+ gdb_assert (PROP_CONST == TYPE_DATA_LOCATION_KIND (type));
+ /* For dynamic data types defer memory allocation
+ until we actual access the value. */
+ v = allocate_value_lazy (type);
}
else
{
/* Plain old data member */
- offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+ offset += (TYPE_FIELD_BITPOS (arg_type, fieldno)
+ / (HOST_CHAR_BIT * unit_size));
/* Lazy register values with offsets are not supported. */
if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
value_fetch_lazy (arg1);
- /* The optimized_out flag is only set correctly once a lazy value is
- loaded, having just loaded some lazy values we should check for
- the optimized out case now. */
- if (arg1->optimized_out)
- v = allocate_optimized_out_value (type);
- else if (value_lazy (arg1))
+ if (value_lazy (arg1))
v = allocate_value_lazy (type);
else
{
v = allocate_value (type);
value_contents_copy_raw (v, value_embedded_offset (v),
arg1, value_embedded_offset (arg1) + offset,
- TYPE_LENGTH (type));
+ type_length_units (type));
}
v->offset = (value_offset (arg1) + offset
+ value_embedded_offset (arg1));
}
set_value_component_location (v, arg1);
- VALUE_REGNUM (v) = VALUE_REGNUM (arg1);
- VALUE_FRAME_ID (v) = VALUE_FRAME_ID (arg1);
return v;
}
struct value *
value_fn_field (struct value **arg1p, struct fn_field *f,
int j, struct type *type,
- int offset)
+ LONGEST offset)
{
struct value *v;
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
struct symbol *sym;
struct bound_minimal_symbol msym;
- sym = lookup_symbol (physname, 0, VAR_DOMAIN, 0);
+ sym = lookup_symbol (physname, 0, VAR_DOMAIN, 0).symbol;
if (sym != NULL)
{
memset (&msym, 0, sizeof (msym));
}
v = allocate_value (ftype);
+ VALUE_LVAL (v) = lval_memory;
if (sym)
{
set_value_address (v, BLOCK_START (SYMBOL_BLOCK_VALUE (sym)));
set_value_address (v,
gdbarch_convert_from_func_ptr_addr
- (gdbarch, MSYMBOL_VALUE_ADDRESS (msym.minsym), ¤t_target));
+ (gdbarch, BMSYMBOL_VALUE_ADDRESS (msym), ¤t_target));
}
if (arg1p)
\f
-/* Helper function for both unpack_value_bits_as_long and
- unpack_bits_as_long. See those functions for more details on the
- interface; the only difference is that this function accepts either
- a NULL or a non-NULL ORIGINAL_VALUE. */
+/* Unpack a bitfield of the specified FIELD_TYPE, from the object at
+ VALADDR, and store the result in *RESULT.
+ The bitfield starts at BITPOS bits and contains BITSIZE bits.
+
+ Extracting bits depends on endianness of the machine. Compute the
+ number of least significant bits to discard. For big endian machines,
+ we compute the total number of bits in the anonymous object, subtract
+ off the bit count from the MSB of the object to the MSB of the
+ bitfield, then the size of the bitfield, which leaves the LSB discard
+ count. For little endian machines, the discard count is simply the
+ number of bits from the LSB of the anonymous object to the LSB of the
+ bitfield.
-static int
-unpack_value_bits_as_long_1 (struct type *field_type, const gdb_byte *valaddr,
- int embedded_offset, int bitpos, int bitsize,
- const struct value *original_value,
- LONGEST *result)
+ If the field is signed, we also do sign extension. */
+
+static LONGEST
+unpack_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
+ LONGEST bitpos, LONGEST bitsize)
{
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (field_type));
ULONGEST val;
ULONGEST valmask;
int lsbcount;
- int bytes_read;
- int read_offset;
+ LONGEST bytes_read;
+ LONGEST read_offset;
/* Read the minimum number of bytes required; there may not be
enough bytes to read an entire ULONGEST. */
- CHECK_TYPEDEF (field_type);
+ field_type = check_typedef (field_type);
if (bitsize)
bytes_read = ((bitpos % 8) + bitsize + 7) / 8;
else
read_offset = bitpos / 8;
- if (original_value != NULL
- && !value_bits_available (original_value, embedded_offset + bitpos,
- bitsize))
- return 0;
-
- val = extract_unsigned_integer (valaddr + embedded_offset + read_offset,
+ val = extract_unsigned_integer (valaddr + read_offset,
bytes_read, byte_order);
/* Extract bits. See comment above. */
}
}
- *result = val;
- return 1;
-}
-
-/* Unpack a bitfield of the specified FIELD_TYPE, from the object at
- VALADDR + EMBEDDED_OFFSET, and store the result in *RESULT.
- VALADDR points to the contents of ORIGINAL_VALUE, which must not be
- NULL. The bitfield starts at BITPOS bits and contains BITSIZE
- bits.
-
- Returns false if the value contents are unavailable, otherwise
- returns true, indicating a valid value has been stored in *RESULT.
-
- Extracting bits depends on endianness of the machine. Compute the
- number of least significant bits to discard. For big endian machines,
- we compute the total number of bits in the anonymous object, subtract
- off the bit count from the MSB of the object to the MSB of the
- bitfield, then the size of the bitfield, which leaves the LSB discard
- count. For little endian machines, the discard count is simply the
- number of bits from the LSB of the anonymous object to the LSB of the
- bitfield.
-
- If the field is signed, we also do sign extension. */
-
-int
-unpack_value_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
- int embedded_offset, int bitpos, int bitsize,
- const struct value *original_value,
- LONGEST *result)
-{
- gdb_assert (original_value != NULL);
-
- return unpack_value_bits_as_long_1 (field_type, valaddr, embedded_offset,
- bitpos, bitsize, original_value, result);
-
-}
-
-/* Unpack a field FIELDNO of the specified TYPE, from the object at
- VALADDR + EMBEDDED_OFFSET. VALADDR points to the contents of
- ORIGINAL_VALUE. See unpack_value_bits_as_long for more
- details. */
-
-static int
-unpack_value_field_as_long_1 (struct type *type, const gdb_byte *valaddr,
- int embedded_offset, int fieldno,
- const struct value *val, LONGEST *result)
-{
- int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
- int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
- struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
-
- return unpack_value_bits_as_long_1 (field_type, valaddr, embedded_offset,
- bitpos, bitsize, val,
- result);
+ return val;
}
/* Unpack a field FIELDNO of the specified TYPE, from the object at
int
unpack_value_field_as_long (struct type *type, const gdb_byte *valaddr,
- int embedded_offset, int fieldno,
+ LONGEST embedded_offset, int fieldno,
const struct value *val, LONGEST *result)
{
+ int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+ int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
+ int bit_offset;
+
gdb_assert (val != NULL);
- return unpack_value_field_as_long_1 (type, valaddr, embedded_offset,
- fieldno, val, result);
+ bit_offset = embedded_offset * TARGET_CHAR_BIT + bitpos;
+ if (value_bits_any_optimized_out (val, bit_offset, bitsize)
+ || !value_bits_available (val, bit_offset, bitsize))
+ return 0;
+
+ *result = unpack_bits_as_long (field_type, valaddr + embedded_offset,
+ bitpos, bitsize);
+ return 1;
}
/* Unpack a field FIELDNO of the specified TYPE, from the anonymous
- object at VALADDR. See unpack_value_bits_as_long for more details.
- This function differs from unpack_value_field_as_long in that it
- operates without a struct value object. */
+ object at VALADDR. See unpack_bits_as_long for more details. */
LONGEST
unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
{
- LONGEST result;
+ int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+ int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
- unpack_value_field_as_long_1 (type, valaddr, 0, fieldno, NULL, &result);
- return result;
+ return unpack_bits_as_long (field_type, valaddr, bitpos, bitsize);
+}
+
+/* Unpack a bitfield of BITSIZE bits found at BITPOS in the object at
+ VALADDR + EMBEDDEDOFFSET that has the type of DEST_VAL and store
+ the contents in DEST_VAL, zero or sign extending if the type of
+ DEST_VAL is wider than BITSIZE. VALADDR points to the contents of
+ VAL. If the VAL's contents required to extract the bitfield from
+ are unavailable/optimized out, DEST_VAL is correspondingly
+ marked unavailable/optimized out. */
+
+void
+unpack_value_bitfield (struct value *dest_val,
+ LONGEST bitpos, LONGEST bitsize,
+ const gdb_byte *valaddr, LONGEST embedded_offset,
+ const struct value *val)
+{
+ enum bfd_endian byte_order;
+ int src_bit_offset;
+ int dst_bit_offset;
+ struct type *field_type = value_type (dest_val);
+
+ byte_order = gdbarch_byte_order (get_type_arch (field_type));
+
+ /* First, unpack and sign extend the bitfield as if it was wholly
+ valid. Optimized out/unavailable bits are read as zero, but
+ that's OK, as they'll end up marked below. If the VAL is
+ wholly-invalid we may have skipped allocating its contents,
+ though. See allocate_optimized_out_value. */
+ if (valaddr != NULL)
+ {
+ LONGEST num;
+
+ num = unpack_bits_as_long (field_type, valaddr + embedded_offset,
+ bitpos, bitsize);
+ store_signed_integer (value_contents_raw (dest_val),
+ TYPE_LENGTH (field_type), byte_order, num);
+ }
+
+ /* Now copy the optimized out / unavailability ranges to the right
+ bits. */
+ src_bit_offset = embedded_offset * TARGET_CHAR_BIT + bitpos;
+ if (byte_order == BFD_ENDIAN_BIG)
+ dst_bit_offset = TYPE_LENGTH (field_type) * TARGET_CHAR_BIT - bitsize;
+ else
+ dst_bit_offset = 0;
+ value_ranges_copy_adjusted (dest_val, dst_bit_offset,
+ val, src_bit_offset, bitsize);
}
/* Return a new value with type TYPE, which is FIELDNO field of the
object at VALADDR + EMBEDDEDOFFSET. VALADDR points to the contents
of VAL. If the VAL's contents required to extract the bitfield
- from are unavailable, the new value is correspondingly marked as
- unavailable. */
+ from are unavailable/optimized out, the new value is
+ correspondingly marked unavailable/optimized out. */
struct value *
value_field_bitfield (struct type *type, int fieldno,
const gdb_byte *valaddr,
- int embedded_offset, const struct value *val)
+ LONGEST embedded_offset, const struct value *val)
{
- LONGEST l;
+ int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+ int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ struct value *res_val = allocate_value (TYPE_FIELD_TYPE (type, fieldno));
- if (!unpack_value_field_as_long (type, valaddr, embedded_offset, fieldno,
- val, &l))
- {
- struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
- struct value *retval = allocate_value (field_type);
- mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (field_type));
- return retval;
- }
- else
- {
- return value_from_longest (TYPE_FIELD_TYPE (type, fieldno), l);
- }
+ unpack_value_bitfield (res_val, bitpos, bitsize,
+ valaddr, embedded_offset, val);
+
+ return res_val;
}
/* Modify the value of a bitfield. ADDR points to a block of memory in
void
modify_field (struct type *type, gdb_byte *addr,
- LONGEST fieldval, int bitpos, int bitsize)
+ LONGEST fieldval, LONGEST bitpos, LONGEST bitsize)
{
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
ULONGEST oword;
ULONGEST mask = (ULONGEST) -1 >> (8 * sizeof (ULONGEST) - bitsize);
- int bytesize;
+ LONGEST bytesize;
/* Normalize BITPOS. */
addr += bitpos / 8;
{
/* FIXME: would like to include fieldval in the message, but
we don't have a sprintf_longest. */
- warning (_("Value does not fit in %d bits."), bitsize);
+ warning (_("Value does not fit in %s bits."), plongest (bitsize));
/* Truncate it, otherwise adjoining fields may be corrupted. */
fieldval &= mask;
pack_long (gdb_byte *buf, struct type *type, LONGEST num)
{
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
- int len;
+ LONGEST len;
type = check_typedef (type);
len = TYPE_LENGTH (type);
break;
case TYPE_CODE_REF:
+ case TYPE_CODE_RVALUE_REF:
case TYPE_CODE_PTR:
store_typed_address (buf, type, (CORE_ADDR) num);
break;
static void
pack_unsigned_long (gdb_byte *buf, struct type *type, ULONGEST num)
{
- int len;
+ LONGEST len;
enum bfd_endian byte_order;
type = check_typedef (type);
break;
case TYPE_CODE_REF:
+ case TYPE_CODE_RVALUE_REF:
case TYPE_CODE_PTR:
store_typed_address (buf, type, (CORE_ADDR) num);
break;
/* Create a value representing a pointer of type TYPE to the address
ADDR. */
+
struct value *
value_from_pointer (struct type *type, CORE_ADDR addr)
{
struct value *val = allocate_value (type);
- store_typed_address (value_contents_raw (val), check_typedef (type), addr);
+ store_typed_address (value_contents_raw (val),
+ check_typedef (type), addr);
return val;
}
/* Create a value of type TYPE whose contents come from VALADDR, if it
is non-null, and whose memory address (in the inferior) is
- ADDRESS. */
+ ADDRESS. The type of the created value may differ from the passed
+ type TYPE. Make sure to retrieve values new type after this call.
+ Note that TYPE is not passed through resolve_dynamic_type; this is
+ a special API intended for use only by Ada. */
struct value *
-value_from_contents_and_address (struct type *type,
- const gdb_byte *valaddr,
- CORE_ADDR address)
+value_from_contents_and_address_unresolved (struct type *type,
+ const gdb_byte *valaddr,
+ CORE_ADDR address)
{
struct value *v;
v = allocate_value_lazy (type);
else
v = value_from_contents (type, valaddr);
+ VALUE_LVAL (v) = lval_memory;
set_value_address (v, address);
+ return v;
+}
+
+/* Create a value of type TYPE whose contents come from VALADDR, if it
+ is non-null, and whose memory address (in the inferior) is
+ ADDRESS. The type of the created value may differ from the passed
+ type TYPE. Make sure to retrieve values new type after this call. */
+
+struct value *
+value_from_contents_and_address (struct type *type,
+ const gdb_byte *valaddr,
+ CORE_ADDR address)
+{
+ struct type *resolved_type = resolve_dynamic_type (type, valaddr, address);
+ struct type *resolved_type_no_typedef = check_typedef (resolved_type);
+ struct value *v;
+
+ if (valaddr == NULL)
+ v = allocate_value_lazy (resolved_type);
+ else
+ v = value_from_contents (resolved_type, valaddr);
+ if (TYPE_DATA_LOCATION (resolved_type_no_typedef) != NULL
+ && TYPE_DATA_LOCATION_KIND (resolved_type_no_typedef) == PROP_CONST)
+ address = TYPE_DATA_LOCATION_ADDR (resolved_type_no_typedef);
VALUE_LVAL (v) = lval_memory;
+ set_value_address (v, address);
return v;
}
for details. */
struct value *
-value_from_history_ref (char *h, char **endp)
+value_from_history_ref (const char *h, const char **endp)
{
int index, len;
*endp += len;
}
else
- index = -strtol (&h[2], endp, 10);
+ {
+ char *local_end;
+
+ index = -strtol (&h[2], &local_end, 10);
+ *endp = local_end;
+ }
}
else
{
*endp += len;
}
else
- index = strtol (&h[1], endp, 10);
+ {
+ char *local_end;
+
+ index = strtol (&h[1], &local_end, 10);
+ *endp = local_end;
+ }
}
return access_value_history (index);
}
+/* Get the component value (offset by OFFSET bytes) of a struct or
+ union WHOLE. Component's type is TYPE. */
+
+struct value *
+value_from_component (struct value *whole, struct type *type, LONGEST offset)
+{
+ struct value *v;
+
+ if (VALUE_LVAL (whole) == lval_memory && value_lazy (whole))
+ v = allocate_value_lazy (type);
+ else
+ {
+ v = allocate_value (type);
+ value_contents_copy (v, value_embedded_offset (v),
+ whole, value_embedded_offset (whole) + offset,
+ type_length_units (type));
+ }
+ v->offset = value_offset (whole) + offset + value_embedded_offset (whole);
+ set_value_component_location (v, whole);
+
+ return v;
+}
+
struct value *
coerce_ref_if_computed (const struct value *arg)
{
const struct lval_funcs *funcs;
- if (TYPE_CODE (check_typedef (value_type (arg))) != TYPE_CODE_REF)
+ if (!TYPE_IS_REFERENCE (check_typedef (value_type (arg))))
return NULL;
if (value_lval_const (arg) != lval_computed)
struct value *
readjust_indirect_value_type (struct value *value, struct type *enc_type,
- struct type *original_type,
- struct value *original_value)
+ const struct type *original_type,
+ const struct value *original_value)
{
/* Re-adjust type. */
deprecated_set_value_type (value, TYPE_TARGET_TYPE (original_type));
if (retval)
return retval;
- if (TYPE_CODE (value_type_arg_tmp) != TYPE_CODE_REF)
+ if (!TYPE_IS_REFERENCE (value_type_arg_tmp))
return arg;
enc_type = check_typedef (value_enclosing_type (arg));
retval = value_at_lazy (enc_type,
unpack_pointer (value_type (arg),
value_contents (arg)));
+ enc_type = value_type (retval);
return readjust_indirect_value_type (retval, enc_type,
value_type_arg_tmp, arg);
}
/* Return the initialized field in a value struct. */
int
-value_initialized (struct value *val)
+value_initialized (const struct value *val)
{
return val->initialized;
}
-/* Called only from the value_contents and value_contents_all()
- macros, if the current data for a variable needs to be loaded into
- value_contents(VAL). Fetches the data from the user's process, and
- clears the lazy flag to indicate that the data in the buffer is
- valid.
+/* Load the actual content of a lazy value. Fetch the data from the
+ user's process and clear the lazy flag to indicate that the data in
+ the buffer is valid.
If the value is zero-length, we avoid calling read_memory, which
would abort. We mark the value as fetched anyway -- all 0 bytes of
- it.
-
- This function returns a value because it is used in the
- value_contents macro as part of an expression, where a void would
- not work. The value is ignored. */
+ it. */
-int
+void
value_fetch_lazy (struct value *val)
{
gdb_assert (value_lazy (val));
allocate_value_contents (val);
+ /* A value is either lazy, or fully fetched. The
+ availability/validity is only established as we try to fetch a
+ value. */
+ gdb_assert (VEC_empty (range_s, val->optimized_out));
+ gdb_assert (VEC_empty (range_s, val->unavailable));
if (value_bitsize (val))
{
/* To read a lazy bitfield, read the entire enclosing value. This
word, but we have no way to record that just specific bits of a
value have been fetched. */
struct type *type = check_typedef (value_type (val));
- enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
struct value *parent = value_parent (val);
- LONGEST offset = value_offset (val);
- LONGEST num;
if (value_lazy (parent))
value_fetch_lazy (parent);
- if (!value_bits_valid (parent,
- TARGET_CHAR_BIT * offset + value_bitpos (val),
- value_bitsize (val)))
- set_value_optimized_out (val, 1);
- else if (!unpack_value_bits_as_long (value_type (val),
- value_contents_for_printing (parent),
- offset,
- value_bitpos (val),
- value_bitsize (val), parent, &num))
- mark_value_bytes_unavailable (val,
- value_embedded_offset (val),
- TYPE_LENGTH (type));
- else
- store_signed_integer (value_contents_raw (val), TYPE_LENGTH (type),
- byte_order, num);
+ unpack_value_bitfield (val,
+ value_bitpos (val), value_bitsize (val),
+ value_contents_for_printing (parent),
+ value_offset (val), parent);
}
else if (VALUE_LVAL (val) == lval_memory)
{
if (TYPE_LENGTH (type))
read_value_memory (val, 0, value_stack (val),
addr, value_contents_all_raw (val),
- TYPE_LENGTH (type));
+ type_length_units (type));
}
else if (VALUE_LVAL (val) == lval_register)
{
- struct frame_info *frame;
+ struct frame_info *next_frame;
int regnum;
struct type *type = check_typedef (value_type (val));
struct value *new_val = val, *mark = value_mark ();
while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
{
- struct frame_id frame_id = VALUE_FRAME_ID (new_val);
+ struct frame_id next_frame_id = VALUE_NEXT_FRAME_ID (new_val);
- frame = frame_find_by_id (frame_id);
+ next_frame = frame_find_by_id (next_frame_id);
regnum = VALUE_REGNUM (new_val);
- gdb_assert (frame != NULL);
+ gdb_assert (next_frame != NULL);
/* Convertible register routines are used for multi-register
values and for interpretation in different types
(e.g. float or int from a double register). Lazy
register values should have the register's natural type,
so they do not apply. */
- gdb_assert (!gdbarch_convert_register_p (get_frame_arch (frame),
+ gdb_assert (!gdbarch_convert_register_p (get_frame_arch (next_frame),
regnum, type));
- new_val = get_frame_register_value (frame, regnum);
+ /* FRAME was obtained, above, via VALUE_NEXT_FRAME_ID.
+ Since a "->next" operation was performed when setting
+ this field, we do not need to perform a "next" operation
+ again when unwinding the register. That's why
+ frame_unwind_register_value() is called here instead of
+ get_frame_register_value(). */
+ new_val = frame_unwind_register_value (next_frame, regnum);
/* If we get another lazy lval_register value, it means the
- register is found by reading it from the next frame.
- get_frame_register_value should never return a value with
- the frame id pointing to FRAME. If it does, it means we
+ register is found by reading it from NEXT_FRAME's next frame.
+ frame_unwind_register_value should never return a value with
+ the frame id pointing to NEXT_FRAME. If it does, it means we
either have two consecutive frames with the same frame id
in the frame chain, or some code is trying to unwind
behind get_prev_frame's back (e.g., a frame unwind
in this situation. */
if (VALUE_LVAL (new_val) == lval_register
&& value_lazy (new_val)
- && frame_id_eq (VALUE_FRAME_ID (new_val), frame_id))
+ && frame_id_eq (VALUE_NEXT_FRAME_ID (new_val), next_frame_id))
internal_error (__FILE__, __LINE__,
_("infinite loop while fetching a register"));
}
if (value_lazy (new_val))
value_fetch_lazy (new_val);
- /* If the register was not saved, mark it optimized out. */
- if (value_optimized_out (new_val))
- set_value_optimized_out (val, 1);
- else
- {
- set_value_lazy (val, 0);
- value_contents_copy (val, value_embedded_offset (val),
- new_val, value_embedded_offset (new_val),
- TYPE_LENGTH (type));
- }
+ /* Copy the contents and the unavailability/optimized-out
+ meta-data from NEW_VAL to VAL. */
+ set_value_lazy (val, 0);
+ value_contents_copy (val, value_embedded_offset (val),
+ new_val, value_embedded_offset (new_val),
+ type_length_units (type));
if (frame_debug)
{
struct gdbarch *gdbarch;
+ struct frame_info *frame;
+ /* VALUE_FRAME_ID is used here, instead of VALUE_NEXT_FRAME_ID,
+ so that the frame level will be shown correctly. */
frame = frame_find_by_id (VALUE_FRAME_ID (val));
regnum = VALUE_REGNUM (val);
gdbarch = get_frame_arch (frame);
else if (VALUE_LVAL (val) == lval_computed
&& value_computed_funcs (val)->read != NULL)
value_computed_funcs (val)->read (val);
- /* Don't call value_optimized_out on val, doing so would result in a
- recursive call back to value_fetch_lazy, instead check the
- optimized_out flag directly. */
- else if (val->optimized_out)
- /* Keep it optimized out. */;
else
internal_error (__FILE__, __LINE__, _("Unexpected lazy value type."));
set_value_lazy (val, 0);
- return 0;
}
/* Implementation of the convenience function $_isvoid. */
Usage: $_isvoid (expression)\n\
Return 1 if the expression is void, zero otherwise."),
isvoid_internal_fn, NULL);
+
+ add_setshow_zuinteger_unlimited_cmd ("max-value-size",
+ class_support, &max_value_size, _("\
+Set maximum sized value gdb will load from the inferior."), _("\
+Show maximum sized value gdb will load from the inferior."), _("\
+Use this to control the maximum size, in bytes, of a value that gdb\n\
+will load from the inferior. Setting this value to 'unlimited'\n\
+disables checking.\n\
+Setting this does not invalidate already allocated values, it only\n\
+prevents future values, larger than this size, from being allocated."),
+ set_max_value_size,
+ show_max_value_size,
+ &setlist, &showlist);
}