-/* Low level packing and unpacking of values for GDB.
- Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+/* Low level packing and unpacking of values for GDB, the GNU Debugger.
+ Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GDB.
-GDB is free software; you can redistribute it and/or modify
+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 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-GDB is distributed in the hope that it will be useful,
+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 GDB; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#include <stdio.h>
-#include <string.h>
#include "defs.h"
-#include "param.h"
+#include <string.h>
#include "symtab.h"
+#include "gdbtypes.h"
#include "value.h"
#include "gdbcore.h"
#include "frame.h"
#include "command.h"
#include "gdbcmd.h"
+#include "target.h"
+#include "demangle.h"
+
+/* Local function prototypes. */
+
+static value
+value_headof PARAMS ((value, struct type *, struct type *));
+
+static void
+show_values PARAMS ((char *, int));
-extern char *cplus_demangle ();
-extern char *cplus_mangle_opname ();
+static void
+show_convenience PARAMS ((char *, int));
/* The value-history records all the values printed
by print commands during this session. Each chunk
It contains the same contents, for same memory address,
but it's a different block of storage. */
-static value
+value
value_copy (arg)
value arg;
{
VALUE_LAZY (val) = VALUE_LAZY (arg);
if (!VALUE_LAZY (val))
{
- bcopy (VALUE_CONTENTS_RAW (arg), VALUE_CONTENTS_RAW (val),
- TYPE_LENGTH (VALUE_TYPE (arg))
- * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
+ memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS_RAW (arg),
+ TYPE_LENGTH (VALUE_TYPE (arg))
+ * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
}
return val;
}
/* 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 */
+ }
/* 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));
- bzero (new->values, 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;
+
+ /* 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);
+ VALUE_LVAL (val) = not_lval;
release_value (val);
/* Now we regard value_history_count as origin-one
while (value_history_chain)
{
for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
- if (val = value_history_chain->values[i])
- free (val);
+ if ((val = value_history_chain->values[i]) != NULL)
+ free ((PTR)val);
next = value_history_chain->next;
- free (value_history_chain);
+ free ((PTR)value_history_chain);
value_history_chain = next;
}
value_history_count = 0;
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
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));
- var->name = concat (name, "", "");
+ var->name = concat (name, NULL);
var->value = allocate_value (builtin_type_void);
release_value (var->value);
var->next = internalvars;
#endif
if (bitsize)
- modify_field (addr, (int) value_as_long (newval),
+ modify_field (addr, value_as_long (newval),
bitpos, bitsize);
else
- bcopy (VALUE_CONTENTS (newval), addr,
- TYPE_LENGTH (VALUE_TYPE (newval)));
+ memcpy (addr, VALUE_CONTENTS (newval), TYPE_LENGTH (VALUE_TYPE (newval)));
}
void
SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0);
#endif
- free (var->value);
+ free ((PTR)var->value);
var->value = value_copy (val);
+ /* 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);
}
{
var = internalvars;
internalvars = var->next;
- free (var->name);
- free (var->value);
- free (var);
+ free ((PTR)var->name);
+ free ((PTR)var->value);
+ free ((PTR)var);
}
}
static void
-show_convenience ()
+show_convenience (ignore, from_tty)
+ char *ignore;
+ int from_tty;
{
register struct internalvar *var;
int varseen = 0;
#endif
if (!varseen)
{
-#if 0
- /* Useless noise. */
- printf ("Debugger convenience variables:\n\n");
-#endif
varseen = 1;
}
- printf ("$%s = ", var->name);
+ printf_filtered ("$%s = ", var->name);
value_print (var->value, stdout, 0, Val_pretty_default);
- printf ("\n");
+ printf_filtered ("\n");
}
if (!varseen)
printf ("No debugger convenience variables now defined.\n\
{
/* 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)
+ if (code == TYPE_CODE_ENUM || code == TYPE_CODE_BOOL)
code = TYPE_CODE_INT;
if (code == TYPE_CODE_FLT)
{
if (len == sizeof (float))
{
float retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (double))
{
double retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
error ("Unexpected type of floating point number.");
}
}
- else if (code == TYPE_CODE_INT && nosign)
+ else if ((code == TYPE_CODE_INT || code == TYPE_CODE_CHAR) && nosign)
{
- 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;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (int))
- {
- unsigned int retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (long))
- {
- unsigned long retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- {
- unsigned long long retval;
- bcopy (valaddr, &retval, 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.");
- }
+ return extract_unsigned_integer (valaddr, len);
}
- else if (code == TYPE_CODE_INT)
+ else if (code == TYPE_CODE_INT || code == TYPE_CODE_CHAR)
{
- if (len == sizeof (char))
- {
- char retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (short))
- {
- short retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (int))
- {
- int retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (long))
- {
- long retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- {
- long long retval;
- bcopy (valaddr, &retval, 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.");
- }
+ return extract_signed_integer (valaddr, len);
}
/* 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)
+ else if (code == TYPE_CODE_PTR || code == TYPE_CODE_REF)
{
- if (len == sizeof (CORE_ADDR))
- {
- CORE_ADDR retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
+ return extract_address (valaddr, len);
}
else if (code == TYPE_CODE_MEMBER)
error ("not implemented: member types in unpack_long");
if (len == sizeof (float))
{
float retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (double))
{
double retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
}
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
+ return (unsigned LONGEST) unpack_long (type, valaddr);
} else {
/* Signed -- we are OK with unpack_long. */
return unpack_long (type, 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;
- bcopy (valaddr, &retval, 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)
offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
{
- v = value_from_long (type,
+ v = value_from_longest (type,
unpack_field_as_long (arg_type,
VALUE_CONTENTS (arg1),
fieldno));
if (VALUE_LAZY (arg1))
VALUE_LAZY (v) = 1;
else
- bcopy (VALUE_CONTENTS_RAW (arg1) + offset,
- VALUE_CONTENTS_RAW (v),
- 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)
return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1));
}
+/* Return a non-virtual function as a value.
+ 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 (arg1, fieldno, subfieldno)
- register value arg1;
- register int fieldno;
- int subfieldno;
+value_fn_field (arg1p, f, j, type, offset)
+ value *arg1p;
+ struct fn_field *f;
+ int j;
+ struct type *type;
+ int offset;
{
register value v;
- struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno);
- register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno);
+ register struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
struct symbol *sym;
- sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno),
+ 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",
- TYPE_FN_FIELD_PHYSNAME (f, subfieldno));
+ 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_virtual_fn_field (arg1p, f, j, type, offset)
+ value *arg1p;
struct fn_field *f;
int j;
struct type *type;
+ int offset;
{
+ value 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 entry, vfn, vtbl;
- value vi = value_from_long (builtin_type_int,
+ value 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;
/* 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
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));
+ VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0)) + offset;
if (! VALUE_LAZY (arg1))
{
VALUE_LAZY (arg1) = 1;
/* 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;
+value_headof (in_arg, btype, dtype)
+ value 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;
- /* FIXME: entry_type is never used. */
- struct type *entry_type;
+ value arg, vtbl, entry, best_entry = 0;
int i, nelems;
int offset, best_offset = 0;
struct symbol *sym;
CORE_ADDR pc_for_sym;
char *demangled_name;
+ struct minimal_symbol *msymbol;
btype = TYPE_VPTR_BASETYPE (dtype);
check_stub_type (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. */
- i = find_pc_misc_function (VALUE_ADDRESS (vtbl));
- if (i < 0 || ! VTBL_PREFIX_P (misc_function_vector[i].name))
+ msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (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));
- bcopy (VALUE_TYPE (arg), error_type, 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_ind (vtbl);
- entry_type = VALUE_TYPE (entry);
nelems = longest_to_int (value_as_long (value_field (entry, 2)));
for (i = 1; i <= nelems; i++)
{
- entry = value_subscript (vtbl, value_from_long (builtin_type_int, 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 (offset < best_offset)
+ /* 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;
}
}
- if (best_entry == 0)
- return arg;
-
/* Move the pointer according to BEST_ENTRY's offset, and figure
out what type we should return as the new pointer. */
- 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), -1);
- *(strchr (demangled_name, ':')) = '\0';
+ 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 == 0)
- error ("could not find type declaration for `%s'", SYMBOL_NAME (sym));
- free (demangled_name);
- arg = value_add (value_cast (builtin_type_int, arg),
- value_field (best_entry, 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;
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg;
}
return value_headof (arg, 0, type);
}
-/* The value of a static class member does not depend
- on its instance, only on its type. If FIELDNO >= 0,
- then fieldno is a valid field number and is used directly.
- Otherwise, FIELDNAME is the name of the field we are
- searching for. If it is not a static field name, an
- error is signaled. TYPE is the type in which we look for the
- static field member.
+/* Return true if the INDEXth field of TYPE is a virtual baseclass
+ pointer which is for the base class whose type is BASECLASS. */
- Return zero if we couldn't find anything; the caller may signal
- an error in that case. */
+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;
-value
-value_static_field (type, fieldname, fieldno)
- register struct type *type;
- char *fieldname;
- register int fieldno;
+ 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 a value ARG,
+ wih extra offset of OFFSET.
+ The result is the offste 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 arg;
+ int offset;
{
- register value v;
- struct symbol *sym;
- char *phys_name;
+ struct type *basetype = TYPE_BASECLASS (type, index);
- if (fieldno < 0)
+ if (BASETYPE_VIA_VIRTUAL (type, index))
{
- /* Look for static field. */
- int i;
- for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
- if (! strcmp (TYPE_FIELD_NAME (type, i), fieldname))
- {
- if (TYPE_FIELD_STATIC (type, i))
- {
- fieldno = i;
- goto found;
- }
- else
- error ("field `%s' is not static", fieldname);
- }
- for (; i > 0; i--)
+ /* 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++)
{
- v = value_static_field (TYPE_BASECLASS (type, i), fieldname, -1);
- if (v != 0)
- return v;
- }
+ 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 (destructor_name_p (fieldname, type))
- error ("Cannot get value of destructor");
+ if (VALUE_LVAL (arg) != lval_memory)
+ return -1;
- for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
+ return addr -
+ (LONGEST) (VALUE_ADDRESS (arg) + VALUE_OFFSET (arg) + offset);
+ }
+ }
+ /* Not in the fields, so try looking through the baseclasses. */
+ for (i = index+1; i < n_baseclasses; i++)
{
- if (! strcmp (TYPE_FN_FIELDLIST_NAME (type, i), fieldname))
- error ("Cannot get value of method \"%s\"", fieldname);
+ int boffset =
+ baseclass_offset (type, i, arg, offset);
+ if (boffset)
+ return boffset;
}
- error("there is no field named %s", fieldname);
+ /* Not found. */
+ return -1;
}
- found:
- phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
- sym = lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
- if (! sym) error ("Internal error: could not find physical static variable named %s", phys_name);
-
- type = TYPE_FIELD_TYPE (type, fieldno);
- v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
- return v;
+ /* Baseclass is easily computed. */
+ return TYPE_BASECLASS_BITPOS (type, index) / 8;
}
/* Compute the address of the baseclass which is
- the INDEXth baseclass of TYPE. The TYPE base
+ 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,
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;
/* 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);
- if (TYPE_MAIN_VARIANT (basetype))
- basetype = TYPE_MAIN_VARIANT (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;
status = target_read_memory (addr,
VALUE_CONTENTS_RAW (val),
- TYPE_LENGTH (type));
+ TYPE_LENGTH (basetype));
VALUE_LVAL (val) = lval_memory;
VALUE_ADDRESS (val) = addr;
*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.
-/* Ugly hack to convert method stubs into method types.
-
- He ain't kiddin'. This demangles the name of the method into a string
- including argument types, parses out each argument type, generates
- a string casting a zero to that type, evaluates the string, and stuffs
- the resulting type into an argtype vector!!! Then it knows the type
- of the whole function (including argument types for overloading),
- which info used to be in the stab's but was removed to hack back
- the space required for them. */
-void
-check_stub_method (type, i, j)
- struct type *type;
- int i, j;
-{
- extern char *gdb_mangle_typename (), *strchr ();
- struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
- char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
- char *inner_name = gdb_mangle_typename (type);
- int mangled_name_len = (strlen (field_name)
- + strlen (inner_name)
- + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
- + 1);
- char *mangled_name;
- char *demangled_name;
- char *argtypetext, *p;
- int depth = 0, argcount = 1;
- struct type **argtypes;
-
- if (OPNAME_PREFIX_P (field_name))
- {
- char *opname = cplus_mangle_opname (field_name + 3);
- if (opname == NULL)
- error ("No mangling for \"%s\"", field_name);
- mangled_name_len += strlen (opname);
- mangled_name = (char *)xmalloc (mangled_name_len);
-
- strncpy (mangled_name, field_name, 3);
- mangled_name[3] = '\0';
- strcat (mangled_name, opname);
- }
- else
- {
- mangled_name = (char *)xmalloc (mangled_name_len);
- strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
- }
- strcat (mangled_name, inner_name);
- strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j));
- demangled_name = cplus_demangle (mangled_name, 0);
-
- /* Now, read in the parameters that define this type. */
- argtypetext = strchr (demangled_name, '(') + 1;
- p = argtypetext;
- while (*p)
- {
- if (*p == '(')
- depth += 1;
- else if (*p == ')')
- depth -= 1;
- else if (*p == ',' && depth == 0)
- argcount += 1;
-
- p += 1;
- }
- /* We need one more slot for the void [...] or NULL [end of arglist] */
- argtypes = (struct type **)xmalloc ((argcount+1) * sizeof (struct type *));
- p = argtypetext;
- argtypes[0] = lookup_pointer_type (type);
- argcount = 1;
-
- if (*p != ')') /* () means no args, skip while */
- {
- while (*p)
- {
- if (*p == '(')
- depth += 1;
- else if (*p == ')')
- depth -= 1;
-
- if (depth <= 0 && (*p == ',' || *p == ')'))
- {
- char *tmp = (char *)alloca (p - argtypetext + 4);
- value val;
- tmp[0] = '(';
- bcopy (argtypetext, tmp+1, p - argtypetext);
- tmp[p-argtypetext+1] = ')';
- tmp[p-argtypetext+2] = '0';
- tmp[p-argtypetext+3] = '\0';
- val = parse_and_eval (tmp);
- argtypes[argcount] = VALUE_TYPE (val);
- argcount += 1;
- argtypetext = p + 1;
- }
- p += 1;
- }
- }
-
- if (p[-2] != '.') /* ... */
- argtypes[argcount] = builtin_type_void; /* Ellist terminator */
- else
- argtypes[argcount] = NULL; /* List terminator */
+ Extracting bits depends on endianness of the machine. Compute the
+ number of least significant bits to discard. For big endian machines,
+ we compute the total number of bits in the anonymous object, subtract
+ off the bit count from the MSB of the object to the MSB of the
+ bitfield, then the size of the bitfield, which leaves the LSB discard
+ count. For little endian machines, the discard count is simply the
+ number of bits from the LSB of the anonymous object to the LSB of the
+ bitfield.
- free (demangled_name);
+ If the field is signed, we also do sign extension. */
- type = lookup_method_type (type, TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), argtypes);
- /* Free the stub type...it's no longer needed. */
- free (TYPE_FN_FIELD_TYPE (f, j));
- TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
- TYPE_FN_FIELD_TYPE (f, j) = type;
-}
-\f
-long
+LONGEST
unpack_field_as_long (type, valaddr, fieldno)
struct type *type;
char *valaddr;
int fieldno;
{
- long val;
+ unsigned LONGEST val;
+ unsigned LONGEST valmask;
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ int lsbcount;
+
+ val = extract_unsigned_integer (valaddr + bitpos / 8, sizeof (val));
- bcopy (valaddr + bitpos / 8, &val, sizeof val);
- SWAP_TARGET_AND_HOST (&val, sizeof val);
+ /* Extract bits. See comment above. */
- /* Extracting bits depends on endianness of the machine. */
#if BITS_BIG_ENDIAN
- val = val >> (sizeof val * 8 - bitpos % 8 - bitsize);
+ lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);
#else
- val = val >> (bitpos % 8);
+ lsbcount = (bitpos % 8);
#endif
+ val >>= lsbcount;
- val &= (1 << bitsize) - 1;
- return val;
+ /* 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)))
+ {
+ valmask = (((unsigned LONGEST) 1) << bitsize) - 1;
+ val &= valmask;
+ if (!TYPE_UNSIGNED (TYPE_FIELD_TYPE (type, fieldno)))
+ {
+ if (val & (valmask ^ (valmask >> 1)))
+ {
+ val |= ~valmask;
+ }
+ }
+ }
+ return (val);
}
/* Modify the value of a bitfield. ADDR points to a block of memory in
void
modify_field (addr, fieldval, bitpos, bitsize)
char *addr;
- int fieldval;
+ LONGEST fieldval;
int bitpos, bitsize;
{
- long oword;
+ LONGEST oword;
- /* Reject values too big to fit in the field in question.
- Otherwise adjoining fields may be corrupted. */
- if (fieldval & ~((1<<bitsize)-1))
- error ("Value %d does not fit in %d bits.", fieldval, bitsize);
-
- bcopy (addr, &oword, sizeof oword);
- SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To host format */
+ /* 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)))
+ {
+ /* 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);
+ }
+
+ 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
- oword &= ~(((1 << bitsize) - 1) << bitpos);
+ /* Mask out old value, while avoiding shifts >= size of oword */
+ if (bitsize < 8 * sizeof (oword))
+ oword &= ~(((((unsigned LONGEST)1) << bitsize) - 1) << bitpos);
+ else
+ oword &= ~((~(unsigned LONGEST)0) << bitpos);
oword |= fieldval << bitpos;
- SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To target format */
- bcopy (&oword, addr, sizeof oword);
+ store_signed_integer (addr, sizeof oword, oword);
}
\f
/* Convert C numbers into newly allocated values */
value
-value_from_long (type, num)
+value_from_longest (type, num)
struct type *type;
register LONGEST num;
{
register enum type_code code = TYPE_CODE (type);
register int len = TYPE_LENGTH (type);
- if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM)
+ 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_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ 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;
}
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
if (code == TYPE_CODE_ERROR)
error ("Function return type unknown.");
- if (code == TYPE_CODE_STRUCT
- || code == TYPE_CODE_UNION)
- error ("Specifying a struct or union return value is not supported.");
+ 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.... */