/* Implementation of the GDB variable objects API.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009 Free Software Foundation, Inc.
+ 2009, 2010 Free Software Foundation, Inc.
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
static int is_root_p (struct varobj *var);
+#if HAVE_PYTHON
+
static struct varobj *
varobj_add_child (struct varobj *var, const char *name, struct value *value);
+#endif /* HAVE_PYTHON */
+
/* C implementation */
static int c_number_of_children (struct varobj *var);
comparing it against our argument. */
CORE_ADDR frame_base = get_frame_base_address (frame);
int addr_bit = gdbarch_addr_bit (get_frame_arch (frame));
+
if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
frame_base &= ((CORE_ADDR) 1 << addr_bit) - 1;
char *expression, CORE_ADDR frame, enum varobj_type type)
{
struct varobj *var;
- struct frame_info *fi;
- struct frame_info *old_fi = NULL;
- struct block *block;
struct cleanup *old_chain;
/* Fill out a varobj structure for the (root) variable being constructed. */
if (expression != NULL)
{
+ struct frame_info *fi;
+ struct frame_id old_id = null_frame_id;
+ struct block *block;
char *p;
enum varobj_languages lang;
struct value *value = NULL;
var->root->frame = get_frame_id (fi);
var->root->thread_id = pid_to_thread_id (inferior_ptid);
- old_fi = get_selected_frame (NULL);
+ old_id = get_frame_id (get_selected_frame (NULL));
select_frame (fi);
}
/* Error getting the value. Try to at least get the
right type. */
struct value *type_only_value = evaluate_type (var->root->exp);
+
var->type = value_type (type_only_value);
}
else
var->root->rootvar = var;
/* Reset the selected frame */
- if (old_fi != NULL)
- select_frame (old_fi);
+ if (frame_id_p (old_id))
+ select_frame (frame_find_by_id (old_id));
}
/* If the variable object name is null, that means this
return delcount;
}
+#if HAVE_PYTHON
+
/* Convenience function for varobj_set_visualizer. Instantiate a
pretty-printer for a given value. */
static PyObject *
instantiate_pretty_printer (PyObject *constructor, struct value *value)
{
-#if HAVE_PYTHON
PyObject *val_obj = NULL;
PyObject *printer;
printer = PyObject_CallFunctionObjArgs (constructor, val_obj, NULL);
Py_DECREF (val_obj);
return printer;
-#endif
return NULL;
}
+#endif
+
/* Set/Get variable object display format */
enum varobj_display_formats
}
}
+#if HAVE_PYTHON
+
/* A helper for update_dynamic_varobj_children that installs a new
child when needed. */
{
/* There's no child yet. */
struct varobj *child = varobj_add_child (var, name, value);
+
if (new)
{
VEC_safe_push (varobj_p, *new, child);
else
{
varobj_p existing = VEC_index (varobj_p, var->children, index);
+
if (install_new_value (existing, value, 0))
{
if (changed)
}
}
-#if HAVE_PYTHON
-
static int
dynamic_varobj_has_child_method (struct varobj *var)
{
if (i < VEC_length (varobj_p, var->children))
{
int j;
+
*cchanged = 1;
for (j = i; j < VEC_length (varobj_p, var->children); ++j)
varobj_delete (VEC_index (varobj_p, var->children, j), NULL, 0);
VEC (varobj_p)*
varobj_list_children (struct varobj *var, int *from, int *to)
{
- struct varobj *child;
char *name;
int i, children_changed;
return var->children;
}
+#if HAVE_PYTHON
+
static struct varobj *
varobj_add_child (struct varobj *var, const char *name, struct value *value)
{
varobj_p v = create_child_with_value (var,
VEC_length (varobj_p, var->children),
name, value);
+
VEC_safe_push (varobj_p, var->children, v);
return v;
}
+#endif /* HAVE_PYTHON */
+
/* Obtain the type of an object Variable as a string similar to the one gdb
prints on the console */
varobj_set_value (struct varobj *var, char *expression)
{
struct value *val;
- int offset = 0;
- int error = 0;
/* The argument "expression" contains the variable's new value.
We need to first construct a legal expression for this -- ugh! */
struct value *value;
int saved_input_radix = input_radix;
char *s = expression;
- int i;
gdb_assert (varobj_editable_p (var));
if (var->constructor != Py_None && var->value)
{
struct cleanup *cleanup;
- PyObject *pretty_printer = NULL;
cleanup = varobj_ensure_python_env (var);
{
struct varobj *parent = var->parent;
int frozen = var->frozen;
+
for (; !frozen && parent; parent = parent->parent)
frozen |= parent->frozen;
{
xfree (print_value);
print_value = value_get_print_value (var->value, var->format, var);
- if (!var->print_value || strcmp (var->print_value, print_value) != 0)
+ if ((var->print_value == NULL && print_value != NULL)
+ || (var->print_value != NULL && print_value == NULL)
+ || (var->print_value != NULL && print_value != NULL
+ && strcmp (var->print_value, print_value) != 0))
changed = 1;
}
if (var->print_value)
varobj_set_visualizer (struct varobj *var, const char *visualizer)
{
#if HAVE_PYTHON
- PyObject *mainmod, *globals, *pretty_printer, *constructor;
- struct cleanup *back_to, *value;
+ PyObject *mainmod, *globals, *constructor;
+ struct cleanup *back_to;
back_to = varobj_ensure_python_env (var);
int changed = 0;
int type_changed = 0;
int i;
- int vleft;
- struct varobj *v;
- struct varobj **cv;
- struct varobj **templist = NULL;
struct value *new;
VEC (varobj_update_result) *stack = NULL;
VEC (varobj_update_result) *result = NULL;
- struct frame_info *fi;
/* Frozen means frozen -- we don't check for any change in
this varobj, including its going out of scope, or
if (!(*varp)->root->is_valid)
{
- varobj_update_result r = {*varp};
+ varobj_update_result r = {0};
+
+ r.varobj = *varp;
r.status = VAROBJ_INVALID;
VEC_safe_push (varobj_update_result, result, &r);
return result;
if ((*varp)->root->rootvar == *varp)
{
- varobj_update_result r = {*varp};
+ varobj_update_result r = {0};
+
+ r.varobj = *varp;
r.status = VAROBJ_IN_SCOPE;
/* Update the root variable. value_of_root can return NULL
}
else
{
- varobj_update_result r = {*varp};
+ varobj_update_result r = {0};
+
+ r.varobj = *varp;
VEC_safe_push (varobj_update_result, stack, &r);
}
if (v->pretty_printer)
{
VEC (varobj_p) *changed = 0, *new = 0, *unchanged = 0;
- int i, children_changed;
+ int i, children_changed = 0;
if (v->frozen)
continue;
for (i = VEC_length (varobj_p, changed) - 1; i >= 0; --i)
{
varobj_p tmp = VEC_index (varobj_p, changed, i);
- varobj_update_result r = {tmp};
+ varobj_update_result r = {0};
+
+ r.varobj = tmp;
r.changed = 1;
r.value_installed = 1;
VEC_safe_push (varobj_update_result, stack, &r);
for (i = VEC_length (varobj_p, unchanged) - 1; i >= 0; --i)
{
varobj_p tmp = VEC_index (varobj_p, unchanged, i);
+
if (!tmp->frozen)
{
- varobj_update_result r = {tmp};
+ varobj_update_result r = {0};
+
+ r.varobj = tmp;
r.value_installed = 1;
VEC_safe_push (varobj_update_result, stack, &r);
}
for (i = VEC_length (varobj_p, v->children)-1; i >= 0; --i)
{
varobj_p c = VEC_index (varobj_p, v->children, i);
+
/* Child may be NULL if explicitly deleted by -var-delete. */
if (c != NULL && !c->frozen)
{
- varobj_update_result r = {c};
+ varobj_update_result r = {0};
+
+ r.varobj = c;
VEC_safe_push (varobj_update_result, stack, &r);
}
}
for (i = 0; i < VEC_length (varobj_p, var->children); ++i)
{
varobj_p child = VEC_index (varobj_p, var->children, i);
+
if (!child)
continue;
if (!remove_from_parent_p)
new_root_variable (void)
{
struct varobj *var = new_variable ();
+
var->root = (struct varobj_root *) xmalloc (sizeof (struct varobj_root));;
var->root->lang = NULL;
var->root->exp = NULL;
get_type (struct varobj *var)
{
struct type *type;
- type = var->type;
+ type = var->type;
if (type != NULL)
type = check_typedef (type);
correct in other frames, so update the expression. */
struct expression *tmp_exp = var->root->exp;
+
var->root->exp = tmp_var->root->exp;
tmp_var->root->exp = tmp_exp;
struct cleanup *old_chain;
gdb_byte *thevalue = NULL;
struct value_print_options opts;
- int len = 0;
+ struct type *type = NULL;
+ long len = 0;
+ char *encoding = NULL;
+ struct gdbarch *gdbarch = NULL;
if (value == NULL)
return NULL;
+ gdbarch = get_type_arch (value_type (value));
#if HAVE_PYTHON
{
struct cleanup *back_to = varobj_ensure_python_env (var);
&replacement);
if (output)
{
- PyObject *py_str
- = python_string_to_target_python_string (output);
- if (py_str)
+ if (gdbpy_is_lazy_string (output))
{
- char *s = PyString_AsString (py_str);
- len = PyString_Size (py_str);
- thevalue = xmemdup (s, len + 1, len + 1);
- Py_DECREF (py_str);
+ thevalue = gdbpy_extract_lazy_string (output, &type,
+ &len, &encoding);
+ string_print = 1;
+ }
+ else
+ {
+ PyObject *py_str
+ = python_string_to_target_python_string (output);
+
+ if (py_str)
+ {
+ char *s = PyString_AsString (py_str);
+
+ len = PyString_Size (py_str);
+ thevalue = xmemdup (s, len + 1, len + 1);
+ type = builtin_type (gdbarch)->builtin_char;
+ Py_DECREF (py_str);
+ }
}
Py_DECREF (output);
}
if (thevalue && !string_print)
{
do_cleanups (back_to);
+ xfree (encoding);
return thevalue;
}
if (replacement)
opts.raw = 1;
if (thevalue)
{
- struct gdbarch *gdbarch = get_type_arch (value_type (value));
make_cleanup (xfree, thevalue);
- LA_PRINT_STRING (stb, builtin_type (gdbarch)->builtin_char,
- thevalue, len, 0, &opts);
+ make_cleanup (xfree, encoding);
+ LA_PRINT_STRING (stb, type, thevalue, len, encoding, 0, &opts);
}
else
common_val_print (value, stb, 0, &opts, current_language);
varobj_editable_p (struct varobj *var)
{
struct type *type;
- struct value *value;
if (!(var->root->is_valid && var->value && VALUE_LVAL (var->value)))
return 0;
{
if (value && *value)
{
- int success = gdb_value_ind (*value, value);
+ int success = gdb_value_ind (*value, value);
+
if (!success)
*value = NULL;
}
{
struct value *result = NULL;
volatile struct gdb_exception e;
-
struct type *type = value_type (value);
+
type = check_typedef (type);
gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
{
case TYPE_CODE_ARRAY:
if (cname)
- *cname = xstrprintf ("%d", index
- + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)));
+ *cname = xstrdup (int_string (index
+ + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
+ 10, 1, 0, 0));
if (cvalue && value)
{
int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
+
gdb_value_subscript (value, real_index, cvalue);
}
*ctype = get_target_type (type);
if (cfull_expression)
- *cfull_expression = xstrprintf ("(%s)[%d]", parent_expression,
- index
- + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)));
+ *cfull_expression =
+ xstrprintf ("(%s)[%s]", parent_expression,
+ int_string (index
+ + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
+ 10, 1, 0, 0));
break;
if (cfull_expression)
{
char *join = was_ptr ? "->" : ".";
+
*cfull_expression = xstrprintf ("(%s)%s%s", parent_expression, join,
TYPE_FIELD_NAME (type, index));
}
if (cvalue && value)
{
int success = gdb_value_ind (value, cvalue);
+
if (!success)
*cvalue = NULL;
}
c_name_of_child (struct varobj *parent, int index)
{
char *name;
+
c_describe_child (parent, index, &name, NULL, NULL, NULL);
return name;
}
if (fi)
{
CORE_ADDR pc = get_frame_pc (fi);
+
if (pc < BLOCK_START (var->root->valid_block) ||
pc >= BLOCK_END (var->root->valid_block))
scope = 0;
{
struct value *new_val = NULL;
struct varobj *var = *var_handle;
- struct frame_info *fi;
int within_scope = 0;
struct cleanup *back_to;
c_value_of_child (struct varobj *parent, int index)
{
struct value *value = NULL;
- c_describe_child (parent, index, NULL, &value, NULL, NULL);
+ c_describe_child (parent, index, NULL, &value, NULL, NULL);
return value;
}
c_type_of_child (struct varobj *parent, int index)
{
struct type *type = NULL;
+
c_describe_child (parent, index, NULL, NULL, &type, NULL);
return type;
}
case TYPE_CODE_ARRAY:
{
char *number;
+
number = xstrprintf ("[%d]", var->num_children);
return (number);
}
static void
cplus_class_num_children (struct type *type, int children[3])
{
- int i;
+ int i, vptr_fieldno;
+ struct type *basetype = NULL;
children[v_public] = 0;
children[v_private] = 0;
children[v_protected] = 0;
+ vptr_fieldno = get_vptr_fieldno (type, &basetype);
for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
{
- /* If we have a virtual table pointer, omit it. */
- if (TYPE_VPTR_BASETYPE (type) == type && TYPE_VPTR_FIELDNO (type) == i)
+ /* If we have a virtual table pointer, omit it. Even if virtual
+ table pointers are not specifically marked in the debug info,
+ they should be artificial. */
+ if ((type == basetype && i == vptr_fieldno)
+ || TYPE_FIELD_ARTIFICIAL (type, i))
continue;
if (TYPE_FIELD_PROTECTED (type, i))
char **cname, struct value **cvalue, struct type **ctype,
char **cfull_expression)
{
- char *name = NULL;
struct value *value;
struct type *type;
int was_ptr;
|| TYPE_CODE (type) == TYPE_CODE_UNION)
{
char *join = was_ptr ? "->" : ".";
+
if (CPLUS_FAKE_CHILD (parent))
{
/* The fields of the class type are ordered as they
find the indexed field. */
int type_index = TYPE_N_BASECLASSES (type);
enum accessibility acc = public_field;
+ int vptr_fieldno;
+ struct type *basetype = NULL;
+
+ vptr_fieldno = get_vptr_fieldno (type, &basetype);
if (strcmp (parent->name, "private") == 0)
acc = private_field;
else if (strcmp (parent->name, "protected") == 0)
while (index >= 0)
{
- if (TYPE_VPTR_BASETYPE (type) == type
- && type_index == TYPE_VPTR_FIELDNO (type))
+ if ((type == basetype && type_index == vptr_fieldno)
+ || TYPE_FIELD_ARTIFICIAL (type, type_index))
; /* ignore vptr */
else if (match_accessibility (type, type_index, acc))
--index;
if (cfull_expression)
{
char *ptr = was_ptr ? "*" : "";
+
/* Cast the parent to the base' type. Note that in gdb,
expression like
(Base1)d
{
char *access = NULL;
int children[3];
+
cplus_class_num_children (type, children);
/* Everything beyond the baseclasses can
cplus_name_of_child (struct varobj *parent, int index)
{
char *name = NULL;
+
cplus_describe_child (parent, index, &name, NULL, NULL, NULL);
return name;
}
cplus_value_of_child (struct varobj *parent, int index)
{
struct value *value = NULL;
+
cplus_describe_child (parent, index, NULL, &value, NULL, NULL);
return value;
}
cplus_type_of_child (struct varobj *parent, int index)
{
struct type *type = NULL;
+
cplus_describe_child (parent, index, NULL, NULL, &type, NULL);
return type;
}
static char *
-cplus_value_of_variable (struct varobj *var, enum varobj_display_formats format)
+cplus_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format)
{
/* If we have one of our special types, don't print out