/* Low level packing and unpacking of values for GDB, the GNU Debugger.
- Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1989, 1991, 1993, 1994, 1995
+ Free Software Foundation, Inc.
This file is part of GDB.
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. */
+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 "demangle.h"
/* Local function prototypes. */
-static value
-value_headof PARAMS ((value, struct type *, struct type *));
+static value_ptr value_headof PARAMS ((value_ptr, struct type *,
+ struct type *));
-static void
-show_values PARAMS ((char *, int));
+static void show_values PARAMS ((char *, int));
-static void
-show_convenience PARAMS ((char *, int));
+static void show_convenience PARAMS ((char *, int));
/* The value-history records all the values printed
by print commands during this session. Each chunk
struct value_history_chunk
{
struct value_history_chunk *next;
- value values[VALUE_HISTORY_CHUNK];
+ value_ptr values[VALUE_HISTORY_CHUNK];
};
/* Chain of chunks now in use. */
(except for those released by calls to release_value)
This is so they can be freed after each command. */
-static value all_values;
+static value_ptr all_values;
/* Allocate a value that has the correct length for type TYPE. */
-value
+value_ptr
allocate_value (type)
struct type *type;
{
- register value val;
-
- check_stub_type (type);
+ register value_ptr val;
+ struct type *atype = check_typedef (type);
- val = (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_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;
+ val->modifiable = 1;
return val;
}
/* Allocate a value that has the correct length
for COUNT repetitions type TYPE. */
-value
+value_ptr
allocate_repeat_value (type, count)
struct type *type;
int count;
{
- register value val;
-
- val = (value) 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;
+ struct type *element_type = type;
+ 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
+value_ptr
value_mark ()
{
return all_values;
(except for those released). */
void
value_free_to_mark (mark)
- value mark;
+ value_ptr mark;
{
- value val, next;
+ value_ptr val, next;
for (val = all_values; val && val != mark; val = next)
{
void
free_all_values ()
{
- register value val, next;
+ register value_ptr val, next;
for (val = all_values; val; val = next)
{
void
release_value (val)
- register value val;
+ register value_ptr val;
{
- register value v;
+ register value_ptr v;
if (all_values == val)
{
}
}
+/* Release all values up to mark */
+value_ptr
+value_release_to_mark (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
+value_ptr
value_copy (arg)
- value arg;
+ value_ptr arg;
{
- register value 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 value_ptr val = allocate_value (type);
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);
+ 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));
+ TYPE_LENGTH (VALUE_TYPE (arg)));
}
return val;
}
int
record_latest_value (val)
- value val;
+ 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) {
- (void) unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i);
- if (i) return -1; /* Indicate value not saved in history */
- }
+ 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. */
register struct value_history_chunk *new
= (struct value_history_chunk *)
xmalloc (sizeof (struct value_history_chunk));
- (void) memset (new->values, 0, sizeof new->values);
+ memset (new->values, 0, sizeof new->values);
new->next = value_history_chain;
value_history_chain = new;
}
value_history_chain->values[i] = val;
- 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
+value_ptr
access_value_history (num)
int num;
{
{
register struct value_history_chunk *next;
register int i;
- register value val;
+ register value_ptr val;
while (value_history_chain)
{
for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
- if (val = value_history_chain->values[i])
+ if ((val = value_history_chain->values[i]) != NULL)
free ((PTR)val);
next = value_history_chain->next;
free ((PTR)value_history_chain);
int from_tty;
{
register int i;
- register value val;
+ register value_ptr val;
static int num = 1;
if (num_exp)
{
- if (num_exp[0] == '+' && num_exp[1] == '\0')
- /* "info history +" should print from the stored position. */
- ;
- else
- /* "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;
}
else
{
val = access_value_history (i);
printf_filtered ("$%d = ", i);
- value_print (val, stdout, 0, Val_pretty_default);
+ value_print (val, gdb_stdout, 0, Val_pretty_default);
printf_filtered ("\n");
}
register struct internalvar *var;
for (var = internalvars; var; var = var->next)
- if (!strcmp (var->name, name))
+ if (STREQ (var->name, name))
return var;
var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
return var;
}
-value
+value_ptr
value_of_internalvar (var)
struct internalvar *var;
{
- register value val;
+ register value_ptr val;
#ifdef IS_TRAPPED_INTERNALVAR
if (IS_TRAPPED_INTERNALVAR (var->name))
set_internalvar_component (var, offset, bitpos, bitsize, newval)
struct internalvar *var;
int offset, bitpos, bitsize;
- value newval;
+ value_ptr newval;
{
register char *addr = VALUE_CONTENTS (var->value) + offset;
#endif
if (bitsize)
- modify_field (addr, (int) value_as_long (newval),
+ modify_field (addr, value_as_long (newval),
bitpos, bitsize);
else
- (void) memcpy (addr, VALUE_CONTENTS (newval),
- TYPE_LENGTH (VALUE_TYPE (newval)));
+ memcpy (addr, VALUE_CONTENTS (newval), TYPE_LENGTH (VALUE_TYPE (newval)));
}
void
set_internalvar (var, val)
struct internalvar *var;
- value val;
+ value_ptr val;
{
+ value_ptr newval;
+
#ifdef IS_TRAPPED_INTERNALVAR
if (IS_TRAPPED_INTERNALVAR (var->name))
SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0);
#endif
- free ((PTR)var->value);
- var->value = value_copy (val);
+ 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
has changed. */
- if (VALUE_LAZY (var->value))
- value_fetch_lazy (var->value);
- release_value (var->value);
+ if (VALUE_LAZY (newval))
+ value_fetch_lazy (newval);
+
+ /* Begin code which must not call error(). If var->value points to
+ something free'd, an error() obviously leaves a dangling pointer.
+ But we also get a danling pointer if var->value points to
+ 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);
+ var->value = newval;
+ release_value (newval);
+ /* End code which must not call error(). */
}
char *
varseen = 1;
}
printf_filtered ("$%s = ", var->name);
- value_print (var->value, stdout, 0, Val_pretty_default);
+ value_print (var->value, gdb_stdout, 0, Val_pretty_default);
printf_filtered ("\n");
}
if (!varseen)
- printf ("No debugger convenience variables now defined.\n\
+ printf_unfiltered ("No debugger convenience variables now defined.\n\
Convenience variables have names starting with \"$\";\n\
use \"set\" as in \"set $foo = 5\" to define them.\n");
}
LONGEST
value_as_long (val)
- register value val;
+ 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 val;
+ register value_ptr val;
{
double foo;
int inv;
Does not deallocate the value. */
CORE_ADDR
value_as_pointer (val)
- value val;
+ value_ptr val;
{
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
+#if 0
+ /* 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));
+#else
+ return value_as_long (val);
+#endif
}
\f
/* Unpack raw data (copied from debugee, target byte order) at VALADDR
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;
register int len = TYPE_LENGTH (type);
register int nosign = TYPE_UNSIGNED (type);
- if (code == TYPE_CODE_ENUM || code == TYPE_CODE_BOOL)
- code = TYPE_CODE_INT;
- if (code == TYPE_CODE_FLT)
- {
- if (len == sizeof (float))
- {
- float retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
+ if (current_language->la_language == language_scm
+ && is_scmvalue_type (type))
+ return scm_unpack (type, valaddr, TYPE_CODE_INT);
- if (len == sizeof (double))
- {
- double retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
- else
- {
- error ("Unexpected type of floating point number.");
- }
- }
- else if (code == TYPE_CODE_INT && nosign)
+ switch (code)
{
- if (len == sizeof (char))
- {
- unsigned char retval = * (unsigned char *) valaddr;
- /* SWAP_TARGET_AND_HOST (&retval, sizeof (unsigned char)); */
- return retval;
- }
-
- if (len == sizeof (short))
- {
- unsigned short retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (int))
- {
- unsigned int retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (long))
- {
- unsigned long retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- {
- unsigned long long retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-#endif
+ 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
- {
- error ("That operation is not possible on an integer of that size.");
- }
- }
- else if (code == TYPE_CODE_INT)
- {
- if (len == sizeof (char))
- {
- SIGNED char retval; /* plain chars might be unsigned on host */
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
+ return extract_signed_integer (valaddr, len);
- if (len == sizeof (short))
- {
- short retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
+ case TYPE_CODE_FLT:
+ return extract_floating (valaddr, len);
- if (len == sizeof (int))
- {
- int retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
+ 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);
- if (len == sizeof (long))
- {
- long retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
+ case TYPE_CODE_MEMBER:
+ error ("not implemented: member types in unpack_long");
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- {
- long long retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-#endif
- else
- {
- error ("That operation is not possible on an integer of that size.");
- }
+ default:
+ error ("Value can't be converted to integer.");
}
- /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
- whether we want this to be true eventually. */
- else if (code == TYPE_CODE_PTR
- || code == TYPE_CODE_REF)
- {
- if (len == sizeof(long))
- {
- unsigned long retval;
- (void) memcpy (&retval, valaddr, sizeof(retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof(retval));
- return retval;
- }
- else if (len == sizeof(short))
- {
- unsigned short retval;
- (void) memcpy (&retval, valaddr, len);
- SWAP_TARGET_AND_HOST (&retval, len);
- return retval;
- }
- }
- else if (code == TYPE_CODE_MEMBER)
- error ("not implemented: member types in unpack_long");
- else if (code == TYPE_CODE_CHAR)
- return *(unsigned char *)valaddr;
-
- error ("Value not integer or pointer.");
- return 0; /* For lint -- never reached */
+ return 0; /* Placate lint. */
}
/* Return a double value from the specified type and address.
register int nosign = TYPE_UNSIGNED (type);
*invp = 0; /* Assume valid. */
+ CHECK_TYPEDEF (type);
if (code == TYPE_CODE_FLT)
{
+#ifdef INVALID_FLOAT
if (INVALID_FLOAT (valaddr, len))
{
*invp = 1;
return 1.234567891011121314;
}
-
- if (len == sizeof (float))
- {
- float retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (double))
- {
- double retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
- else
- {
- error ("Unexpected type of floating point number.");
- return 0; /* Placate lint. */
- }
- }
- else if (nosign) {
- /* Unsigned -- be sure we compensate for signed LONGEST. */
-#ifdef LONG_LONG
- return (unsigned long long) unpack_long (type, valaddr);
-#else
- return (unsigned long ) unpack_long (type, valaddr);
#endif
- } else {
- /* Signed -- we are OK with unpack_long. */
- return unpack_long (type, valaddr);
- }
+ return extract_floating (valaddr, len);
+ }
+ else if (nosign)
+ {
+ /* Unsigned -- be sure we compensate for signed LONGEST. */
+ return (unsigned LONGEST) unpack_long (type, valaddr);
+ }
+ else
+ {
+ /* Signed -- we are OK with unpack_long. */
+ return unpack_long (type, valaddr);
+ }
}
/* Unpack raw data (copied from debugee, target byte order) at VALADDR
struct type *type;
char *valaddr;
{
-#if 0
- /* The user should be able to use an int (e.g. 0x7892) in contexts
- where a pointer is expected. So this doesn't do enough. */
- register enum type_code code = TYPE_CODE (type);
- register int len = TYPE_LENGTH (type);
-
- if (code == TYPE_CODE_PTR
- || code == TYPE_CODE_REF)
- {
- if (len == sizeof (CORE_ADDR))
- {
- CORE_ADDR retval;
- (void) memcpy (&retval, valaddr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
- error ("Unrecognized pointer size.");
- }
- else if (code == TYPE_CODE_MEMBER)
- error ("not implemented: member types in unpack_pointer");
-
- error ("Value is not a pointer.");
- return 0; /* For lint -- never reached */
-#else
/* 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);
-#endif
}
\f
/* Given a value ARG1 (offset by OFFSET bytes)
For C++, must also be able to return values from static fields */
-value
+value_ptr
value_primitive_field (arg1, offset, fieldno, arg_type)
- register value arg1;
+ register value_ptr arg1;
int offset;
register int fieldno;
register struct type *arg_type;
{
- register value v;
+ 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 */
if (VALUE_LAZY (arg1))
VALUE_LAZY (v) = 1;
else
- (void) memcpy (VALUE_CONTENTS_RAW (v),
- VALUE_CONTENTS_RAW (arg1) + offset, TYPE_LENGTH (type));
+ memcpy (VALUE_CONTENTS_RAW (v), VALUE_CONTENTS_RAW (arg1) + offset,
+ TYPE_LENGTH (type));
}
VALUE_LVAL (v) = VALUE_LVAL (arg1);
if (VALUE_LVAL (arg1) == lval_internalvar)
For C++, must also be able to return values from static fields */
-value
+value_ptr
value_field (arg1, fieldno)
- register value arg1;
+ register value_ptr arg1;
register int fieldno;
{
return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1));
F is the list of member functions which contains the desired method.
J is an index into F which provides the desired method. */
-value
-value_fn_field (f, j)
+value_ptr
+value_fn_field (arg1p, f, j, type, offset)
+ value_ptr *arg1p;
struct fn_field *f;
int j;
+ struct type *type;
+ int offset;
{
- register value v;
- register struct type *type = TYPE_FN_FIELD_TYPE (f, j);
+ register value_ptr v;
+ register struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
struct symbol *sym;
sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
0, VAR_NAMESPACE, 0, NULL);
- if (! sym) error ("Internal error: could not find physical method named %s",
+ if (! sym)
+ return NULL;
+/*
+ error ("Internal error: could not find physical method named %s",
TYPE_FN_FIELD_PHYSNAME (f, j));
+*/
- v = allocate_value (type);
+ v = allocate_value (ftype);
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
- VALUE_TYPE (v) = type;
+ 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;
+ */
+ }
+
return v;
}
/* Return a virtual function as a value.
ARG1 is the object which provides the virtual function
- table pointer. ARG1 is side-effected in calling this function.
+ table pointer. *ARG1P is side-effected in calling this function.
F is the list of member functions which contains the desired virtual
function.
J is an index into F which provides the desired virtual function.
TYPE is the type in which F is located. */
-value
-value_virtual_fn_field (arg1, f, j, type)
- value arg1;
+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_ptr arg1 = *arg1p;
+ struct type *type1 = check_typedef (VALUE_TYPE (arg1));
+ 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 entry, vfn, vtbl;
- value vi = value_from_longest (builtin_type_int,
- (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+ 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)
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)));
+ if (TYPE_TARGET_TYPE (context) != type1)
+ {
+ arg1 = value_ind (value_cast (context, value_addr (arg1)));
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ }
- context = VALUE_TYPE (arg1);
+ context = type1;
/* Now context is the basetype containing the vtbl. */
/* This type may have been defined before its virtual function table
/* The virtual function table is now an array of structures
which have the form { int16 offset, delta; void *pfn; }. */
- vtbl = value_ind (value_field (arg1, TYPE_VPTR_FIELDNO (context)));
+ 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);
+ entry_type = check_typedef (VALUE_TYPE (entry));
- /* Move the `this' pointer according to the virtual function table. */
- VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
- if (! VALUE_LAZY (arg1))
+ if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
{
- VALUE_LAZY (arg1) = 1;
- value_fetch_lazy (arg1);
- }
+ /* 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);
+ 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;
}
FIXME-tiemann: should work with dossier entries as well. */
-static value
-value_headof (arg, btype, dtype)
- value arg;
+static value_ptr
+value_headof (in_arg, btype, dtype)
+ value_ptr in_arg;
struct type *btype, *dtype;
{
/* First collect the vtables we must look at for this object. */
/* FIXME-tiemann: right now, just look at top-most vtable. */
- value vtbl, entry, best_entry = 0;
+ value_ptr arg, vtbl, entry, best_entry = 0;
int i, nelems;
int offset, best_offset = 0;
struct symbol *sym;
struct minimal_symbol *msymbol;
btype = TYPE_VPTR_BASETYPE (dtype);
- check_stub_type (btype);
+ CHECK_TYPEDEF (btype);
+ arg = in_arg;
if (btype != dtype)
- vtbl = value_cast (lookup_pointer_type (btype), arg);
- else
- vtbl = arg;
- vtbl = value_ind (value_field (value_ind (vtbl), TYPE_VPTR_FIELDNO (btype)));
+ arg = value_cast (lookup_pointer_type (btype), arg);
+ vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (btype)));
/* Check that VTBL looks like it points to a virtual function table. */
msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
if (msymbol == NULL
- || !VTBL_PREFIX_P (demangled_name = msymbol -> name))
+ || (demangled_name = SYMBOL_NAME (msymbol)) == NULL
+ || !VTBL_PREFIX_P (demangled_name))
{
/* 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));
- (void) memcpy (error_type, VALUE_TYPE (arg), sizeof (struct type));
+ memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type));
TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
- VALUE_TYPE (arg) = error_type;
- return arg;
+ VALUE_TYPE (in_arg) = error_type;
+ return in_arg;
}
/* Now search through the virtual function table. */
{
entry = value_subscript (vtbl, value_from_longest (builtin_type_int,
(LONGEST) i));
+ /* This won't work if we're using thunks. */
+ if (TYPE_CODE (check_typedef (VALUE_TYPE (entry))) != TYPE_CODE_STRUCT)
+ break;
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. */
{
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), 0);
+ 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 == 0)
- error ("could not find type declaration for `%s'", SYMBOL_NAME (sym));
+ 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;
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg;
}
of its baseclasses) to figure out the most derived type that ARG
could actually be a pointer to. */
-value
+value_ptr
value_from_vtable_info (arg, type)
- value arg;
+ 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);
}
-/* Compute the address of the baseclass which is
- the INDEXth baseclass of class TYPE. The TYPE base
- of the object is at VALADDR.
+/* Return true if the INDEXth field of TYPE is a virtual baseclass
+ 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;
+{
+ struct type *fieldtype;
+ char *name = TYPE_FIELD_NAME (type, index);
+ char *field_class_name = NULL;
+
+ if (*name != '_')
+ return 0;
+ /* gcc 2.4 uses _vb$. */
+ if (name[1] == 'v' && name[2] == 'b' && name[3] == CPLUS_MARKER)
+ field_class_name = name + 4;
+ /* gcc 2.5 will use __vb_. */
+ if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_')
+ field_class_name = name + 5;
+
+ if (field_class_name == NULL)
+ /* This field is not a virtual base class pointer. */
+ return 0;
+
+ /* It's a virtual baseclass pointer, now we just need to find out whether
+ it is for this baseclass. */
+ fieldtype = TYPE_FIELD_TYPE (type, index);
+ if (fieldtype == NULL
+ || TYPE_CODE (fieldtype) != TYPE_CODE_PTR)
+ /* "Can't happen". */
+ return 0;
+
+ /* What we check for is that either the types are equal (needed for
+ nameless types) or have the same name. This is ugly, and a more
+ elegant solution should be devised (which would probably just push
+ the ugliness into symbol reading unless we change the stabs format). */
+ if (TYPE_TARGET_TYPE (fieldtype) == basetype)
+ return 1;
+
+ if (TYPE_NAME (basetype) != NULL
+ && TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)) != NULL
+ && STREQ (TYPE_NAME (basetype),
+ TYPE_NAME (TYPE_TARGET_TYPE (fieldtype))))
+ return 1;
+ return 0;
+}
+
+/* Compute the offset of the baseclass which is
+ 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.
- 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. */
+ -1 is returned on error. */
-char *
-baseclass_addr (type, index, valaddr, valuep, errp)
+int
+baseclass_offset (type, index, valaddr, address)
struct type *type;
int index;
char *valaddr;
- value *valuep;
- int *errp;
+ CORE_ADDR address;
{
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);
- char *vbase_name, *type_name = type_name_no_tag (basetype);
- vbase_name = (char *)alloca (strlen (type_name) + 8);
- sprintf (vbase_name, "_vb$%s", type_name);
/* First look for the virtual baseclass pointer
in the fields. */
for (i = n_baseclasses; i < len; i++)
{
- if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i)))
+ if (vb_match (type, i, basetype))
{
- value val = allocate_value (basetype);
- CORE_ADDR addr;
- int status;
-
- addr
+ CORE_ADDR 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);
- }
+ return addr - (LONGEST) address;
}
}
/* 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;
+ int boffset =
+ baseclass_offset (type, i, valaddr, address);
+ if (boffset)
+ return boffset;
}
/* Not found. */
- if (valuep)
- *valuep = 0;
- return 0;
+ return -1;
}
/* Baseclass is easily computed. */
- if (valuep)
- *valuep = 0;
- return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8;
+ return TYPE_BASECLASS_BITPOS (type, index) / 8;
}
\f
/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
int lsbcount;
- (void) memcpy (&val, valaddr + bitpos / 8, sizeof (val));
- SWAP_TARGET_AND_HOST (&val, sizeof (val));
+ val = extract_unsigned_integer (valaddr + bitpos / 8, sizeof (val));
/* 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.
void
modify_field (addr, fieldval, bitpos, bitsize)
char *addr;
- int fieldval;
+ LONGEST fieldval;
int bitpos, bitsize;
{
- long oword;
+ LONGEST oword;
+
+ /* If a negative fieldval fits in the field in question, chop
+ off the sign extension bits. */
+ if (bitsize < (8 * sizeof (fieldval))
+ && (~fieldval & ~((1 << (bitsize - 1)) - 1)) == 0)
+ fieldval = fieldval & ((1 << bitsize) - 1);
- /* Reject values too big to fit in the field in question,
- otherwise adjoining fields may be corrupted. */
+ /* Warn if value is too big to fit in the field in question. */
if (bitsize < (8 * sizeof (fieldval))
&& 0 != (fieldval & ~((1<<bitsize)-1)))
- error ("Value %d does not fit in %d bits.", fieldval, bitsize);
-
- (void) memcpy (&oword, addr, sizeof oword);
- SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To host format */
+ {
+ /* 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);
+
+ /* 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 >= longword size */
+ /* Mask out old value, while avoiding shifts >= size of oword */
if (bitsize < 8 * sizeof (oword))
- oword &= ~(((((unsigned long)1) << bitsize) - 1) << bitpos);
+ oword &= ~(((((unsigned LONGEST)1) << bitsize) - 1) << bitpos);
else
- oword &= ~((-1) << bitpos);
+ oword &= ~((~(unsigned LONGEST)0) << bitpos);
oword |= fieldval << bitpos;
- SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To target format */
- (void) memcpy (addr, &oword, sizeof oword);
+ store_signed_integer (addr, sizeof oword, oword);
}
\f
/* Convert C numbers into newly allocated values */
-value
+value_ptr
value_from_longest (type, num)
struct type *type;
register LONGEST num;
{
- register value val = allocate_value (type);
- register enum type_code code = TYPE_CODE (type);
- register int len = TYPE_LENGTH (type);
-
- /* FIXME, we assume that pointers have the same form and byte order as
- integers, and that all pointers have the same form. */
- if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM ||
- code == TYPE_CODE_CHAR || code == TYPE_CODE_PTR ||
- code == TYPE_CODE_REF)
+ register value_ptr val = allocate_value (type);
+ register enum type_code code;
+ register int len;
+ retry:
+ code = TYPE_CODE (type);
+ len = TYPE_LENGTH (type);
+
+ switch (code)
{
- if (len == sizeof (char))
- * (char *) VALUE_CONTENTS_RAW (val) = num;
- else if (len == sizeof (short))
- * (short *) VALUE_CONTENTS_RAW (val) = num;
- else if (len == sizeof (int))
- * (int *) VALUE_CONTENTS_RAW (val) = num;
- else if (len == sizeof (long))
- * (long *) VALUE_CONTENTS_RAW (val) = num;
-#ifdef LONG_LONG
- else if (len == sizeof (long long))
- * (long long *) VALUE_CONTENTS_RAW (val) = num;
-#endif
- else
- error ("Integer type encountered with unexpected data length.");
+ 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);
+ break;
+
+ default:
+ error ("Unexpected type encountered for integer constant.");
}
- else
- error ("Unexpected type encountered for integer constant.");
-
- /* num was in host byte order. So now put the value's contents
- into target byte order. */
- SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len);
-
return val;
}
-value
+value_ptr
value_from_double (type, num)
struct type *type;
double num;
{
- register value val = allocate_value (type);
- register enum type_code code = TYPE_CODE (type);
- register int len = TYPE_LENGTH (type);
+ register value_ptr val = allocate_value (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)
{
- if (len == sizeof (float))
- * (float *) VALUE_CONTENTS_RAW (val) = num;
- else if (len == sizeof (double))
- * (double *) VALUE_CONTENTS_RAW (val) = num;
- else
- error ("Floating type encountered with unexpected data length.");
+ store_floating (VALUE_CONTENTS_RAW (val), len, num);
}
else
error ("Unexpected type encountered for floating constant.");
- /* num was in host byte order. So now put the value's contents
- into target byte order. */
- SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len);
-
return val;
}
\f
0 when it is using the value returning conventions (this often
means returning pointer to where structure is vs. returning value). */
-value
+value_ptr
value_being_returned (valtype, retbuf, struct_return)
register struct type *valtype;
char retbuf[REGISTER_BYTES];
int struct_return;
/*ARGSUSED*/
{
- register value val;
+ register value_ptr val;
CORE_ADDR addr;
#if defined (EXTRACT_STRUCT_VALUE_ADDRESS)
#endif
val = allocate_value (valtype);
+ CHECK_TYPEDEF (valtype);
EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val));
return val;
On most machines, the struct convention is used unless we are
using gcc and the type is of a special size. */
+/* As of about 31 Mar 93, GCC was changed to be compatible with the
+ native compiler. GCC 2.3.3 was the last release that did it the
+ old way. Since gcc2_compiled was not changed, we have no
+ way to correctly win in all cases, so we just do the right thing
+ for gcc1 and for gcc2 after this change. Thus it loses for gcc
+ 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) && (TYPE_LENGTH (value_type) == 1 \
- || TYPE_LENGTH (value_type) == 2 \
- || TYPE_LENGTH (value_type) == 4 \
- || TYPE_LENGTH (value_type) == 8 \
- ) \
+ (!((gcc_p == 1) && (TYPE_LENGTH (value_type) == 1 \
+ || TYPE_LENGTH (value_type) == 2 \
+ || TYPE_LENGTH (value_type) == 4 \
+ || TYPE_LENGTH (value_type) == 8 \
+ ) \
))
#endif
int
using_struct_return (function, funcaddr, value_type, gcc_p)
- value function;
+ value_ptr function;
CORE_ADDR funcaddr;
struct type *value_type;
int gcc_p;
void
set_return_value (val)
- value val;
+ 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.");
|| 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