#include "defs.h"
#include "gdb_string.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "value.h"
#include "gdbcore.h"
#include "command.h"
#include "gdbcmd.h"
#include "target.h"
#include "language.h"
#include "scm-lang.h"
#include "demangle.h"
#include "doublest.h"
#include "gdb_assert.h"
#include "regcache.h"
#include "block.h"
void _initialize_values (void);
static void show_values (char *, int);
static void show_convenience (char *, int);
#define VALUE_HISTORY_CHUNK 60
struct value_history_chunk
{
struct value_history_chunk *next;
struct value *values[VALUE_HISTORY_CHUNK];
};
static struct value_history_chunk *value_history_chain;
static int value_history_count;
static struct value *all_values;
struct value *
allocate_value (struct type *type)
{
struct value *val;
struct type *atype = check_typedef (type);
val = (struct value *) xmalloc (sizeof (struct value) + TYPE_LENGTH (atype));
VALUE_NEXT (val) = all_values;
all_values = val;
VALUE_TYPE (val) = type;
VALUE_ENCLOSING_TYPE (val) = type;
VALUE_LVAL (val) = not_lval;
VALUE_ADDRESS (val) = 0;
VALUE_FRAME_ID (val) = null_frame_id;
VALUE_OFFSET (val) = 0;
VALUE_BITPOS (val) = 0;
VALUE_BITSIZE (val) = 0;
VALUE_REGNO (val) = -1;
VALUE_LAZY (val) = 0;
VALUE_OPTIMIZED_OUT (val) = 0;
VALUE_BFD_SECTION (val) = NULL;
VALUE_EMBEDDED_OFFSET (val) = 0;
VALUE_POINTED_TO_OFFSET (val) = 0;
val->modifiable = 1;
return val;
}
struct value *
allocate_repeat_value (struct type *type, int count)
{
int low_bound = current_language->string_lower_bound;
struct type *range_type
= create_range_type ((struct type *) NULL, builtin_type_int,
low_bound, count + low_bound - 1);
return allocate_value (create_array_type ((struct type *) NULL,
type, range_type));
}
struct value *
value_mark (void)
{
return all_values;
}
void
value_free_to_mark (struct value *mark)
{
struct value *val;
struct value *next;
for (val = all_values; val && val != mark; val = next)
{
next = VALUE_NEXT (val);
value_free (val);
}
all_values = val;
}
void
free_all_values (void)
{
struct value *val;
struct value *next;
for (val = all_values; val; val = next)
{
next = VALUE_NEXT (val);
value_free (val);
}
all_values = 0;
}
void
release_value (struct value *val)
{
struct value *v;
if (all_values == val)
{
all_values = val->next;
return;
}
for (v = all_values; v; v = v->next)
{
if (v->next == val)
{
v->next = val->next;
break;
}
}
}
struct value *
value_release_to_mark (struct value *mark)
{
struct value *val;
struct value *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;
}
struct value *
value_copy (struct value *arg)
{
struct type *encl_type = VALUE_ENCLOSING_TYPE (arg);
struct value *val = allocate_value (encl_type);
VALUE_TYPE (val) = VALUE_TYPE (arg);
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_ID (val) = VALUE_FRAME_ID (arg);
VALUE_REGNO (val) = VALUE_REGNO (arg);
VALUE_LAZY (val) = VALUE_LAZY (arg);
VALUE_OPTIMIZED_OUT (val) = VALUE_OPTIMIZED_OUT (arg);
VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (arg);
VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (arg);
VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (arg);
val->modifiable = arg->modifiable;
if (!VALUE_LAZY (val))
{
memcpy (VALUE_CONTENTS_ALL_RAW (val), VALUE_CONTENTS_ALL_RAW (arg),
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg)));
}
return val;
}
int
record_latest_value (struct value *val)
{
int i;
if (VALUE_LAZY (val))
value_fetch_lazy (val);
val->modifiable = 0;
release_value (val);
i = value_history_count % VALUE_HISTORY_CHUNK;
if (i == 0)
{
struct value_history_chunk *new
= (struct value_history_chunk *)
xmalloc (sizeof (struct value_history_chunk));
memset (new->values, 0, sizeof new->values);
new->next = value_history_chain;
value_history_chain = new;
}
value_history_chain->values[i] = val;
return ++value_history_count;
}
struct value *
access_value_history (int num)
{
struct value_history_chunk *chunk;
int i;
int absnum = num;
if (absnum <= 0)
absnum += value_history_count;
if (absnum <= 0)
{
if (num == 0)
error ("The history is empty.");
else if (num == 1)
error ("There is only one value in the history.");
else
error ("History does not go back to $$%d.", -num);
}
if (absnum > value_history_count)
error ("History has not yet reached $%d.", absnum);
absnum--;
chunk = value_history_chain;
for (i = (value_history_count - 1) / VALUE_HISTORY_CHUNK - absnum / VALUE_HISTORY_CHUNK;
i > 0; i--)
chunk = chunk->next;
return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]);
}
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)
{
int i;
struct value *val;
static int num = 1;
if (num_exp)
{
if (num_exp[0] != '+' || num_exp[1] != '\0')
num = parse_and_eval_long (num_exp) - 5;
}
else
{
num = value_history_count - 9;
}
if (num <= 0)
num = 1;
for (i = num; i < num + 10 && i <= value_history_count; i++)
{
val = access_value_history (i);
printf_filtered ("$%d = ", i);
value_print (val, gdb_stdout, 0, Val_pretty_default);
printf_filtered ("\n");
}
num += 10;
if (from_tty && num_exp)
{
num_exp[0] = '+';
num_exp[1] = '\0';
}
}
static struct internalvar *internalvars;
struct internalvar *
lookup_internalvar (char *name)
{
struct internalvar *var;
for (var = internalvars; var; var = var->next)
if (strcmp (var->name, name) == 0)
return var;
var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
var->name = concat (name, NULL);
var->value = allocate_value (builtin_type_void);
release_value (var->value);
var->next = internalvars;
internalvars = var;
return var;
}
struct value *
value_of_internalvar (struct internalvar *var)
{
struct value *val;
val = value_copy (var->value);
if (VALUE_LAZY (val))
value_fetch_lazy (val);
VALUE_LVAL (val) = lval_internalvar;
VALUE_INTERNALVAR (val) = var;
return val;
}
void
set_internalvar_component (struct internalvar *var, int offset, int bitpos,
int bitsize, struct value *newval)
{
char *addr = VALUE_CONTENTS (var->value) + offset;
if (bitsize)
modify_field (addr, value_as_long (newval),
bitpos, bitsize);
else
memcpy (addr, VALUE_CONTENTS (newval), TYPE_LENGTH (VALUE_TYPE (newval)));
}
void
set_internalvar (struct internalvar *var, struct value *val)
{
struct value *newval;
newval = value_copy (val);
newval->modifiable = 1;
if (VALUE_LAZY (newval))
value_fetch_lazy (newval);
xfree (var->value);
var->value = newval;
release_value (newval);
}
char *
internalvar_name (struct internalvar *var)
{
return var->name;
}
void
clear_internalvars (void)
{
struct internalvar *var;
while (internalvars)
{
var = internalvars;
internalvars = var->next;
xfree (var->name);
xfree (var->value);
xfree (var);
}
}
static void
show_convenience (char *ignore, int from_tty)
{
struct internalvar *var;
int varseen = 0;
for (var = internalvars; var; var = var->next)
{
if (!varseen)
{
varseen = 1;
}
printf_filtered ("$%s = ", var->name);
value_print (var->value, gdb_stdout, 0, Val_pretty_default);
printf_filtered ("\n");
}
if (!varseen)
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 (struct value *val)
{
COERCE_ARRAY (val);
return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
}
DOUBLEST
value_as_double (struct value *val)
{
DOUBLEST foo;
int inv;
foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv);
if (inv)
error ("Invalid floating value found in program.");
return foo;
}
CORE_ADDR
value_as_address (struct value *val)
{
#if 0
return ADDR_BITS_REMOVE (value_as_long (val));
#else
if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_METHOD)
return VALUE_ADDRESS (val);
COERCE_ARRAY (val);
if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_PTR
&& TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_REF
&& INTEGER_TO_ADDRESS_P ())
return INTEGER_TO_ADDRESS (VALUE_TYPE (val), VALUE_CONTENTS (val));
return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
#endif
}
LONGEST
unpack_long (struct type *type, const char *valaddr)
{
enum type_code code = TYPE_CODE (type);
int len = TYPE_LENGTH (type);
int nosign = TYPE_UNSIGNED (type);
if (current_language->la_language == language_scm
&& is_scmvalue_type (type))
return scm_unpack (type, valaddr, TYPE_CODE_INT);
switch (code)
{
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
return extract_signed_integer (valaddr, len);
case TYPE_CODE_FLT:
return extract_typed_floating (valaddr, type);
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
return extract_typed_address (valaddr, type);
case TYPE_CODE_MEMBER:
error ("not implemented: member types in unpack_long");
default:
error ("Value can't be converted to integer.");
}
return 0;
}
DOUBLEST
unpack_double (struct type *type, const char *valaddr, int *invp)
{
enum type_code code;
int len;
int nosign;
*invp = 0;
CHECK_TYPEDEF (type);
code = TYPE_CODE (type);
len = TYPE_LENGTH (type);
nosign = TYPE_UNSIGNED (type);
if (code == TYPE_CODE_FLT)
{
if (!floatformat_is_valid (floatformat_from_type (type), valaddr))
{
*invp = 1;
return 0.0;
}
return extract_typed_floating (valaddr, type);
}
else if (nosign)
{
return (ULONGEST) unpack_long (type, valaddr);
}
else
{
return unpack_long (type, valaddr);
}
}
CORE_ADDR
unpack_pointer (struct type *type, const char *valaddr)
{
return unpack_long (type, valaddr);
}
struct value *
value_static_field (struct type *type, int fieldno)
{
struct value *retval;
if (TYPE_FIELD_STATIC_HAS_ADDR (type, fieldno))
{
retval = value_at (TYPE_FIELD_TYPE (type, fieldno),
TYPE_FIELD_STATIC_PHYSADDR (type, fieldno),
NULL);
}
else
{
char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0, NULL);
if (sym == NULL)
{
struct minimal_symbol *msym = lookup_minimal_symbol (phys_name, NULL, NULL);
if (!msym)
return NULL;
else
{
retval = value_at (TYPE_FIELD_TYPE (type, fieldno),
SYMBOL_VALUE_ADDRESS (msym),
SYMBOL_BFD_SECTION (msym));
}
}
else
{
if (symbol_read_needs_frame (sym))
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)
SET_FIELD_PHYSADDR (TYPE_FIELD (type, fieldno),
VALUE_ADDRESS (retval));
}
return retval;
}
struct value *
value_change_enclosing_type (struct value *val, struct type *new_encl_type)
{
if (TYPE_LENGTH (new_encl_type) <= TYPE_LENGTH (VALUE_ENCLOSING_TYPE (val)))
{
VALUE_ENCLOSING_TYPE (val) = new_encl_type;
return val;
}
else
{
struct value *new_val;
struct value *prev;
new_val = (struct value *) xrealloc (val, sizeof (struct value) + TYPE_LENGTH (new_encl_type));
VALUE_ENCLOSING_TYPE (new_val) = new_encl_type;
if (val != all_values)
{
for (prev = all_values; prev != NULL; prev = prev->next)
{
if (prev->next == val)
{
prev->next = new_val;
break;
}
}
}
return new_val;
}
}
struct value *
value_primitive_field (struct value *arg1, int offset,
int fieldno, struct type *arg_type)
{
struct value *v;
struct type *type;
CHECK_TYPEDEF (arg_type);
type = TYPE_FIELD_TYPE (arg_type, fieldno);
if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
{
v = value_from_longest (type,
unpack_field_as_long (arg_type,
VALUE_CONTENTS (arg1)
+ offset,
fieldno));
VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8;
VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno);
VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset
+ TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
}
else if (fieldno < TYPE_N_BASECLASSES (arg_type))
{
v = allocate_value (VALUE_ENCLOSING_TYPE (arg1));
VALUE_TYPE (v) = type;
if (VALUE_LAZY (arg1))
VALUE_LAZY (v) = 1;
else
memcpy (VALUE_CONTENTS_ALL_RAW (v), VALUE_CONTENTS_ALL_RAW (arg1),
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg1)));
VALUE_OFFSET (v) = VALUE_OFFSET (arg1);
VALUE_EMBEDDED_OFFSET (v)
= offset +
VALUE_EMBEDDED_OFFSET (arg1) +
TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
}
else
{
offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
v = allocate_value (type);
if (VALUE_LAZY (arg1))
VALUE_LAZY (v) = 1;
else
memcpy (VALUE_CONTENTS_RAW (v),
VALUE_CONTENTS_RAW (arg1) + offset,
TYPE_LENGTH (type));
VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset
+ VALUE_EMBEDDED_OFFSET (arg1);
}
VALUE_LVAL (v) = VALUE_LVAL (arg1);
if (VALUE_LVAL (arg1) == lval_internalvar)
VALUE_LVAL (v) = lval_internalvar_component;
VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1);
VALUE_REGNO (v) = VALUE_REGNO (arg1);
return v;
}
struct value *
value_field (struct value *arg1, int fieldno)
{
return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1));
}
struct value *
value_fn_field (struct value **arg1p, struct fn_field *f, int j, struct type *type,
int offset)
{
struct value *v;
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
struct symbol *sym;
struct minimal_symbol *msym;
sym = lookup_symbol (physname, 0, VAR_DOMAIN, 0, NULL);
if (sym != NULL)
{
msym = NULL;
}
else
{
gdb_assert (sym == NULL);
msym = lookup_minimal_symbol (physname, NULL, NULL);
if (msym == NULL)
return NULL;
}
v = allocate_value (ftype);
if (sym)
{
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
}
else
{
VALUE_ADDRESS (v) = SYMBOL_VALUE_ADDRESS (msym);
}
if (arg1p)
{
if (type != VALUE_TYPE (*arg1p))
*arg1p = value_ind (value_cast (lookup_pointer_type (type),
value_addr (*arg1p)));
}
return v;
}
LONGEST
unpack_field_as_long (struct type *type, const char *valaddr, int fieldno)
{
ULONGEST val;
ULONGEST valmask;
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
int lsbcount;
struct type *field_type;
val = extract_unsigned_integer (valaddr + bitpos / 8, sizeof (val));
field_type = TYPE_FIELD_TYPE (type, fieldno);
CHECK_TYPEDEF (field_type);
if (BITS_BIG_ENDIAN)
lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);
else
lsbcount = (bitpos % 8);
val >>= lsbcount;
if ((bitsize > 0) && (bitsize < 8 * (int) sizeof (val)))
{
valmask = (((ULONGEST) 1) << bitsize) - 1;
val &= valmask;
if (!TYPE_UNSIGNED (field_type))
{
if (val & (valmask ^ (valmask >> 1)))
{
val |= ~valmask;
}
}
}
return (val);
}
void
modify_field (char *addr, LONGEST fieldval, int bitpos, int bitsize)
{
LONGEST oword;
if (bitsize < (8 * (int) sizeof (fieldval))
&& (~fieldval & ~((1 << (bitsize - 1)) - 1)) == 0)
fieldval = fieldval & ((1 << bitsize) - 1);
if (bitsize < (8 * (int) sizeof (fieldval))
&& 0 != (fieldval & ~((1 << bitsize) - 1)))
{
warning ("Value does not fit in %d bits.", bitsize);
fieldval = fieldval & ((1 << bitsize) - 1);
}
oword = extract_signed_integer (addr, sizeof oword);
if (BITS_BIG_ENDIAN)
bitpos = sizeof (oword) * 8 - bitpos - bitsize;
if (bitsize < 8 * (int) sizeof (oword))
oword &= ~(((((ULONGEST) 1) << bitsize) - 1) << bitpos);
else
oword &= ~((~(ULONGEST) 0) << bitpos);
oword |= fieldval << bitpos;
store_signed_integer (addr, sizeof oword, oword);
}
struct value *
value_from_longest (struct type *type, LONGEST num)
{
struct value *val = allocate_value (type);
enum type_code code;
int len;
retry:
code = TYPE_CODE (type);
len = TYPE_LENGTH (type);
switch (code)
{
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:
store_typed_address (VALUE_CONTENTS_RAW (val), type, (CORE_ADDR) num);
break;
default:
error ("Unexpected type (%d) encountered for integer constant.", code);
}
return val;
}
struct value *
value_from_pointer (struct type *type, CORE_ADDR addr)
{
struct value *val = allocate_value (type);
store_typed_address (VALUE_CONTENTS_RAW (val), type, addr);
return val;
}
struct value *
value_from_string (char *ptr)
{
struct value *val;
int len = strlen (ptr);
int lowbound = current_language->string_lower_bound;
struct type *rangetype =
create_range_type ((struct type *) NULL,
builtin_type_int,
lowbound, len + lowbound - 1);
struct type *stringtype =
create_array_type ((struct type *) NULL,
*current_language->string_char_type,
rangetype);
val = allocate_value (stringtype);
memcpy (VALUE_CONTENTS_RAW (val), ptr, len);
return val;
}
struct value *
value_from_double (struct type *type, DOUBLEST num)
{
struct value *val = allocate_value (type);
struct type *base_type = check_typedef (type);
enum type_code code = TYPE_CODE (base_type);
int len = TYPE_LENGTH (base_type);
if (code == TYPE_CODE_FLT)
{
store_typed_floating (VALUE_CONTENTS_RAW (val), base_type, num);
}
else
error ("Unexpected type encountered for floating constant.");
return val;
}
struct value *
register_value_being_returned (struct type *valtype, struct regcache *retbuf)
{
struct value *val = allocate_value (valtype);
if (TYPE_CODE (valtype) == TYPE_CODE_VOID)
return val;
if (!gdbarch_return_value_p (current_gdbarch))
{
CHECK_TYPEDEF (valtype);
EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val));
return val;
}
gdb_assert (gdbarch_return_value (current_gdbarch, valtype,
NULL, NULL, NULL)
== RETURN_VALUE_REGISTER_CONVENTION);
gdbarch_return_value (current_gdbarch, valtype, retbuf,
VALUE_CONTENTS_RAW (val) , NULL );
return val;
}
int
generic_use_struct_convention (int gcc_p, struct type *value_type)
{
return !((gcc_p == 1)
&& (TYPE_LENGTH (value_type) == 1
|| TYPE_LENGTH (value_type) == 2
|| TYPE_LENGTH (value_type) == 4
|| TYPE_LENGTH (value_type) == 8));
}
int
using_struct_return (struct type *value_type, int gcc_p)
{
enum type_code code = TYPE_CODE (value_type);
if (code == TYPE_CODE_ERROR)
error ("Function return type unknown.");
if (code == TYPE_CODE_VOID)
return 0;
if (!gdbarch_return_value_p (current_gdbarch))
{
if (code == TYPE_CODE_STRUCT
|| code == TYPE_CODE_UNION
|| code == TYPE_CODE_ARRAY
|| RETURN_VALUE_ON_STACK (value_type))
return USE_STRUCT_CONVENTION (gcc_p, value_type);
else
return 0;
}
return (gdbarch_return_value (current_gdbarch, value_type,
NULL, NULL, NULL)
== RETURN_VALUE_STRUCT_CONVENTION);
}
void
_initialize_values (void)
{
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\
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\".",
&showlist);
add_cmd ("values", no_class, show_values,
"Elements of value history around item number IDX (or last ten).",
&showlist);
}