/* Low level packing and unpacking of values for GDB, the GNU Debugger.
- Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+ Copyright 1986, 87, 89, 91, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
-This file is part of GDB.
+ This file is part of GDB.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
#include "defs.h"
-#include <string.h>
+#include "gdb_string.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "value.h"
#include "command.h"
#include "gdbcmd.h"
#include "target.h"
+#include "language.h"
+#include "scm-lang.h"
#include "demangle.h"
-/* Local function prototypes. */
+/* Prototypes for exported functions. */
-static value_ptr value_headof PARAMS ((value_ptr, struct type *,
- struct type *));
+void _initialize_values (void);
-static void show_values PARAMS ((char *, int));
+/* Prototypes for local functions. */
-static void show_convenience PARAMS ((char *, int));
+static value_ptr value_headof (value_ptr, struct type *, struct type *);
+
+static void show_values (char *, int);
+
+static void show_convenience (char *, int);
+
+static int vb_match (struct type *, int, struct type *);
/* The value-history records all the values printed
by print commands during this session. Each chunk
#define VALUE_HISTORY_CHUNK 60
struct value_history_chunk
-{
- struct value_history_chunk *next;
- value_ptr values[VALUE_HISTORY_CHUNK];
-};
+ {
+ struct value_history_chunk *next;
+ value_ptr values[VALUE_HISTORY_CHUNK];
+ };
/* Chain of chunks now in use. */
/* Allocate a value that has the correct length for type TYPE. */
value_ptr
-allocate_value (type)
- struct type *type;
+allocate_value (struct type *type)
{
register value_ptr val;
+ struct type *atype = check_typedef (type);
- check_stub_type (type);
-
- val = (struct value *) xmalloc (sizeof (struct value) + TYPE_LENGTH (type));
+ val = (struct value *) xmalloc (sizeof (struct value) + TYPE_LENGTH (atype));
VALUE_NEXT (val) = all_values;
all_values = val;
VALUE_TYPE (val) = type;
+ VALUE_ENCLOSING_TYPE (val) = type;
VALUE_LVAL (val) = not_lval;
VALUE_ADDRESS (val) = 0;
VALUE_FRAME (val) = 0;
VALUE_OFFSET (val) = 0;
VALUE_BITPOS (val) = 0;
VALUE_BITSIZE (val) = 0;
- VALUE_REPEATED (val) = 0;
- VALUE_REPETITIONS (val) = 0;
VALUE_REGNO (val) = -1;
VALUE_LAZY (val) = 0;
VALUE_OPTIMIZED_OUT (val) = 0;
+ VALUE_BFD_SECTION (val) = NULL;
+ VALUE_EMBEDDED_OFFSET (val) = 0;
+ VALUE_POINTED_TO_OFFSET (val) = 0;
val->modifiable = 1;
return val;
}
for COUNT repetitions type TYPE. */
value_ptr
-allocate_repeat_value (type, count)
- struct type *type;
- int count;
+allocate_repeat_value (struct type *type, int count)
{
- register value_ptr val;
-
- val =
- (value_ptr) xmalloc (sizeof (struct value) + TYPE_LENGTH (type) * count);
- VALUE_NEXT (val) = all_values;
- all_values = val;
- VALUE_TYPE (val) = type;
- VALUE_LVAL (val) = not_lval;
- VALUE_ADDRESS (val) = 0;
- VALUE_FRAME (val) = 0;
- VALUE_OFFSET (val) = 0;
- VALUE_BITPOS (val) = 0;
- VALUE_BITSIZE (val) = 0;
- VALUE_REPEATED (val) = 1;
- VALUE_REPETITIONS (val) = count;
- VALUE_REGNO (val) = -1;
- VALUE_LAZY (val) = 0;
- VALUE_OPTIMIZED_OUT (val) = 0;
- return val;
+ int low_bound = current_language->string_lower_bound; /* ??? */
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ struct type *range_type
+ = create_range_type ((struct type *) NULL, builtin_type_int,
+ low_bound, count + low_bound - 1);
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ return allocate_value (create_array_type ((struct type *) NULL,
+ type, range_type));
}
/* Return a mark in the value chain. All values allocated after the
mark is obtained (except for those released) are subject to being freed
if a subsequent value_free_to_mark is passed the mark. */
value_ptr
-value_mark ()
+value_mark (void)
{
return all_values;
}
/* Free all values allocated since MARK was obtained by value_mark
(except for those released). */
void
-value_free_to_mark (mark)
- value_ptr mark;
+value_free_to_mark (value_ptr mark)
{
value_ptr val, next;
Called after each command, successful or not. */
void
-free_all_values ()
+free_all_values (void)
{
register value_ptr val, next;
so it will not be freed automatically. */
void
-release_value (val)
- register value_ptr val;
+release_value (register value_ptr val)
{
register value_ptr v;
}
}
+/* Release all values up to mark */
+value_ptr
+value_release_to_mark (value_ptr mark)
+{
+ value_ptr val, next;
+
+ for (val = next = all_values; next; next = VALUE_NEXT (next))
+ if (VALUE_NEXT (next) == mark)
+ {
+ all_values = VALUE_NEXT (next);
+ VALUE_NEXT (next) = 0;
+ return val;
+ }
+ all_values = 0;
+ return val;
+}
+
/* Return a copy of the value ARG.
It contains the same contents, for same memory address,
but it's a different block of storage. */
value_ptr
-value_copy (arg)
- value_ptr arg;
+value_copy (value_ptr arg)
{
- register value_ptr val;
- register struct type *type = VALUE_TYPE (arg);
- if (VALUE_REPEATED (arg))
- val = allocate_repeat_value (type, VALUE_REPETITIONS (arg));
- else
- val = allocate_value (type);
+ register struct type *encl_type = VALUE_ENCLOSING_TYPE (arg);
+ register value_ptr val = allocate_value (encl_type);
+ VALUE_TYPE (val) = VALUE_TYPE (arg);
VALUE_LVAL (val) = VALUE_LVAL (arg);
VALUE_ADDRESS (val) = VALUE_ADDRESS (arg);
VALUE_OFFSET (val) = VALUE_OFFSET (arg);
VALUE_BITPOS (val) = VALUE_BITPOS (arg);
VALUE_BITSIZE (val) = VALUE_BITSIZE (arg);
+ VALUE_FRAME (val) = VALUE_FRAME (arg);
VALUE_REGNO (val) = VALUE_REGNO (arg);
VALUE_LAZY (val) = VALUE_LAZY (arg);
+ VALUE_OPTIMIZED_OUT (val) = VALUE_OPTIMIZED_OUT (arg);
+ VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (arg);
+ VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (arg);
+ VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (arg);
val->modifiable = arg->modifiable;
if (!VALUE_LAZY (val))
{
- memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS_RAW (arg),
- TYPE_LENGTH (VALUE_TYPE (arg))
- * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
+ memcpy (VALUE_CONTENTS_ALL_RAW (val), VALUE_CONTENTS_ALL_RAW (arg),
+ TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg)));
+
}
return val;
}
value history index of this new item. */
int
-record_latest_value (val)
- value_ptr val;
+record_latest_value (value_ptr val)
{
int i;
- /* Check error now if about to store an invalid float. We return -1
- to the caller, but allow them to continue, e.g. to print it as "Nan". */
- if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT)
- {
- unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i);
- if (i) return -1; /* Indicate value not saved in history */
- }
+ /* We don't want this value to have anything to do with the inferior anymore.
+ In particular, "set $1 = 50" should not affect the variable from which
+ the value was taken, and fast watchpoints should be able to assume that
+ a value on the value history never changes. */
+ if (VALUE_LAZY (val))
+ value_fetch_lazy (val);
+ /* We preserve VALUE_LVAL so that the user can find out where it was fetched
+ 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);
/* Here we treat value_history_count as origin-zero
and applying to the value being stored now. */
if (i == 0)
{
register struct value_history_chunk *new
- = (struct value_history_chunk *)
- xmalloc (sizeof (struct value_history_chunk));
+ = (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;
value_history_chain->values[i] = val;
- /* We don't want this value to have anything to do with the inferior anymore.
- In particular, "set $1 = 50" should not affect the variable from which
- the value was taken, and fast watchpoints should be able to assume that
- a value on the value history never changes. */
- if (VALUE_LAZY (val))
- value_fetch_lazy (val);
- /* We preserve VALUE_LVAL so that the user can find out where it was fetched
- 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);
-
/* Now we regard value_history_count as origin-one
and applying to the value just stored. */
/* Return a copy of the value in the history with sequence number NUM. */
value_ptr
-access_value_history (num)
- int num;
+access_value_history (int num)
{
register struct value_history_chunk *chunk;
register int i;
because the type pointers become invalid. */
void
-clear_value_history ()
+clear_value_history (void)
{
register struct value_history_chunk *next;
register int i;
{
for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
if ((val = value_history_chain->values[i]) != NULL)
- free ((PTR)val);
+ xfree (val);
next = value_history_chain->next;
- free ((PTR)value_history_chain);
+ xfree (value_history_chain);
value_history_chain = next;
}
value_history_count = 0;
}
static void
-show_values (num_exp, from_tty)
- char *num_exp;
- int from_tty;
+show_values (char *num_exp, int from_tty)
{
register int i;
register value_ptr val;
if (num_exp)
{
- /* "info history +" should print from the stored position.
- "info history <exp>" should print around value number <exp>. */
+ /* "info history +" should print from the stored position.
+ "info history <exp>" should print around value number <exp>. */
if (num_exp[0] != '+' || num_exp[1] != '\0')
- num = parse_and_eval_address (num_exp) - 5;
+ num = parse_and_eval_long (num_exp) - 5;
}
else
{
one is created, with a void value. */
struct internalvar *
-lookup_internalvar (name)
- char *name;
+lookup_internalvar (char *name)
{
register struct internalvar *var;
}
value_ptr
-value_of_internalvar (var)
- struct internalvar *var;
+value_of_internalvar (struct internalvar *var)
{
register value_ptr val;
#ifdef IS_TRAPPED_INTERNALVAR
if (IS_TRAPPED_INTERNALVAR (var->name))
return VALUE_OF_TRAPPED_INTERNALVAR (var);
-#endif
+#endif
val = value_copy (var->value);
if (VALUE_LAZY (val))
}
void
-set_internalvar_component (var, offset, bitpos, bitsize, newval)
- struct internalvar *var;
- int offset, bitpos, bitsize;
- value_ptr newval;
+set_internalvar_component (struct internalvar *var, int offset, int bitpos,
+ int bitsize, value_ptr newval)
{
register char *addr = VALUE_CONTENTS (var->value) + offset;
}
void
-set_internalvar (var, val)
- struct internalvar *var;
- value_ptr val;
+set_internalvar (struct internalvar *var, value_ptr val)
{
value_ptr newval;
#endif
newval = value_copy (val);
+ newval->modifiable = 1;
/* Force the value to be fetched from the target now, to avoid problems
later when this internalvar is referenced and the target is gone or
something in the value chain (i.e., before release_value is
called), because after the error free_all_values will get called before
long. */
- free ((PTR)var->value);
+ xfree (var->value);
var->value = newval;
release_value (newval);
/* End code which must not call error(). */
}
char *
-internalvar_name (var)
- struct internalvar *var;
+internalvar_name (struct internalvar *var)
{
return var->name;
}
because that makes the values invalid. */
void
-clear_internalvars ()
+clear_internalvars (void)
{
register struct internalvar *var;
{
var = internalvars;
internalvars = var->next;
- free ((PTR)var->name);
- free ((PTR)var->value);
- free ((PTR)var);
+ xfree (var->name);
+ xfree (var->value);
+ xfree (var);
}
}
static void
-show_convenience (ignore, from_tty)
- char *ignore;
- int from_tty;
+show_convenience (char *ignore, int from_tty)
{
register struct internalvar *var;
int varseen = 0;
Does not deallocate the value. */
LONGEST
-value_as_long (val)
- register value_ptr val;
+value_as_long (register value_ptr val)
{
/* This coerces arrays and functions, which is necessary (e.g.
in disassemble_command). It also dereferences references, which
I suspect is the most logical thing to do. */
- if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_ENUM)
- COERCE_ARRAY (val);
+ COERCE_ARRAY (val);
return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
}
-double
-value_as_double (val)
- register value_ptr val;
+DOUBLEST
+value_as_double (register value_ptr val)
{
- double foo;
+ DOUBLEST foo;
int inv;
-
+
foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv);
if (inv)
error ("Invalid floating value found in program.");
return foo;
}
-/* Extract a value as a C pointer.
- Does not deallocate the value. */
+/* Extract a value as a C pointer. Does not deallocate the value.
+ Note that val's type may not actually be a pointer; value_as_long
+ handles all the cases. */
CORE_ADDR
-value_as_pointer (val)
- value_ptr val;
+value_as_pointer (value_ptr val)
{
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
/* ADDR_BITS_REMOVE is wrong if we are being called for a
non-address (e.g. argument to "signal", "info break", etc.), or
for pointers to char, in which the low bits *are* significant. */
- return ADDR_BITS_REMOVE(value_as_long (val));
+ return ADDR_BITS_REMOVE (value_as_long (val));
#else
- return value_as_long (val);
+ COERCE_ARRAY (val);
+ /* In converting VAL to an address (CORE_ADDR), any small integers
+ are first cast to a generic pointer. The function unpack_long
+ will then correctly convert that pointer into a canonical address
+ (using POINTER_TO_ADDRESS).
+
+ Without the cast, the MIPS gets: 0xa0000000 -> (unsigned int)
+ 0xa0000000 -> (LONGEST) 0x00000000a0000000
+
+ With the cast, the MIPS gets: 0xa0000000 -> (unsigned int)
+ 0xa0000000 -> (void*) 0xa0000000 -> (LONGEST) 0xffffffffa0000000.
+
+ If the user specifies an integer that is larger than the target
+ pointer type, it is assumed that it was intentional and the value
+ is converted directly into an ADDRESS. This ensures that no
+ information is discarded.
+
+ NOTE: The cast operation may eventualy be converted into a TARGET
+ method (see POINTER_TO_ADDRESS() and ADDRESS_TO_POINTER()) so
+ that the TARGET ISA/ABI can apply an arbitrary conversion.
+
+ NOTE: In pure harvard architectures function and data pointers
+ can be different and may require different integer to pointer
+ conversions. */
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT
+ && TYPE_LENGTH (VALUE_TYPE (val)) <= TYPE_LENGTH (builtin_type_ptr))
+ {
+ val = value_cast (builtin_type_ptr, val);
+ }
+ return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
#endif
}
\f
to member which reaches here is considered to be equivalent
to an INT (or some size). After all, it is only an offset. */
-/* FIXME: This should be rewritten as a switch statement for speed and
- ease of comprehension. */
-
LONGEST
-unpack_long (type, valaddr)
- struct type *type;
- char *valaddr;
+unpack_long (struct type *type, char *valaddr)
{
register enum type_code code = TYPE_CODE (type);
register int len = TYPE_LENGTH (type);
register int nosign = TYPE_UNSIGNED (type);
+ if (current_language->la_language == language_scm
+ && is_scmvalue_type (type))
+ return scm_unpack (type, valaddr, TYPE_CODE_INT);
+
switch (code)
{
+ case TYPE_CODE_TYPEDEF:
+ return unpack_long (check_typedef (type), valaddr);
case TYPE_CODE_ENUM:
case TYPE_CODE_BOOL:
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
if (nosign)
return extract_unsigned_integer (valaddr, len);
else
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
- whether we want this to be true eventually. */
- return extract_address (valaddr, len);
+ whether we want this to be true eventually. */
+ if (GDB_TARGET_IS_D10V
+ && len == 2)
+ return D10V_MAKE_DADDR (extract_address (valaddr, len));
+ return extract_typed_address (valaddr, type);
case TYPE_CODE_MEMBER:
error ("not implemented: member types in unpack_long");
default:
error ("Value can't be converted to integer.");
}
- return 0; /* Placate lint. */
+ return 0; /* Placate lint. */
}
/* Return a double value from the specified type and address.
the returned double is OK to use. Argument is in target
format, result is in host format. */
-double
-unpack_double (type, valaddr, invp)
- struct type *type;
- char *valaddr;
- int *invp;
+DOUBLEST
+unpack_double (struct type *type, char *valaddr, int *invp)
{
- register enum type_code code = TYPE_CODE (type);
- register int len = TYPE_LENGTH (type);
- register int nosign = TYPE_UNSIGNED (type);
+ enum type_code code;
+ int len;
+ int nosign;
*invp = 0; /* Assume valid. */
+ CHECK_TYPEDEF (type);
+ code = TYPE_CODE (type);
+ len = TYPE_LENGTH (type);
+ nosign = TYPE_UNSIGNED (type);
if (code == TYPE_CODE_FLT)
{
+#ifdef INVALID_FLOAT
if (INVALID_FLOAT (valaddr, len))
{
*invp = 1;
return 1.234567891011121314;
}
+#endif
return extract_floating (valaddr, len);
}
else if (nosign)
{
/* Unsigned -- be sure we compensate for signed LONGEST. */
- return (unsigned LONGEST) unpack_long (type, valaddr);
+#if !defined (_MSC_VER) || (_MSC_VER > 900)
+ return (ULONGEST) unpack_long (type, valaddr);
+#else
+ /* FIXME!!! msvc22 doesn't support unsigned __int64 -> double */
+ return (LONGEST) unpack_long (type, valaddr);
+#endif /* _MSC_VER */
}
else
{
to an INT (or some size). After all, it is only an offset. */
CORE_ADDR
-unpack_pointer (type, valaddr)
- struct type *type;
- char *valaddr;
+unpack_pointer (struct type *type, char *valaddr)
{
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
return unpack_long (type, valaddr);
}
+
\f
+/* Get the value of the FIELDN'th field (which must be static) of TYPE. */
+
+value_ptr
+value_static_field (struct type *type, int fieldno)
+{
+ CORE_ADDR addr;
+ asection *sect;
+ if (TYPE_FIELD_STATIC_HAS_ADDR (type, fieldno))
+ {
+ addr = TYPE_FIELD_STATIC_PHYSADDR (type, fieldno);
+ sect = NULL;
+ }
+ else
+ {
+ char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
+ struct symbol *sym = lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym == NULL)
+ {
+ /* With some compilers, e.g. HP aCC, static data members are reported
+ as non-debuggable symbols */
+ struct minimal_symbol *msym = lookup_minimal_symbol (phys_name, NULL, NULL);
+ if (!msym)
+ return NULL;
+ else
+ {
+ addr = SYMBOL_VALUE_ADDRESS (msym);
+ sect = SYMBOL_BFD_SECTION (msym);
+ }
+ }
+ else
+ {
+ addr = SYMBOL_VALUE_ADDRESS (sym);
+ sect = SYMBOL_BFD_SECTION (sym);
+ }
+ SET_FIELD_PHYSADDR (TYPE_FIELD (type, fieldno), addr);
+ }
+ return value_at (TYPE_FIELD_TYPE (type, fieldno), addr, sect);
+}
+
/* Given a value ARG1 (offset by OFFSET bytes)
of a struct or union type ARG_TYPE,
- extract and return the value of one of its fields.
- FIELDNO says which field.
-
- For C++, must also be able to return values from static fields */
+ extract and return the value of one of its (non-static) fields.
+ FIELDNO says which field. */
value_ptr
-value_primitive_field (arg1, offset, fieldno, arg_type)
- register value_ptr arg1;
- int offset;
- register int fieldno;
- register struct type *arg_type;
+value_primitive_field (register value_ptr arg1, int offset,
+ register int fieldno, register struct type *arg_type)
{
register value_ptr v;
register struct type *type;
- check_stub_type (arg_type);
+ CHECK_TYPEDEF (arg_type);
type = TYPE_FIELD_TYPE (arg_type, fieldno);
/* Handle packed fields */
- offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
{
v = value_from_longest (type,
- unpack_field_as_long (arg_type,
- VALUE_CONTENTS (arg1),
- fieldno));
+ unpack_field_as_long (arg_type,
+ VALUE_CONTENTS (arg1)
+ + offset,
+ fieldno));
VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8;
VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+ VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset
+ + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+ }
+ 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. */
+ v = allocate_value (VALUE_ENCLOSING_TYPE (arg1));
+ VALUE_TYPE (v) = arg_type;
+ if (VALUE_LAZY (arg1))
+ VALUE_LAZY (v) = 1;
+ else
+ memcpy (VALUE_CONTENTS_ALL_RAW (v), VALUE_CONTENTS_ALL_RAW (arg1),
+ TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg1)));
+ VALUE_OFFSET (v) = VALUE_OFFSET (arg1);
+ VALUE_EMBEDDED_OFFSET (v)
+ = offset +
+ VALUE_EMBEDDED_OFFSET (arg1) +
+ TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
}
else
{
+ /* Plain old data member */
+ offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
v = allocate_value (type);
if (VALUE_LAZY (arg1))
VALUE_LAZY (v) = 1;
else
- memcpy (VALUE_CONTENTS_RAW (v), VALUE_CONTENTS_RAW (arg1) + offset,
+ memcpy (VALUE_CONTENTS_RAW (v),
+ VALUE_CONTENTS_RAW (arg1) + offset,
TYPE_LENGTH (type));
+ VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset;
}
VALUE_LVAL (v) = VALUE_LVAL (arg1);
if (VALUE_LVAL (arg1) == lval_internalvar)
VALUE_LVAL (v) = lval_internalvar_component;
VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1);
- VALUE_OFFSET (v) = offset + VALUE_OFFSET (arg1);
+ VALUE_REGNO (v) = VALUE_REGNO (arg1);
+/* VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset
+ + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; */
return v;
}
/* Given a value ARG1 of a struct or union type,
- extract and return the value of one of its fields.
- FIELDNO says which field.
-
- For C++, must also be able to return values from static fields */
+ extract and return the value of one of its (non-static) fields.
+ FIELDNO says which field. */
value_ptr
-value_field (arg1, fieldno)
- register value_ptr arg1;
- register int fieldno;
+value_field (register value_ptr arg1, register int fieldno)
{
return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1));
}
J is an index into F which provides the desired method. */
value_ptr
-value_fn_field (arg1p, f, j, type, offset)
- value_ptr *arg1p;
- struct fn_field *f;
- int j;
- struct type *type;
- int offset;
+value_fn_field (value_ptr *arg1p, struct fn_field *f, int j, struct type *type,
+ int offset)
{
register value_ptr v;
register struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
0, VAR_NAMESPACE, 0, NULL);
- if (! sym)
- return NULL;
+ if (!sym)
+ return NULL;
/*
- error ("Internal error: could not find physical method named %s",
- TYPE_FN_FIELD_PHYSNAME (f, j));
-*/
-
+ error ("Internal error: could not find physical method named %s",
+ TYPE_FN_FIELD_PHYSNAME (f, j));
+ */
+
v = allocate_value (ftype);
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
VALUE_TYPE (v) = ftype;
if (arg1p)
- {
- if (type != VALUE_TYPE (*arg1p))
- *arg1p = value_ind (value_cast (lookup_pointer_type (type),
- value_addr (*arg1p)));
-
- /* Move the `this' pointer according to the offset.
- VALUE_OFFSET (*arg1p) += offset;
- */
+ {
+ if (type != VALUE_TYPE (*arg1p))
+ *arg1p = value_ind (value_cast (lookup_pointer_type (type),
+ value_addr (*arg1p)));
+
+ /* Move the `this' pointer according to the offset.
+ VALUE_OFFSET (*arg1p) += offset;
+ */
}
return v;
TYPE is the type in which F is located. */
value_ptr
-value_virtual_fn_field (arg1p, f, j, type, offset)
- value_ptr *arg1p;
- struct fn_field *f;
- int j;
- struct type *type;
- int offset;
+value_virtual_fn_field (value_ptr *arg1p, struct fn_field *f, int j,
+ struct type *type, int offset)
{
value_ptr arg1 = *arg1p;
- /* First, get the virtual function table pointer. That comes
- with a strange type, so cast it to type `pointer to long' (which
- should serve just fine as a function type). Then, index into
- the table, and convert final value to appropriate function type. */
- value_ptr entry, vfn, vtbl;
- value_ptr vi = value_from_longest (builtin_type_int,
- (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
- struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
- struct type *context;
- if (fcontext == NULL)
- /* We don't have an fcontext (e.g. the program was compiled with
- g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE.
- This won't work right for multiple inheritance, but at least we
- should do as well as GDB 3.x did. */
- fcontext = TYPE_VPTR_BASETYPE (type);
- context = lookup_pointer_type (fcontext);
- /* Now context is a pointer to the basetype containing the vtbl. */
- if (TYPE_TARGET_TYPE (context) != VALUE_TYPE (arg1))
- arg1 = value_ind (value_cast (context, value_addr (arg1)));
-
- context = VALUE_TYPE (arg1);
- /* Now context is the basetype containing the vtbl. */
-
- /* This type may have been defined before its virtual function table
- was. If so, fill in the virtual function table entry for the
- type now. */
- if (TYPE_VPTR_FIELDNO (context) < 0)
- fill_in_vptr_fieldno (context);
-
- /* The virtual function table is now an array of structures
- which have the form { int16 offset, delta; void *pfn; }. */
- vtbl = value_ind (value_primitive_field (arg1, 0,
- TYPE_VPTR_FIELDNO (context),
- TYPE_VPTR_BASETYPE (context)));
-
- /* Index into the virtual function table. This is hard-coded because
- looking up a field is not cheap, and it may be important to save
- time, e.g. if the user has set a conditional breakpoint calling
- a virtual function. */
- entry = value_subscript (vtbl, vi);
-
- /* Move the `this' pointer according to the virtual function table. */
- VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0))/* + offset*/;
-
- if (! VALUE_LAZY (arg1))
+ struct type *type1 = check_typedef (VALUE_TYPE (arg1));
+
+ if (TYPE_HAS_VTABLE (type))
{
- VALUE_LAZY (arg1) = 1;
- value_fetch_lazy (arg1);
+ /* Deal with HP/Taligent runtime model for virtual functions */
+ value_ptr vp;
+ value_ptr argp; /* arg1 cast to base */
+ CORE_ADDR coreptr; /* pointer to target address */
+ int class_index; /* which class segment pointer to use */
+ struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */
+
+ argp = value_cast (type, *arg1p);
+
+ if (VALUE_ADDRESS (argp) == 0)
+ error ("Address of object is null; object may not have been created.");
+
+ /* pai: FIXME -- 32x64 possible problem? */
+ /* First word (4 bytes) in object layout is the vtable pointer */
+ coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */
+ /* + offset + VALUE_EMBEDDED_OFFSET (argp)); */
+
+ if (!coreptr)
+ error ("Virtual table pointer is null for object; object may not have been created.");
+
+ /* pai/1997-05-09
+ * FIXME: The code here currently handles only
+ * the non-RRBC case of the Taligent/HP runtime spec; when RRBC
+ * is introduced, the condition for the "if" below will have to
+ * be changed to be a test for the RRBC case. */
+
+ if (1)
+ {
+ /* Non-RRBC case; the virtual function pointers are stored at fixed
+ * offsets in the virtual table. */
+
+ /* Retrieve the offset in the virtual table from the debug
+ * info. The offset of the vfunc's entry is in words from
+ * the beginning of the vtable; but first we have to adjust
+ * by HP_ACC_VFUNC_START to account for other entries */
+
+ /* pai: FIXME: 32x64 problem here, a word may be 8 bytes in
+ * which case the multiplier should be 8 and values should be long */
+ vp = value_at (builtin_type_int,
+ coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) + HP_ACC_VFUNC_START), NULL);
+
+ coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
+ /* coreptr now contains the address of the virtual function */
+ /* (Actually, it contains the pointer to the plabel for the function. */
+ }
+ else
+ {
+ /* RRBC case; the virtual function pointers are found by double
+ * indirection through the class segment tables. */
+
+ /* Choose class segment depending on type we were passed */
+ class_index = class_index_in_primary_list (type);
+
+ /* Find class segment pointer. These are in the vtable slots after
+ * some other entries, so adjust by HP_ACC_VFUNC_START for that. */
+ /* pai: FIXME 32x64 problem here, if words are 8 bytes long
+ * the multiplier below has to be 8 and value should be long. */
+ vp = value_at (builtin_type_int,
+ coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL);
+ /* Indirect once more, offset by function index */
+ /* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */
+ coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp) + 4 * TYPE_FN_FIELD_VOFFSET (f, j));
+ vp = value_at (builtin_type_int, coreptr, NULL);
+ coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
+
+ /* coreptr now contains the address of the virtual function */
+ /* (Actually, it contains the pointer to the plabel for the function.) */
+
+ }
+
+ if (!coreptr)
+ error ("Address of virtual function is null; error in virtual table?");
+
+ /* Wrap this addr in a value and return pointer */
+ vp = allocate_value (ftype);
+ VALUE_TYPE (vp) = ftype;
+ VALUE_ADDRESS (vp) = coreptr;
+
+ /* pai: (temp) do we need the value_ind stuff in value_fn_field? */
+ return vp;
}
+ else
+ { /* Not using HP/Taligent runtime conventions; so try to
+ * use g++ conventions for virtual table */
+
+ struct type *entry_type;
+ /* First, get the virtual function table pointer. That comes
+ with a strange type, so cast it to type `pointer to long' (which
+ should serve just fine as a function type). Then, index into
+ the table, and convert final value to appropriate function type. */
+ value_ptr entry, vfn, vtbl;
+ value_ptr vi = value_from_longest (builtin_type_int,
+ (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+ struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
+ struct type *context;
+ if (fcontext == NULL)
+ /* We don't have an fcontext (e.g. the program was compiled with
+ g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE.
+ This won't work right for multiple inheritance, but at least we
+ should do as well as GDB 3.x did. */
+ fcontext = TYPE_VPTR_BASETYPE (type);
+ context = lookup_pointer_type (fcontext);
+ /* Now context is a pointer to the basetype containing the vtbl. */
+ if (TYPE_TARGET_TYPE (context) != type1)
+ {
+ value_ptr tmp = value_cast (context, value_addr (arg1));
+ VALUE_POINTED_TO_OFFSET (tmp) = 0;
+ arg1 = value_ind (tmp);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ }
+
+ context = type1;
+ /* Now context is the basetype containing the vtbl. */
+
+ /* This type may have been defined before its virtual function table
+ was. If so, fill in the virtual function table entry for the
+ type now. */
+ if (TYPE_VPTR_FIELDNO (context) < 0)
+ fill_in_vptr_fieldno (context);
+
+ /* The virtual function table is now an array of structures
+ which have the form { int16 offset, delta; void *pfn; }. */
+ vtbl = value_primitive_field (arg1, 0, TYPE_VPTR_FIELDNO (context),
+ TYPE_VPTR_BASETYPE (context));
+
+ /* With older versions of g++, the vtbl field pointed to an array
+ of structures. Nowadays it points directly to the structure. */
+ if (TYPE_CODE (VALUE_TYPE (vtbl)) == TYPE_CODE_PTR
+ && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (vtbl))) == TYPE_CODE_ARRAY)
+ {
+ /* Handle the case where the vtbl field points to an
+ array of structures. */
+ vtbl = value_ind (vtbl);
+
+ /* Index into the virtual function table. This is hard-coded because
+ looking up a field is not cheap, and it may be important to save
+ time, e.g. if the user has set a conditional breakpoint calling
+ a virtual function. */
+ entry = value_subscript (vtbl, vi);
+ }
+ else
+ {
+ /* Handle the case where the vtbl field points directly to a structure. */
+ vtbl = value_add (vtbl, vi);
+ entry = value_ind (vtbl);
+ }
- vfn = value_field (entry, 2);
- /* Reinstantiate the function pointer with the correct type. */
- VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+ entry_type = check_typedef (VALUE_TYPE (entry));
- *arg1p = arg1;
- return vfn;
+ if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
+ {
+ /* Move the `this' pointer according to the virtual function table. */
+ VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
+
+ if (!VALUE_LAZY (arg1))
+ {
+ VALUE_LAZY (arg1) = 1;
+ value_fetch_lazy (arg1);
+ }
+
+ vfn = value_field (entry, 2);
+ }
+ else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR)
+ vfn = entry;
+ else
+ error ("I'm confused: virtual function table has bad type");
+ /* Reinstantiate the function pointer with the correct type. */
+ VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+
+ *arg1p = arg1;
+ return vfn;
+ }
}
/* ARG is a pointer to an object we know to be at least
return the most derived type we find. The caller must
be satisfied when the return value == DTYPE.
- FIXME-tiemann: should work with dossier entries as well. */
+ FIXME-tiemann: should work with dossier entries as well.
+ NOTICE - djb: I see no good reason at all to keep this function now that
+ we have RTTI support. It's used in literally one place, and it's
+ hard to keep this function up to date when it's purpose is served
+ by value_rtti_type efficiently.
+ Consider it gone for 5.1. */
static value_ptr
-value_headof (in_arg, btype, dtype)
- value_ptr in_arg;
- struct type *btype, *dtype;
+value_headof (value_ptr in_arg, struct type *btype, struct type *dtype)
{
/* First collect the vtables we must look at for this object. */
- /* FIXME-tiemann: right now, just look at top-most vtable. */
- value_ptr arg, vtbl, entry, best_entry = 0;
- int i, nelems;
- int offset, best_offset = 0;
+ value_ptr arg, vtbl;
struct symbol *sym;
- CORE_ADDR pc_for_sym;
char *demangled_name;
struct minimal_symbol *msymbol;
btype = TYPE_VPTR_BASETYPE (dtype);
- check_stub_type (btype);
+ CHECK_TYPEDEF (btype);
arg = in_arg;
if (btype != dtype)
- arg = value_cast (lookup_pointer_type (btype), arg);
+ arg = value_cast (lookup_pointer_type (btype), arg);
+ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_REF)
+ {
+ /*
+ * Copy the value, but change the type from (T&) to (T*).
+ * We keep the same location information, which is efficient,
+ * and allows &(&X) to get the location containing the reference.
+ */
+ arg = value_copy (arg);
+ VALUE_TYPE (arg) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg)));
+ }
+ if (VALUE_ADDRESS(value_field (value_ind(arg), TYPE_VPTR_FIELDNO (btype)))==0)
+ return arg;
+
vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (btype)));
+ /* Turn vtable into typeinfo function */
+ VALUE_OFFSET(vtbl)+=4;
- /* Check that VTBL looks like it points to a virtual function table. */
- msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
+ msymbol = lookup_minimal_symbol_by_pc ( value_as_pointer(value_ind(vtbl)) );
if (msymbol == NULL
- || !VTBL_PREFIX_P (demangled_name = SYMBOL_NAME (msymbol)))
- {
- /* If we expected to find a vtable, but did not, let the user
- know that we aren't happy, but don't throw an error.
- FIXME: there has to be a better way to do this. */
- struct type *error_type = (struct type *)xmalloc (sizeof (struct type));
- memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type));
- TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
- VALUE_TYPE (in_arg) = error_type;
- return in_arg;
- }
+ || (demangled_name = SYMBOL_NAME (msymbol)) == NULL)
+ {
+ /* If we expected to find a vtable, but did not, let the user
+ know that we aren't happy, but don't throw an error.
+ FIXME: there has to be a better way to do this. */
+ struct type *error_type = (struct type *) xmalloc (sizeof (struct type));
+ memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type));
+ TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
+ VALUE_TYPE (in_arg) = error_type;
+ return in_arg;
+ }
+ demangled_name = cplus_demangle(demangled_name,DMGL_ANSI);
+ *(strchr (demangled_name, ' ')) = '\0';
- /* Now search through the virtual function table. */
- entry = value_ind (vtbl);
- nelems = longest_to_int (value_as_long (value_field (entry, 2)));
- for (i = 1; i <= nelems; i++)
- {
- entry = value_subscript (vtbl, value_from_longest (builtin_type_int,
- (LONGEST) i));
- offset = longest_to_int (value_as_long (value_field (entry, 0)));
- /* If we use '<=' we can handle single inheritance
- * where all offsets are zero - just use the first entry found. */
- if (offset <= best_offset)
- {
- best_offset = offset;
- best_entry = entry;
- }
- }
- /* Move the pointer according to BEST_ENTRY's offset, and figure
- out what type we should return as the new pointer. */
- if (best_entry == 0)
- {
- /* An alternative method (which should no longer be necessary).
- * But we leave it in for future use, when we will hopefully
- * have optimizes the vtable to use thunks instead of offsets. */
- /* Use the name of vtable itself to extract a base type. */
- demangled_name += 4; /* Skip _vt$ prefix. */
- }
- else
- {
- pc_for_sym = value_as_pointer (value_field (best_entry, 2));
- sym = find_pc_function (pc_for_sym);
- demangled_name = cplus_demangle (SYMBOL_NAME (sym), DMGL_ANSI);
- *(strchr (demangled_name, ':')) = '\0';
- }
sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);
if (sym == NULL)
- error ("could not find type declaration for `%s'", demangled_name);
- if (best_entry)
- {
- free (demangled_name);
- arg = value_add (value_cast (builtin_type_int, arg),
- value_field (best_entry, 0));
- }
- else arg = in_arg;
+ error ("could not find type declaration for `%s'", demangled_name);
+
+ arg = in_arg;
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg;
}
could actually be a pointer to. */
value_ptr
-value_from_vtable_info (arg, type)
- value_ptr arg;
- struct type *type;
+value_from_vtable_info (value_ptr arg, struct type *type)
{
/* Take care of preliminaries. */
if (TYPE_VPTR_FIELDNO (type) < 0)
fill_in_vptr_fieldno (type);
- if (TYPE_VPTR_FIELDNO (type) < 0 || VALUE_REPEATED (arg))
+ if (TYPE_VPTR_FIELDNO (type) < 0)
return 0;
return value_headof (arg, 0, type);
pointer which is for the base class whose type is BASECLASS. */
static int
-vb_match (type, index, basetype)
- struct type *type;
- int index;
- struct type *basetype;
+vb_match (struct type *type, int index, struct type *basetype)
{
struct type *fieldtype;
char *name = TYPE_FIELD_NAME (type, index);
if (*name != '_')
return 0;
/* gcc 2.4 uses _vb$. */
- if (name[1] == 'v' && name[2] == 'b' && name[3] == CPLUS_MARKER)
+ if (name[1] == 'v' && name[2] == 'b' && is_cplus_marker (name[3]))
field_class_name = name + 4;
/* gcc 2.5 will use __vb_. */
if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_')
}
/* Compute the offset of the baseclass which is
- the INDEXth baseclass of class TYPE, for a value ARG,
- wih extra offset of OFFSET.
- The result is the offste of the baseclass value relative
+ the INDEXth baseclass of class TYPE,
+ for value at VALADDR (in host) at ADDRESS (in target).
+ The result is the offset of the baseclass value relative
to (the address of)(ARG) + OFFSET.
-1 is returned on error. */
int
-baseclass_offset (type, index, arg, offset)
- struct type *type;
- int index;
- value_ptr arg;
- int offset;
+baseclass_offset (struct type *type, int index, char *valaddr,
+ CORE_ADDR address)
{
struct type *basetype = TYPE_BASECLASS (type, index);
register int n_baseclasses = TYPE_N_BASECLASSES (type);
/* First look for the virtual baseclass pointer
- in the fields. */
+ in the fields. */
for (i = n_baseclasses; i < len; i++)
{
if (vb_match (type, i, basetype))
{
CORE_ADDR addr
- = unpack_pointer (TYPE_FIELD_TYPE (type, i),
- VALUE_CONTENTS (arg) + VALUE_OFFSET (arg)
- + offset
- + (TYPE_FIELD_BITPOS (type, i) / 8));
-
- if (VALUE_LVAL (arg) != lval_memory)
- return -1;
+ = unpack_pointer (TYPE_FIELD_TYPE (type, i),
+ valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
- return addr -
- (LONGEST) (VALUE_ADDRESS (arg) + VALUE_OFFSET (arg) + offset);
+ return addr - (LONGEST) address;
}
}
/* Not in the fields, so try looking through the baseclasses. */
- for (i = index+1; i < n_baseclasses; i++)
+ for (i = index + 1; i < n_baseclasses; i++)
{
int boffset =
- baseclass_offset (type, i, arg, offset);
+ baseclass_offset (type, i, valaddr, address);
if (boffset)
return boffset;
}
/* Baseclass is easily computed. */
return TYPE_BASECLASS_BITPOS (type, index) / 8;
}
-
-/* Compute the address of the baseclass which is
- the INDEXth baseclass of class TYPE. The TYPE base
- of the object is at VALADDR.
-
- If ERRP is non-NULL, set *ERRP to be the errno code of any error,
- or 0 if no error. In that case the return value is not the address
- of the baseclasss, but the address which could not be read
- successfully. */
-
-/* FIXME Fix remaining uses of baseclass_addr to use baseclass_offset */
-
-char *
-baseclass_addr (type, index, valaddr, valuep, errp)
- struct type *type;
- int index;
- char *valaddr;
- value_ptr *valuep;
- int *errp;
-{
- struct type *basetype = TYPE_BASECLASS (type, index);
-
- if (errp)
- *errp = 0;
-
- if (BASETYPE_VIA_VIRTUAL (type, index))
- {
- /* Must hunt for the pointer to this virtual baseclass. */
- register int i, len = TYPE_NFIELDS (type);
- register int n_baseclasses = TYPE_N_BASECLASSES (type);
-
- /* First look for the virtual baseclass pointer
- in the fields. */
- for (i = n_baseclasses; i < len; i++)
- {
- if (vb_match (type, i, basetype))
- {
- value_ptr val = allocate_value (basetype);
- CORE_ADDR addr;
- int status;
-
- addr
- = unpack_pointer (TYPE_FIELD_TYPE (type, i),
- valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
-
- status = target_read_memory (addr,
- VALUE_CONTENTS_RAW (val),
- TYPE_LENGTH (basetype));
- VALUE_LVAL (val) = lval_memory;
- VALUE_ADDRESS (val) = addr;
-
- if (status != 0)
- {
- if (valuep)
- *valuep = NULL;
- release_value (val);
- value_free (val);
- if (errp)
- *errp = status;
- return (char *)addr;
- }
- else
- {
- if (valuep)
- *valuep = val;
- return (char *) VALUE_CONTENTS (val);
- }
- }
- }
- /* Not in the fields, so try looking through the baseclasses. */
- for (i = index+1; i < n_baseclasses; i++)
- {
- char *baddr;
-
- baddr = baseclass_addr (type, i, valaddr, valuep, errp);
- if (baddr)
- return baddr;
- }
- /* Not found. */
- if (valuep)
- *valuep = 0;
- return 0;
- }
-
- /* Baseclass is easily computed. */
- if (valuep)
- *valuep = 0;
- return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8;
-}
\f
/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
VALADDR.
If the field is signed, we also do sign extension. */
LONGEST
-unpack_field_as_long (type, valaddr, fieldno)
- struct type *type;
- char *valaddr;
- int fieldno;
+unpack_field_as_long (struct type *type, char *valaddr, int fieldno)
{
- unsigned LONGEST val;
- unsigned LONGEST valmask;
+ ULONGEST val;
+ ULONGEST valmask;
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
int lsbcount;
+ struct type *field_type;
val = extract_unsigned_integer (valaddr + bitpos / 8, sizeof (val));
+ field_type = TYPE_FIELD_TYPE (type, fieldno);
+ CHECK_TYPEDEF (field_type);
/* Extract bits. See comment above. */
-#if BITS_BIG_ENDIAN
- lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);
-#else
- lsbcount = (bitpos % 8);
-#endif
+ if (BITS_BIG_ENDIAN)
+ lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);
+ else
+ lsbcount = (bitpos % 8);
val >>= lsbcount;
/* If the field does not entirely fill a LONGEST, then zero the sign bits.
If the field is signed, and is negative, then sign extend. */
- if ((bitsize > 0) && (bitsize < 8 * sizeof (val)))
+ if ((bitsize > 0) && (bitsize < 8 * (int) sizeof (val)))
{
- valmask = (((unsigned LONGEST) 1) << bitsize) - 1;
+ valmask = (((ULONGEST) 1) << bitsize) - 1;
val &= valmask;
- if (!TYPE_UNSIGNED (TYPE_FIELD_TYPE (type, fieldno)))
+ if (!TYPE_UNSIGNED (field_type))
{
if (val & (valmask ^ (valmask >> 1)))
{
indicate which bits (in target bit order) comprise the bitfield. */
void
-modify_field (addr, fieldval, bitpos, bitsize)
- char *addr;
- LONGEST fieldval;
- int bitpos, bitsize;
+modify_field (char *addr, LONGEST fieldval, int bitpos, int bitsize)
{
LONGEST oword;
- /* Reject values too big to fit in the field in question,
- otherwise adjoining fields may be corrupted. */
- if (bitsize < (8 * sizeof (fieldval))
- && 0 != (fieldval & ~((1<<bitsize)-1)))
+ /* If a negative fieldval fits in the field in question, chop
+ off the sign extension bits. */
+ if (bitsize < (8 * (int) sizeof (fieldval))
+ && (~fieldval & ~((1 << (bitsize - 1)) - 1)) == 0)
+ fieldval = fieldval & ((1 << bitsize) - 1);
+
+ /* Warn if value is too big to fit in the field in question. */
+ if (bitsize < (8 * (int) sizeof (fieldval))
+ && 0 != (fieldval & ~((1 << bitsize) - 1)))
{
/* FIXME: would like to include fieldval in the message, but
- we don't have a sprintf_longest. */
- error ("Value does not fit in %d bits.", bitsize);
+ we don't have a sprintf_longest. */
+ warning ("Value does not fit in %d bits.", bitsize);
+
+ /* Truncate it, otherwise adjoining fields may be corrupted. */
+ fieldval = fieldval & ((1 << bitsize) - 1);
}
oword = extract_signed_integer (addr, sizeof oword);
/* Shifting for bit field depends on endianness of the target machine. */
-#if BITS_BIG_ENDIAN
- bitpos = sizeof (oword) * 8 - bitpos - bitsize;
-#endif
+ if (BITS_BIG_ENDIAN)
+ bitpos = sizeof (oword) * 8 - bitpos - bitsize;
/* Mask out old value, while avoiding shifts >= size of oword */
- if (bitsize < 8 * sizeof (oword))
- oword &= ~(((((unsigned LONGEST)1) << bitsize) - 1) << bitpos);
+ if (bitsize < 8 * (int) sizeof (oword))
+ oword &= ~(((((ULONGEST) 1) << bitsize) - 1) << bitpos);
else
- oword &= ~((~(unsigned LONGEST)0) << bitpos);
+ oword &= ~((~(ULONGEST) 0) << bitpos);
oword |= fieldval << bitpos;
store_signed_integer (addr, sizeof oword, oword);
/* Convert C numbers into newly allocated values */
value_ptr
-value_from_longest (type, num)
- struct type *type;
- register LONGEST num;
+value_from_longest (struct type *type, register LONGEST num)
{
register value_ptr val = allocate_value (type);
- register enum type_code code = TYPE_CODE (type);
- register int len = TYPE_LENGTH (type);
+ register enum type_code code;
+ register int len;
+retry:
+ code = TYPE_CODE (type);
+ len = TYPE_LENGTH (type);
switch (code)
{
+ case TYPE_CODE_TYPEDEF:
+ type = check_typedef (type);
+ goto retry;
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
case TYPE_CODE_ENUM:
case TYPE_CODE_BOOL:
+ case TYPE_CODE_RANGE:
store_signed_integer (VALUE_CONTENTS_RAW (val), len, num);
break;
-
+
case TYPE_CODE_REF:
case TYPE_CODE_PTR:
- /* This assumes that all pointers of a given length
- have the same form. */
- store_address (VALUE_CONTENTS_RAW (val), len, (CORE_ADDR) num);
+ store_typed_address (VALUE_CONTENTS_RAW (val), type, (CORE_ADDR) num);
break;
default:
- error ("Unexpected type encountered for integer constant.");
+ error ("Unexpected type (%d) encountered for integer constant.", code);
}
return val;
}
+
+/* Create a value representing a pointer of type TYPE to the address
+ ADDR. */
value_ptr
-value_from_double (type, num)
- struct type *type;
- double num;
+value_from_pointer (struct type *type, CORE_ADDR addr)
+{
+ value_ptr val = allocate_value (type);
+ store_typed_address (VALUE_CONTENTS_RAW (val), type, addr);
+ return val;
+}
+
+
+/* Create a value for a string constant to be stored locally
+ (not in the inferior's memory space, but in GDB memory).
+ This is analogous to value_from_longest, which also does not
+ use inferior memory. String shall NOT contain embedded nulls. */
+
+value_ptr
+value_from_string (char *ptr)
+{
+ value_ptr val;
+ int len = strlen (ptr);
+ int lowbound = current_language->string_lower_bound;
+ struct type *rangetype =
+ create_range_type ((struct type *) NULL,
+ builtin_type_int,
+ lowbound, len + lowbound - 1);
+ struct type *stringtype =
+ create_array_type ((struct type *) NULL,
+ *current_language->string_char_type,
+ rangetype);
+
+ val = allocate_value (stringtype);
+ memcpy (VALUE_CONTENTS_RAW (val), ptr, len);
+ return val;
+}
+
+value_ptr
+value_from_double (struct type *type, DOUBLEST num)
{
register value_ptr val = allocate_value (type);
- register enum type_code code = TYPE_CODE (type);
- register int len = TYPE_LENGTH (type);
+ struct type *base_type = check_typedef (type);
+ register enum type_code code = TYPE_CODE (base_type);
+ register int len = TYPE_LENGTH (base_type);
if (code == TYPE_CODE_FLT)
{
0 when it is using the value returning conventions (this often
means returning pointer to where structure is vs. returning value). */
+/* ARGSUSED */
value_ptr
-value_being_returned (valtype, retbuf, struct_return)
- register struct type *valtype;
- char retbuf[REGISTER_BYTES];
- int struct_return;
- /*ARGSUSED*/
+value_being_returned (struct type *valtype, char *retbuf, int struct_return)
{
register value_ptr val;
CORE_ADDR addr;
-#if defined (EXTRACT_STRUCT_VALUE_ADDRESS)
/* If this is not defined, just use EXTRACT_RETURN_VALUE instead. */
- if (struct_return) {
- addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf);
- if (!addr)
- error ("Function return value unknown");
- return value_at (valtype, addr);
- }
-#endif
+ if (EXTRACT_STRUCT_VALUE_ADDRESS_P)
+ if (struct_return)
+ {
+ addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf);
+ if (!addr)
+ error ("Function return value unknown");
+ return value_at (valtype, addr, NULL);
+ }
val = allocate_value (valtype);
+ CHECK_TYPEDEF (valtype);
EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val));
return val;
2.0-2.3.3. This is somewhat unfortunate, but changing gcc2_compiled
would cause more chaos than dealing with some struct returns being
handled wrong. */
-#if !defined (USE_STRUCT_CONVENTION)
-#define USE_STRUCT_CONVENTION(gcc_p, type)\
- (!((gcc_p == 1) && (TYPE_LENGTH (value_type) == 1 \
- || TYPE_LENGTH (value_type) == 2 \
- || TYPE_LENGTH (value_type) == 4 \
- || TYPE_LENGTH (value_type) == 8 \
- ) \
- ))
+
+int
+generic_use_struct_convention (int gcc_p, struct type *value_type)
+{
+ return !((gcc_p == 1)
+ && (TYPE_LENGTH (value_type) == 1
+ || TYPE_LENGTH (value_type) == 2
+ || TYPE_LENGTH (value_type) == 4
+ || TYPE_LENGTH (value_type) == 8));
+}
+
+#ifndef USE_STRUCT_CONVENTION
+#define USE_STRUCT_CONVENTION(gcc_p,type) generic_use_struct_convention (gcc_p, type)
#endif
+
/* Return true if the function specified is using the structure returning
convention on this machine to return arguments, or 0 if it is using
the value returning convention. FUNCTION is the value representing
is the type returned by the function. GCC_P is nonzero if compiled
with GCC. */
+/* ARGSUSED */
int
-using_struct_return (function, funcaddr, value_type, gcc_p)
- value_ptr function;
- CORE_ADDR funcaddr;
- struct type *value_type;
- int gcc_p;
- /*ARGSUSED*/
+using_struct_return (value_ptr function, CORE_ADDR funcaddr,
+ struct type *value_type, int gcc_p)
{
register enum type_code code = TYPE_CODE (value_type);
if (code == TYPE_CODE_ERROR)
error ("Function return type unknown.");
- if (code == TYPE_CODE_STRUCT ||
- code == TYPE_CODE_UNION ||
- code == TYPE_CODE_ARRAY)
+ if (code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION
+ || code == TYPE_CODE_ARRAY
+ || RETURN_VALUE_ON_STACK (value_type))
return USE_STRUCT_CONVENTION (gcc_p, value_type);
return 0;
function wants to return. */
void
-set_return_value (val)
- value_ptr val;
+set_return_value (value_ptr val)
{
- register enum type_code code = TYPE_CODE (VALUE_TYPE (val));
- double dbuf;
- LONGEST lbuf;
+ struct type *type = check_typedef (VALUE_TYPE (val));
+ register enum type_code code = TYPE_CODE (type);
if (code == TYPE_CODE_ERROR)
error ("Function return type unknown.");
- if ( code == TYPE_CODE_STRUCT
+ if (code == TYPE_CODE_STRUCT
|| code == TYPE_CODE_UNION) /* FIXME, implement struct return. */
error ("GDB does not support specifying a struct or union return value.");
- /* FIXME, this is bogus. We don't know what the return conventions
- are, or how values should be promoted.... */
- if (code == TYPE_CODE_FLT)
- {
- dbuf = value_as_double (val);
-
- STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&dbuf);
- }
- else
- {
- lbuf = value_as_long (val);
- STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&lbuf);
- }
+ STORE_RETURN_VALUE (type, VALUE_CONTENTS (val));
}
\f
void
-_initialize_values ()
+_initialize_values (void)
{
add_cmd ("convenience", no_class, show_convenience,
- "Debugger convenience (\"$foo\") variables.\n\
+ "Debugger convenience (\"$foo\") variables.\n\
These variables are created when you assign them values;\n\
thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\n\
A few convenience variables are given values automatically:\n\