#include "frame.h"
#include "command.h"
#include "gdbcmd.h"
+#include "target.h"
+#include "demangle.h"
/* Local function prototypes. */
show_values PARAMS ((char *, int));
static void
-show_convenience PARAMS ((void));
+show_convenience PARAMS ((char *, int));
/* The value-history records all the values printed
by print commands during this session. Each chunk
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;
}
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);
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));
modify_field (addr, (int) 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
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);
}
}
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_filtered ("$%s = ", var->name);
{
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
- return value_as_long (val);
+ return ADDR_BITS_REMOVE(value_as_long (val));
}
\f
/* Unpack raw data (copied from debugee, target byte order) at VALADDR
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;
}
if (len == sizeof (short))
{
unsigned short retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (int))
{
unsigned int retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (long))
{
unsigned long retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
-#ifdef LONG_LONG
+#ifdef CC_HAS_LONG_LONG
if (len == sizeof (long long))
{
unsigned long long retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
{
if (len == sizeof (char))
{
- char retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ SIGNED char retval; /* plain chars might be unsigned on host */
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (short))
{
short retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (int))
{
int retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (long))
{
long retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
-#ifdef LONG_LONG
+#ifdef CC_HAS_LONG_LONG
if (len == sizeof (long long))
{
long long retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
}
/* 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(long))
{
- long retval;
- bcopy (valaddr, &retval, sizeof(retval));
+ unsigned long retval;
+ memcpy (&retval, valaddr, sizeof(retval));
SWAP_TARGET_AND_HOST (&retval, sizeof(retval));
return retval;
}
else if (len == sizeof(short))
{
- short retval;
- bcopy (valaddr, &retval, len);
+ unsigned short retval;
+ memcpy (&retval, valaddr, len);
+ SWAP_TARGET_AND_HOST (&retval, len);
+ return retval;
+ }
+#ifdef CC_HAS_LONG_LONG
+ else if (len == sizeof(long long))
+ {
+ unsigned long long retval;
+ memcpy (&retval, valaddr, len);
SWAP_TARGET_AND_HOST (&retval, len);
return retval;
}
+#endif
}
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);
if (len == sizeof (CORE_ADDR))
{
CORE_ADDR retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
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)
J is an index into F which provides the desired method. */
value
-value_fn_field (f, j)
+value_fn_field (arg1p, f, j, type, offset)
+ value *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 struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
struct symbol *sym;
sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
if (! sym) 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_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 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;
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. */
msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
if (msymbol == NULL
- || !VTBL_PREFIX_P (demangled_name = msymbol -> name))
+ || !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. */
{
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);
+ 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;
}
return value_headof (arg, 0, type);
}
+/* 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;
+{
+ struct type *basetype = TYPE_BASECLASS (type, index);
+
+ 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%c%s", CPLUS_MARKER, type_name);
+ /* First look for the virtual baseclass pointer
+ in the fields. */
+ for (i = n_baseclasses; i < len; i++)
+ {
+ if (STREQ (vbase_name, TYPE_FIELD_NAME (type, i)))
+ {
+ 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;
+
+ 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++)
+ {
+ int boffset =
+ baseclass_offset (type, i, arg, offset);
+ if (boffset)
+ return boffset;
+ }
+ /* Not found. */
+ return -1;
+ }
+
+ /* 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.
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;
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);
+ sprintf (vbase_name, "_vb%c%s", CPLUS_MARKER, 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 (STREQ (vbase_name, TYPE_FIELD_NAME (type, i)))
{
value val = allocate_value (basetype);
CORE_ADDR addr;
return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8;
}
\f
-long
+/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
+ VALADDR.
+
+ Extracting bits depends on endianness of the machine. Compute the
+ number of least significant bits to discard. For big endian machines,
+ we compute the total number of bits in the anonymous object, subtract
+ off the bit count from the MSB of the object to the MSB of the
+ bitfield, then the size of the bitfield, which leaves the LSB discard
+ count. For little endian machines, the discard count is simply the
+ number of bits from the LSB of the anonymous object to the LSB of the
+ bitfield.
+
+ If the field is signed, we also do sign extension. */
+
+LONGEST
unpack_field_as_long (type, valaddr, fieldno)
struct type *type;
char *valaddr;
int fieldno;
{
- unsigned long val;
+ unsigned LONGEST val;
+ unsigned LONGEST valmask;
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ int lsbcount;
+
+ memcpy (&val, valaddr + bitpos / 8, sizeof (val));
+ SWAP_TARGET_AND_HOST (&val, 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;
- if (bitsize < 8 * sizeof (val))
- val &= (((unsigned long)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
&& 0 != (fieldval & ~((1<<bitsize)-1)))
error ("Value %d does not fit in %d bits.", fieldval, bitsize);
- bcopy (addr, &oword, sizeof oword);
+ memcpy (&oword, addr, sizeof oword);
SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To host format */
/* Shifting for bit field depends on endianness of the target machine. */
oword |= fieldval << bitpos;
SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To target format */
- bcopy (&oword, addr, sizeof oword);
+ memcpy (addr, &oword, sizeof oword);
}
\f
/* Convert C numbers into newly allocated values */
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)
+ code == TYPE_CODE_REF || code == TYPE_CODE_BOOL)
{
if (len == sizeof (char))
* (char *) VALUE_CONTENTS_RAW (val) = num;
* (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 if (len == sizeof (LONGEST))
+ * (LONGEST *) VALUE_CONTENTS_RAW (val) = num;
else
error ("Integer type encountered with unexpected data length.");
}
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