/* Low level packing and unpacking of values for GDB, the GNU Debugger.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
- 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005 Free
- Software Foundation, Inc.
+ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+ 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+ 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "gdb_string.h"
void _initialize_values (void);
+struct value
+{
+ /* Type of value; either not an lval, or one of the various
+ different possible kinds of lval. */
+ enum lval_type lval;
+
+ /* Is it modifiable? Only relevant if lval != not_lval. */
+ int modifiable;
+
+ /* Location of value (if lval). */
+ union
+ {
+ /* If lval == lval_memory, this is the address in the inferior.
+ If lval == lval_register, this is the byte offset into the
+ registers structure. */
+ CORE_ADDR address;
+
+ /* Pointer to internal variable. */
+ struct internalvar *internalvar;
+ } location;
+
+ /* Describes offset of a value within lval of a structure in bytes.
+ If lval == lval_memory, this is an offset to the address. If
+ lval == lval_register, this is a further offset from
+ location.address within the registers structure. Note also the
+ member embedded_offset below. */
+ int offset;
+
+ /* Only used for bitfields; number of bits contained in them. */
+ int bitsize;
+
+ /* Only used for bitfields; position of start of field. For
+ BITS_BIG_ENDIAN=0 targets, it is the position of the LSB. For
+ BITS_BIG_ENDIAN=1 targets, it is the position of the MSB. */
+ int bitpos;
+
+ /* Frame register value is relative to. This will be described in
+ the lval enum above as "lval_register". */
+ struct frame_id frame_id;
+
+ /* Type of the value. */
+ struct type *type;
+
+ /* If a value represents a C++ object, then the `type' field gives
+ the object's compile-time type. If the object actually belongs
+ to some class derived from `type', perhaps with other base
+ classes and additional members, then `type' is just a subobject
+ of the real thing, and the full object is probably larger than
+ `type' would suggest.
+
+ If `type' is a dynamic class (i.e. one with a vtable), then GDB
+ can actually determine the object's run-time type by looking at
+ the run-time type information in the vtable. When this
+ information is available, we may elect to read in the entire
+ object, for several reasons:
+
+ - When printing the value, the user would probably rather see the
+ full object, not just the limited portion apparent from the
+ compile-time type.
+
+ - If `type' has virtual base classes, then even printing `type'
+ alone may require reaching outside the `type' portion of the
+ object to wherever the virtual base class has been stored.
+
+ When we store the entire object, `enclosing_type' is the run-time
+ type -- the complete object -- and `embedded_offset' is the
+ offset of `type' within that larger type, in bytes. The
+ value_contents() macro takes `embedded_offset' into account, so
+ most GDB code continues to see the `type' portion of the value,
+ just as the inferior would.
+
+ If `type' is a pointer to an object, then `enclosing_type' is a
+ pointer to the object's run-time type, and `pointed_to_offset' is
+ the offset in bytes from the full object to the pointed-to object
+ -- that is, the value `embedded_offset' would have if we followed
+ the pointer and fetched the complete object. (I don't really see
+ the point. Why not just determine the run-time type when you
+ indirect, and avoid the special case? The contents don't matter
+ until you indirect anyway.)
+
+ If we're not doing anything fancy, `enclosing_type' is equal to
+ `type', and `embedded_offset' is zero, so everything works
+ normally. */
+ struct type *enclosing_type;
+ int embedded_offset;
+ int pointed_to_offset;
+
+ /* Values are stored in a chain, so that they can be deleted easily
+ over calls to the inferior. Values assigned to internal
+ variables or put into the value history are taken off this
+ list. */
+ struct value *next;
+
+ /* Register number if the value is from a register. */
+ short regnum;
+
+ /* If zero, contents of this value are in the contents field. If
+ nonzero, contents are in inferior memory at address in the
+ location.address field plus the offset field (and the lval field
+ should be lval_memory).
+
+ WARNING: This field is used by the code which handles watchpoints
+ (see breakpoint.c) to decide whether a particular value can be
+ watched by hardware watchpoints. If the lazy flag is set for
+ some member of a value chain, it is assumed that this member of
+ the chain doesn't need to be watched as part of watching the
+ value itself. This is how GDB avoids watching the entire struct
+ or array when the user wants to watch a single struct member or
+ array element. If you ever change the way lazy flag is set and
+ reset, be sure to consider this use as well! */
+ char lazy;
+
+ /* If nonzero, this is the value of a variable which does not
+ actually exist in the program. */
+ char optimized_out;
+
+ /* Actual contents of the value. For use of this value; setting it
+ uses the stuff above. Not valid if lazy is nonzero. Target
+ byte-order. We force it to be aligned properly for any possible
+ value. Note that a value therefore extends beyond what is
+ declared here. */
+ union
+ {
+ gdb_byte contents[1];
+ DOUBLEST force_doublest_align;
+ LONGEST force_longest_align;
+ CORE_ADDR force_core_addr_align;
+ void *force_pointer_align;
+ } aligner;
+ /* Do not add any new members here -- contents above will trash
+ them. */
+};
+
/* Prototypes for local functions. */
static void show_values (char *, int);
val->lazy = 0;
val->optimized_out = 0;
val->embedded_offset = 0;
- VALUE_POINTED_TO_OFFSET (val) = 0;
+ val->pointed_to_offset = 0;
val->modifiable = 1;
return val;
}
/* Accessor methods. */
+struct value *
+value_next (struct value *value)
+{
+ return value->next;
+}
+
struct type *
value_type (struct value *value)
{
return value->type;
}
+void
+deprecated_set_value_type (struct value *value, struct type *type)
+{
+ value->type = type;
+}
int
value_offset (struct value *value)
{
return value->offset;
}
+void
+set_value_offset (struct value *value, int offset)
+{
+ value->offset = offset;
+}
int
value_bitpos (struct value *value)
{
return value->bitpos;
}
+void
+set_value_bitpos (struct value *value, int bit)
+{
+ value->bitpos = bit;
+}
int
value_bitsize (struct value *value)
{
return value->bitsize;
}
+void
+set_value_bitsize (struct value *value, int bit)
+{
+ value->bitsize = bit;
+}
-bfd_byte *
+gdb_byte *
value_contents_raw (struct value *value)
{
return value->aligner.contents + value->embedded_offset;
}
-bfd_byte *
+gdb_byte *
value_contents_all_raw (struct value *value)
{
return value->aligner.contents;
return value->enclosing_type;
}
-const bfd_byte *
+const gdb_byte *
value_contents_all (struct value *value)
{
if (value->lazy)
value->lazy = val;
}
-const bfd_byte *
+const gdb_byte *
value_contents (struct value *value)
{
return value_contents_writeable (value);
}
-bfd_byte *
+gdb_byte *
value_contents_writeable (struct value *value)
{
if (value->lazy)
value_fetch_lazy (value);
- return value->aligner.contents;
+ return value_contents_raw (value);
+}
+
+/* Return non-zero if VAL1 and VAL2 have the same contents. Note that
+ this function is different from value_equal; in C the operator ==
+ can return 0 even if the two values being compared are equal. */
+
+int
+value_contents_equal (struct value *val1, struct value *val2)
+{
+ struct type *type1;
+ struct type *type2;
+ int len;
+
+ type1 = check_typedef (value_type (val1));
+ type2 = check_typedef (value_type (val2));
+ len = TYPE_LENGTH (type1);
+ if (len != TYPE_LENGTH (type2))
+ return 0;
+
+ return (memcmp (value_contents (val1), value_contents (val2), len) == 0);
}
int
{
value->embedded_offset = val;
}
+
+int
+value_pointed_to_offset (struct value *value)
+{
+ return value->pointed_to_offset;
+}
+
+void
+set_value_pointed_to_offset (struct value *value, int val)
+{
+ value->pointed_to_offset = val;
+}
+
+enum lval_type *
+deprecated_value_lval_hack (struct value *value)
+{
+ return &value->lval;
+}
+
+CORE_ADDR *
+deprecated_value_address_hack (struct value *value)
+{
+ return &value->location.address;
+}
+
+struct internalvar **
+deprecated_value_internalvar_hack (struct value *value)
+{
+ return &value->location.internalvar;
+}
+
+struct frame_id *
+deprecated_value_frame_id_hack (struct value *value)
+{
+ return &value->frame_id;
+}
+
+short *
+deprecated_value_regnum_hack (struct value *value)
+{
+ return &value->regnum;
+}
+
+int
+deprecated_value_modifiable (struct value *value)
+{
+ return value->modifiable;
+}
+void
+deprecated_set_value_modifiable (struct value *value, int modifiable)
+{
+ value->modifiable = modifiable;
+}
\f
/* Return a mark in the value chain. All values allocated after the
mark is obtained (except for those released) are subject to being freed
val->lazy = arg->lazy;
val->optimized_out = arg->optimized_out;
val->embedded_offset = value_embedded_offset (arg);
- VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (arg);
+ val->pointed_to_offset = arg->pointed_to_offset;
val->modifiable = arg->modifiable;
if (!value_lazy (val))
{
if (absnum <= 0)
{
if (num == 0)
- error ("The history is empty.");
+ error (_("The history is empty."));
else if (num == 1)
- error ("There is only one value in the history.");
+ error (_("There is only one value in the history."));
else
- error ("History does not go back to $$%d.", -num);
+ error (_("History does not go back to $$%d."), -num);
}
if (absnum > value_history_count)
- error ("History has not yet reached $%d.", absnum);
+ error (_("History has not yet reached $%d."), absnum);
absnum--;
return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]);
}
-/* Clear the value history entirely.
- Must be done when new symbol tables are loaded,
- because the type pointers become invalid. */
-
-void
-clear_value_history (void)
-{
- struct value_history_chunk *next;
- int i;
- struct value *val;
-
- while (value_history_chain)
- {
- for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
- if ((val = value_history_chain->values[i]) != NULL)
- xfree (val);
- next = value_history_chain->next;
- xfree (value_history_chain);
- value_history_chain = next;
- }
- value_history_count = 0;
-}
-
static void
show_values (char *num_exp, int from_tty)
{
for (i = num; i < num + 10 && i <= value_history_count; i++)
{
val = access_value_history (i);
- printf_filtered ("$%d = ", i);
+ printf_filtered (("$%d = "), i);
value_print (val, gdb_stdout, 0, Val_pretty_default);
- printf_filtered ("\n");
+ printf_filtered (("\n"));
}
/* The next "info history +" should start after what we just printed. */
static struct internalvar *internalvars;
+/* If the variable does not already exist create it and give it the value given.
+ If no value is given then the default is zero. */
+static void
+init_if_undefined_command (char* args, int from_tty)
+{
+ struct internalvar* intvar;
+
+ /* Parse the expression - this is taken from set_command(). */
+ struct expression *expr = parse_expression (args);
+ register struct cleanup *old_chain =
+ make_cleanup (free_current_contents, &expr);
+
+ /* Validate the expression.
+ Was the expression an assignment?
+ Or even an expression at all? */
+ if (expr->nelts == 0 || expr->elts[0].opcode != BINOP_ASSIGN)
+ error (_("Init-if-undefined requires an assignment expression."));
+
+ /* Extract the variable from the parsed expression.
+ In the case of an assign the lvalue will be in elts[1] and elts[2]. */
+ if (expr->elts[1].opcode != OP_INTERNALVAR)
+ error (_("The first parameter to init-if-undefined should be a GDB variable."));
+ intvar = expr->elts[2].internalvar;
+
+ /* Only evaluate the expression if the lvalue is void.
+ This may still fail if the expresssion is invalid. */
+ if (TYPE_CODE (value_type (intvar->value)) == TYPE_CODE_VOID)
+ evaluate_expression (expr);
+
+ do_cleanups (old_chain);
+}
+
+
/* Look up an internal variable with name NAME. NAME should not
normally include a dollar sign.
return var;
var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
- var->name = concat (name, NULL);
+ var->name = concat (name, (char *)NULL);
var->value = allocate_value (builtin_type_void);
+ var->endian = TARGET_BYTE_ORDER;
release_value (var->value);
var->next = internalvars;
internalvars = var;
value_of_internalvar (struct internalvar *var)
{
struct value *val;
+ int i, j;
+ gdb_byte temp;
val = value_copy (var->value);
if (value_lazy (val))
value_fetch_lazy (val);
VALUE_LVAL (val) = lval_internalvar;
VALUE_INTERNALVAR (val) = var;
+
+ /* Values are always stored in the target's byte order. When connected to a
+ target this will most likely always be correct, so there's normally no
+ need to worry about it.
+
+ However, internal variables can be set up before the target endian is
+ known and so may become out of date. Fix it up before anybody sees.
+
+ Internal variables usually hold simple scalar values, and we can
+ correct those. More complex values (e.g. structures and floating
+ point types) are left alone, because they would be too complicated
+ to correct. */
+
+ if (var->endian != TARGET_BYTE_ORDER)
+ {
+ gdb_byte *array = value_contents_raw (val);
+ struct type *type = check_typedef (value_enclosing_type (val));
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_PTR:
+ /* Reverse the bytes. */
+ for (i = 0, j = TYPE_LENGTH (type) - 1; i < j; i++, j--)
+ {
+ temp = array[j];
+ array[j] = array[i];
+ array[i] = temp;
+ }
+ break;
+ }
+ }
+
return val;
}
set_internalvar_component (struct internalvar *var, int offset, int bitpos,
int bitsize, struct value *newval)
{
- bfd_byte *addr = value_contents_writeable (var->value) + offset;
+ gdb_byte *addr = value_contents_writeable (var->value) + offset;
if (bitsize)
modify_field (addr, value_as_long (newval),
long. */
xfree (var->value);
var->value = newval;
+ var->endian = TARGET_BYTE_ORDER;
release_value (newval);
/* End code which must not call error(). */
}
return var->name;
}
-/* Free all internalvars. Done when new symtabs are loaded,
- because that makes the values invalid. */
+/* Update VALUE before discarding OBJFILE. COPIED_TYPES is used to
+ prevent cycles / duplicates. */
+
+static void
+preserve_one_value (struct value *value, struct objfile *objfile,
+ htab_t copied_types)
+{
+ if (TYPE_OBJFILE (value->type) == objfile)
+ value->type = copy_type_recursive (objfile, value->type, copied_types);
+
+ if (TYPE_OBJFILE (value->enclosing_type) == objfile)
+ value->enclosing_type = copy_type_recursive (objfile,
+ value->enclosing_type,
+ copied_types);
+}
+
+/* Update the internal variables and value history when OBJFILE is
+ discarded; we must copy the types out of the objfile. New global types
+ will be created for every convenience variable which currently points to
+ this objfile's types, and the convenience variables will be adjusted to
+ use the new global types. */
void
-clear_internalvars (void)
+preserve_values (struct objfile *objfile)
{
+ htab_t copied_types;
+ struct value_history_chunk *cur;
struct internalvar *var;
+ int i;
- while (internalvars)
- {
- var = internalvars;
- internalvars = var->next;
- xfree (var->name);
- xfree (var->value);
- xfree (var);
- }
+ /* Create the hash table. We allocate on the objfile's obstack, since
+ it is soon to be deleted. */
+ copied_types = create_copied_types_hash (objfile);
+
+ for (cur = value_history_chain; cur; cur = cur->next)
+ for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
+ if (cur->values[i])
+ preserve_one_value (cur->values[i], objfile, copied_types);
+
+ for (var = internalvars; var; var = var->next)
+ preserve_one_value (var->value, objfile, copied_types);
+
+ htab_delete (copied_types);
}
static void
{
varseen = 1;
}
- printf_filtered ("$%s = ", var->name);
- value_print (var->value, gdb_stdout, 0, Val_pretty_default);
- printf_filtered ("\n");
+ printf_filtered (("$%s = "), var->name);
+ value_print (value_of_internalvar (var), gdb_stdout,
+ 0, Val_pretty_default);
+ printf_filtered (("\n"));
}
if (!varseen)
- printf_unfiltered ("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");
+use \"set\" as in \"set $foo = 5\" to define them.\n"));
}
\f
/* Extract a value as a C number (either long or double).
foo = unpack_double (value_type (val), value_contents (val), &inv);
if (inv)
- error ("Invalid floating value found in program.");
+ error (_("Invalid floating value found in program."));
return foo;
}
/* Extract a value as a C pointer. Does not deallocate the value.
to an INT (or some size). After all, it is only an offset. */
LONGEST
-unpack_long (struct type *type, const char *valaddr)
+unpack_long (struct type *type, const gdb_byte *valaddr)
{
enum type_code code = TYPE_CODE (type);
int len = TYPE_LENGTH (type);
case TYPE_CODE_TYPEDEF:
return unpack_long (check_typedef (type), valaddr);
case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLAGS:
case TYPE_CODE_BOOL:
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
return extract_typed_address (valaddr, type);
case TYPE_CODE_MEMBER:
- error ("not implemented: member types in unpack_long");
+ error (_("not implemented: member types in unpack_long"));
default:
- error ("Value can't be converted to integer.");
+ error (_("Value can't be converted to integer."));
}
return 0; /* Placate lint. */
}
format, result is in host format. */
DOUBLEST
-unpack_double (struct type *type, const char *valaddr, int *invp)
+unpack_double (struct type *type, const gdb_byte *valaddr, int *invp)
{
enum type_code code;
int len;
to an INT (or some size). After all, it is only an offset. */
CORE_ADDR
-unpack_pointer (struct type *type, const char *valaddr)
+unpack_pointer (struct type *type, const gdb_byte *valaddr)
{
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
/* SYM should never have a SYMBOL_CLASS which will require
read_var_value to use the FRAME parameter. */
if (symbol_read_needs_frame (sym))
- warning ("static field's value depends on the current "
- "frame - bad debug info?");
+ warning (_("static field's value depends on the current "
+ "frame - bad debug info?"));
retval = read_var_value (sym, NULL);
}
if (retval && VALUE_LVAL (retval) == lval_memory)
If the field is signed, we also do sign extension. */
LONGEST
-unpack_field_as_long (struct type *type, const char *valaddr, int fieldno)
+unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
{
ULONGEST val;
ULONGEST valmask;
0 <= BITPOS, where lbits is the size of a LONGEST in bits. */
void
-modify_field (char *addr, LONGEST fieldval, int bitpos, int bitsize)
+modify_field (gdb_byte *addr, LONGEST fieldval, int bitpos, int bitsize)
{
ULONGEST oword;
ULONGEST mask = (ULONGEST) -1 >> (8 * sizeof (ULONGEST) - bitsize);
{
/* 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);
+ warning (_("Value does not fit in %d bits."), bitsize);
/* Truncate it, otherwise adjoining fields may be corrupted. */
fieldval &= mask;
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLAGS:
case TYPE_CODE_BOOL:
case TYPE_CODE_RANGE:
store_signed_integer (value_contents_raw (val), len, num);
break;
default:
- error ("Unexpected type (%d) encountered for integer constant.", code);
+ error (_("Unexpected type (%d) encountered for integer constant."), code);
}
return val;
}
store_typed_floating (value_contents_raw (val), base_type, num);
}
else
- error ("Unexpected type encountered for floating constant.");
+ error (_("Unexpected type encountered for floating constant."));
return val;
}
enum type_code code = TYPE_CODE (value_type);
if (code == TYPE_CODE_ERROR)
- error ("Function return type unknown.");
+ error (_("Function return type unknown."));
if (code == TYPE_CODE_VOID)
/* A void return value is never in memory. See also corresponding
void
_initialize_values (void)
{
- add_cmd ("convenience", no_class, show_convenience,
- "Debugger convenience (\"$foo\") variables.\n\
+ add_cmd ("convenience", no_class, show_convenience, _("\
+Debugger convenience (\"$foo\") variables.\n\
These variables are created when you assign them values;\n\
-thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\n\
+thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\
+\n\
A few convenience variables are given values automatically:\n\
\"$_\"holds the last address examined with \"x\" or \"info lines\",\n\
-\"$__\" holds the contents of the last address examined with \"x\".",
+\"$__\" holds the contents of the last address examined with \"x\"."),
&showlist);
add_cmd ("values", no_class, show_values,
- "Elements of value history around item number IDX (or last ten).",
+ _("Elements of value history around item number IDX (or last ten)."),
&showlist);
+
+ add_com ("init-if-undefined", class_vars, init_if_undefined_command, _("\
+Initialize a convenience variable if necessary.\n\
+init-if-undefined VARIABLE = EXPRESSION\n\
+Set an internal VARIABLE to the result of the EXPRESSION if it does not\n\
+exist or does not contain a value. The EXPRESSION is not evaluated if the\n\
+VARIABLE is already initialized."));
}