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 "gdbcmd.h"
extern char *cplus_demangle ();
-extern char *cplus_mangle_opname ();
/* The value-history records all the values printed
by print commands during this session. Each chunk
static struct value_history_chunk *value_history_chain;
static int value_history_count; /* Abs number of last entry stored */
-
\f
/* List of all value objects currently allocated
(except for those released by calls to release_value)
#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\
error ("Invalid floating value found in program.");
return foo;
}
+/* Extract a value as a C pointer.
+ Does not deallocate the value. */
+CORE_ADDR
+value_as_pointer (val)
+ value val;
+{
+ /* 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);
+}
\f
/* Unpack raw data (copied from debugee, target byte order) at VALADDR
as a long, or as a double, assuming the raw data is described
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)
{
error ("That operation is not possible on an integer of that size.");
}
}
+ /* 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 (char *))
+ if (len == sizeof (CORE_ADDR))
{
CORE_ADDR retval;
bcopy (valaddr, &retval, sizeof (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 */
else
{
error ("Unexpected type of floating point number.");
+ return 0; /* Placate lint. */
}
}
else if (nosign) {
return unpack_long (type, valaddr);
}
}
+
+/* Unpack raw data (copied from debugee, target byte order) at VALADDR
+ as a CORE_ADDR, assuming the raw data is described by type TYPE.
+ We don't assume any alignment for the raw data. Return value is in
+ host byte order.
+
+ If you want functions and arrays to be coerced to pointers, and
+ references to be dereferenced, call value_as_pointer() instead.
+
+ C++: It is assumed that the front-end has taken care of
+ all matters concerning pointers to members. A pointer
+ to member which reaches here is considered to be equivalent
+ to an INT (or some size). After all, it is only an offset. */
+
+CORE_ADDR
+unpack_pointer (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)
of a struct or union type ARG_TYPE,
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));
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;
/* 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;
int i, nelems;
int offset, best_offset = 0;
struct symbol *sym;
CORE_ADDR pc_for_sym;
char *demangled_name;
-
- vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (dtype)));
+ btype = TYPE_VPTR_BASETYPE (dtype);
+ check_stub_type (btype);
+ 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)));
/* 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))
+ if (i < 0 || ! VTBL_PREFIX_P (demangled_name = misc_function_vector[i].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.
/* Now search through the virtual function table. */
entry = value_ind (vtbl);
- entry_type = VALUE_TYPE (entry);
- nelems = value_as_long (value_field (entry, 2));
+ 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));
- offset = value_as_long (value_field (entry, 0));
- if (offset < best_offset)
+ entry = value_subscript (vtbl, value_from_longest (builtin_type_int,
+ (LONGEST) i));
+ offset = longest_to_int (value_as_long (value_field (entry, 0)));
+ /* If we use '<=' we can handle single inheritance
+ * where all offsets are zero - just use the first entry found. */
+ if (offset <= best_offset)
{
best_offset = offset;
best_entry = entry;
}
}
- 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_long (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), -1);
+ *(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 (best_entry)
+ {
+ free (demangled_name);
+ arg = value_add (value_cast (builtin_type_int, arg),
+ value_field (best_entry, 0));
+ }
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg;
}
if (fieldno < 0)
{
- register struct type *t = type;
/* Look for static field. */
int i;
for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
if (errp)
*errp = 0;
-
+
if (BASETYPE_VIA_VIRTUAL (type, index))
{
/* Must hunt for the pointer to this virtual baseclass. */
CORE_ADDR addr;
int status;
- addr = unpack_long (TYPE_FIELD_TYPE (type, i),
+ 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 (type));
+ TYPE_LENGTH (basetype));
VALUE_LVAL (val) = lval_memory;
VALUE_ADDRESS (val) = addr;
{
char *baddr;
- baddr = baseclass_addr (type, i, valaddr, valuep);
+ baddr = baseclass_addr (type, i, valaddr, valuep, errp);
if (baddr)
return baddr;
}
struct type *type;
int i, j;
{
- extern char *gdb_mangle_typename (), *strchr ();
+ extern char *gdb_mangle_name (), *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 *mangled_name = gdb_mangle_name (type, i, j);
+ char *demangled_name = cplus_demangle (mangled_name, 0);
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);
- 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;
argtypes[argcount] = NULL; /* List terminator */
free (demangled_name);
-
+
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));
val = val >> (bitpos % 8);
#endif
- val &= (1 << bitsize) - 1;
+ if (bitsize < 8 * sizeof (val))
+ val &= (((unsigned long)1) << bitsize) - 1;
return val;
}
{
long oword;
- /* Reject values too big to fit in the field in question.
- Otherwise adjoining fields may be corrupted. */
- if (fieldval & ~((1<<bitsize)-1))
+ /* 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)))
error ("Value %d does not fit in %d bits.", fieldval, bitsize);
bcopy (addr, &oword, sizeof oword);
bitpos = sizeof (oword) * 8 - bitpos - bitsize;
#endif
- oword &= ~(((1 << bitsize) - 1) << bitpos);
+ /* Mask out old value, while avoiding shifts >= longword size */
+ if (bitsize < 8 * sizeof (oword))
+ oword &= ~(((((unsigned long)1) << bitsize) - 1) << bitpos);
+ else
+ oword &= ~((-1) << bitpos);
oword |= fieldval << bitpos;
SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To target format */
/* 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)
+ /* 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)
{
if (len == sizeof (char))
* (char *) VALUE_CONTENTS_RAW (val) = num;