#include "objfiles.h"
#include "valprint.h"
#include "cli/cli-decode.h"
-
+#include "exceptions.h"
#include "python/python.h"
-
+#include <ctype.h>
#include "tracepoint.h"
/* Prototypes for exported functions. */
return !ranges_contain (value->unavailable, offset, length);
}
+int
+value_entirely_available (struct value *value)
+{
+ /* We can only tell whether the whole value is available when we try
+ to read it. */
+ if (value->lazy)
+ value_fetch_lazy (value);
+
+ if (VEC_empty (range_s, value->unavailable))
+ return 1;
+ return 0;
+}
+
void
mark_value_bytes_unavailable (struct value *value, int offset, int length)
{
i = VEC_lower_bound (range_s, value->unavailable, &newr, range_lessthan);
if (i > 0)
{
- struct range *bef = VEC_index (range_s, value->unavailable, i - i);
+ struct range *bef = VEC_index (range_s, value->unavailable, i - 1);
if (ranges_overlap (bef->offset, bef->length, offset, length))
{
const struct value *val2, int offset2,
int length)
{
- int org_len = length;
- int org_offset1 = offset1;
- int org_offset2 = offset2;
int idx1 = 0, idx2 = 0;
- int prev_avail;
/* This routine is used by printing routines, where we should
already have read the value. Note that we only know whether a
value chunk is available if we've tried to read it. */
gdb_assert (!val1->lazy && !val2->lazy);
- /* The offset from either ORG_OFFSET1 or ORG_OFFSET2 where the
- available contents we haven't compared yet start. */
- prev_avail = 0;
-
while (length > 0)
{
range_s *r1, *r2;
/* The usual case is for both values to be completely available. */
if (idx1 == -1 && idx2 == -1)
- return (memcmp (val1->contents + org_offset1 + prev_avail,
- val2->contents + org_offset2 + prev_avail,
- org_len - prev_avail) == 0);
+ return (memcmp (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;
/* Compare the _available_ contents. */
- if (memcmp (val1->contents + org_offset1 + prev_avail,
- val2->contents + org_offset2 + prev_avail,
- l2 - prev_avail) != 0)
+ if (memcmp (val1->contents + offset1,
+ val2->contents + offset2,
+ l1) != 0)
return 0;
- prev_avail += h1;
length -= h1;
offset1 += h1;
offset2 += h1;
require_available (const struct value *value)
{
if (!VEC_empty (range_s, value->unavailable))
- error (_("value is not available"));
+ throw_error (NOT_AVAILABLE_ERROR, _("value is not available"));
}
const gdb_byte *
return result;
}
+/* Copy LENGTH bytes 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
+ unavailable accordingly. Neither DST nor SRC may be lazy
+ values.
+
+ It is assumed the contents of DST in the [DST_OFFSET,
+ 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)
+{
+ range_s *r;
+ int i;
+
+ /* 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
+ call, say), the contents would be overwritten. A lazy SRC would
+ mean we'd be copying garbage. */
+ gdb_assert (!dst->lazy && !src->lazy);
+
+ /* The overwritten DST range gets unavailability ORed in, not
+ replaced. Make sure to remember to implement replacing if it
+ turns out actually necessary. */
+ gdb_assert (value_bytes_available (dst, dst_offset, length));
+
+ /* Copy the data. */
+ memcpy (value_contents_all_raw (dst) + dst_offset,
+ value_contents_all_raw (src) + src_offset,
+ length);
+
+ /* Copy the meta-data, adjusted. */
+ for (i = 0; VEC_iterate (range_s, src->unavailable, i, r); i++)
+ {
+ ULONGEST h, l;
+
+ l = max (r->offset, src_offset);
+ h = min (r->offset + r->length, src_offset + length);
+
+ if (l < h)
+ mark_value_bytes_unavailable (dst,
+ dst_offset + (l - src_offset),
+ h - l);
+ }
+}
+
+/* Copy LENGTH bytes of SRC value's (all) contents
+ (value_contents_all) starting at SRC_OFFSET byte, into DST value's
+ (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.
+
+ 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)
+{
+ require_not_optimized_out (src);
+
+ if (src->lazy)
+ value_fetch_lazy (src);
+
+ value_contents_copy_raw (dst, dst_offset, src, src_offset, length);
+}
+
int
value_lazy (struct value *value)
{
int
value_bits_valid (const struct value *value, int offset, int length)
{
- if (value == NULL || !value->optimized_out)
+ if (!value->optimized_out)
return 1;
if (value->lval != lval_computed
|| !value->location.computed.funcs->check_validity)
value_bits_synthetic_pointer (const struct value *value,
int offset, int length)
{
- if (value == NULL || value->lval != lval_computed
+ if (value->lval != lval_computed
|| !value->location.computed.funcs->check_synthetic_pointer)
return 0;
return value->location.computed.funcs->check_synthetic_pointer (value,
int
get_internalvar_integer (struct internalvar *var, LONGEST *result)
{
- switch (var->kind)
+ if (var->kind == INTERNALVAR_INTEGER)
{
- case INTERNALVAR_INTEGER:
*result = var->u.integer.val;
return 1;
+ }
- default:
- return 0;
+ if (var->kind == INTERNALVAR_VALUE)
+ {
+ struct type *type = check_typedef (value_type (var->u.value));
+
+ if (TYPE_CODE (type) == TYPE_CODE_INT)
+ {
+ *result = value_as_long (var->u.value);
+ return 1;
+ }
}
+
+ return 0;
}
static int
/* Copies created here are never canonical. */
break;
- case TYPE_CODE_INT:
- new_kind = INTERNALVAR_INTEGER;
- new_data.integer.type = value_type (val);
- new_data.integer.val = value_as_long (val);
- break;
-
default:
new_kind = INTERNALVAR_VALUE;
new_data.value = value_copy (val);
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. */
+ entire object's contents for later references to virtual
+ bases, etc. */
/* Lazy register values with offsets are not supported. */
if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
else
{
v = allocate_value (value_enclosing_type (arg1));
- memcpy (value_contents_all_raw (v), value_contents_all_raw (arg1),
- TYPE_LENGTH (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);
else
{
v = allocate_value (type);
- memcpy (value_contents_raw (v),
- value_contents_raw (arg1) + offset,
- TYPE_LENGTH (type));
+ value_contents_copy_raw (v, value_embedded_offset (v),
+ arg1, value_embedded_offset (arg1) + offset,
+ TYPE_LENGTH (type));
}
v->offset = (value_offset (arg1) + offset
+ value_embedded_offset (arg1));
}
\f
-/* Unpack a bitfield of the specified FIELD_TYPE, from the anonymous
- object at VALADDR. 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.
-
- If the field is signed, we also do sign extension. */
+/* 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. */
-LONGEST
-unpack_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
- int bitpos, int bitsize)
+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)
{
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;
/* Read the minimum number of bytes required; there may not be
enough bytes to read an entire ULONGEST. */
else
bytes_read = TYPE_LENGTH (field_type);
- val = extract_unsigned_integer (valaddr + bitpos / 8,
+ read_offset = bitpos / 8;
+
+ if (original_value != NULL
+ && !value_bytes_available (original_value, embedded_offset + read_offset,
+ bytes_read))
+ return 0;
+
+ val = extract_unsigned_integer (valaddr + embedded_offset + read_offset,
bytes_read, byte_order);
/* Extract bits. See comment above. */
}
}
}
- return (val);
+
+ *result = val;
+ return 1;
}
-/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
- VALADDR. See unpack_bits_as_long for more details. */
+/* 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.
-LONGEST
-unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
+ 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_bits_as_long (field_type, valaddr, bitpos, bitsize);
+ return unpack_value_bits_as_long_1 (field_type, valaddr, embedded_offset,
+ bitpos, bitsize, val,
+ result);
+}
+
+/* Unpack a field FIELDNO of the specified TYPE, from the object at
+ VALADDR + EMBEDDED_OFFSET. VALADDR points to the contents of
+ ORIGINAL_VALUE, which must not be NULL. See
+ unpack_value_bits_as_long for more details. */
+
+int
+unpack_value_field_as_long (struct type *type, const gdb_byte *valaddr,
+ int embedded_offset, int fieldno,
+ const struct value *val, LONGEST *result)
+{
+ gdb_assert (val != NULL);
+
+ return unpack_value_field_as_long_1 (type, valaddr, embedded_offset,
+ fieldno, val, result);
+}
+
+/* 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. */
+
+LONGEST
+unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
+{
+ LONGEST result;
+
+ unpack_value_field_as_long_1 (type, valaddr, 0, fieldno, NULL, &result);
+ return result;
+}
+
+/* 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. */
+
+struct value *
+value_field_bitfield (struct type *type, int fieldno,
+ const gdb_byte *valaddr,
+ int embedded_offset, const struct value *val)
+{
+ LONGEST l;
+
+ 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);
+ }
}
/* Modify the value of a bitfield. ADDR points to a block of memory in
return val;
}
+/* Extract a value from the history file. Input will be of the form
+ $digits or $$digits. See block comment above 'write_dollar_variable'
+ for details. */
+
+struct value *
+value_from_history_ref (char *h, char **endp)
+{
+ int index, len;
+
+ if (h[0] == '$')
+ len = 1;
+ else
+ return NULL;
+
+ if (h[1] == '$')
+ len = 2;
+
+ /* Find length of numeral string. */
+ for (; isdigit (h[len]); len++)
+ ;
+
+ /* Make sure numeral string is not part of an identifier. */
+ if (h[len] == '_' || isalpha (h[len]))
+ return NULL;
+
+ /* Now collect the index value. */
+ if (h[1] == '$')
+ {
+ if (len == 2)
+ {
+ /* For some bizarre reason, "$$" is equivalent to "$$1",
+ rather than to "$$0" as it ought to be! */
+ index = -1;
+ *endp += len;
+ }
+ else
+ index = -strtol (&h[2], endp, 10);
+ }
+ else
+ {
+ if (len == 1)
+ {
+ /* "$" is equivalent to "$0". */
+ index = 0;
+ *endp += len;
+ }
+ else
+ index = strtol (&h[1], endp, 10);
+ }
+
+ return access_value_history (index);
+}
+
struct value *
coerce_ref (struct value *arg)
{
\"$__\" holds the contents of the last address examined with \"x\"."),
&showlist);
- add_cmd ("values", no_class, show_values, _("\
+ add_cmd ("values", no_set_class, show_values, _("\
Elements of value history around item number IDX (or last ten)."),
&showlist);