/* Implementation of the GDB variable objects API.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
#include "varobj.h"
#include "vec.h"
+#include "gdbthread.h"
+#include "inferior.h"
/* Non-zero if we want to see trace of varobj level stuff. */
/* Block for which this expression is valid */
struct block *valid_block;
- /* The frame for this expression */
+ /* The frame for this expression. This field is set iff valid_block is
+ not NULL. */
struct frame_id frame;
- /* If 1, "update" always recomputes the frame & valid block
- using the currently selected frame. */
- int use_selected_frame;
+ /* The thread ID that this varobj_root belong to. This field
+ is only valid if valid_block is not NULL.
+ When not 0, indicates which thread 'frame' belongs to.
+ When 0, indicates that the thread list was empty when the varobj_root
+ was created. */
+ int thread_id;
+
+ /* If 1, the -var-update always recomputes the value in the
+ current thread and frame. Otherwise, variable object is
+ always updated in the specific scope/thread/frame */
+ int floating;
/* Flag that indicates validity: set to 0 when this varobj_root refers
to symbols that do not exist anymore. */
struct varobj_root *next;
};
-typedef struct varobj *varobj_p;
-
-DEF_VEC_P (varobj_p);
-
/* Every variable in the system has a structure of this type defined
for it. This structure holds all information necessary to manipulate
a particular object variable. Members which must be freed are noted. */
static struct value *value_of_child (struct varobj *parent, int index);
-static int variable_editable (struct varobj *var);
-
-static char *my_value_of_variable (struct varobj *var);
+static char *my_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
static char *value_get_print_value (struct value *value,
enum varobj_display_formats format);
static struct type *c_type_of_child (struct varobj *parent, int index);
-static int c_variable_editable (struct varobj *var);
-
-static char *c_value_of_variable (struct varobj *var);
+static char *c_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
/* C++ implementation */
static struct type *cplus_type_of_child (struct varobj *parent, int index);
-static int cplus_variable_editable (struct varobj *var);
-
-static char *cplus_value_of_variable (struct varobj *var);
+static char *cplus_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
/* Java implementation */
static struct type *java_type_of_child (struct varobj *parent, int index);
-static int java_variable_editable (struct varobj *var);
-
-static char *java_value_of_variable (struct varobj *var);
+static char *java_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
/* The language specific vector */
/* The type of the INDEX'th child of PARENT. */
struct type *(*type_of_child) (struct varobj * parent, int index);
- /* Is VAR editable? */
- int (*variable_editable) (struct varobj * var);
-
/* The current value of VAR. */
- char *(*value_of_variable) (struct varobj * var);
+ char *(*value_of_variable) (struct varobj * var,
+ enum varobj_display_formats format);
};
/* Array of known source language routines. */
c_value_of_root,
c_value_of_child,
c_type_of_child,
- c_variable_editable,
c_value_of_variable}
,
/* C */
c_value_of_root,
c_value_of_child,
c_type_of_child,
- c_variable_editable,
c_value_of_variable}
,
/* C++ */
cplus_value_of_root,
cplus_value_of_child,
cplus_type_of_child,
- cplus_variable_editable,
cplus_value_of_variable}
,
/* Java */
java_value_of_root,
java_value_of_child,
java_type_of_child,
- java_variable_editable,
java_value_of_variable}
};
/* frame = -2 means always use selected frame */
if (type == USE_SELECTED_FRAME)
- var->root->use_selected_frame = 1;
+ var->root->floating = 1;
block = NULL;
if (fi != NULL)
we must select the appropriate frame before parsing
the expression, otherwise the value will not be current.
Since select_frame is so benign, just call it for all cases. */
- if (fi != NULL)
+ if (innermost_block && fi != NULL)
{
var->root->frame = get_frame_id (fi);
+ var->root->thread_id = pid_to_thread_id (inferior_ptid);
old_fi = get_selected_frame (NULL);
- select_frame (fi);
+ select_frame (fi);
}
- /* We definitively need to catch errors here.
+ /* We definitely need to catch errors here.
If evaluate_expression succeeds we got the value we wanted.
But if it fails, we still go on with a call to evaluate_type() */
if (!gdb_evaluate_expression (var->root->exp, &value))
var->format = variable_default_display (var);
}
+ if (varobj_value_is_changeable_p (var)
+ && var->value && !value_lazy (var->value))
+ {
+ free (var->print_value);
+ var->print_value = value_get_print_value (var->value, var->format);
+ }
+
return var->format;
}
return var->format;
}
+/* If the variable object is bound to a specific thread, that
+ is its evaluation can always be done in context of a frame
+ inside that thread, returns GDB id of the thread -- which
+ is always positive. Otherwise, returns -1. */
+int
+varobj_get_thread_id (struct varobj *var)
+{
+ if (var->root->valid_block && var->root->thread_id > 0)
+ return var->root->thread_id;
+ else
+ return -1;
+}
+
void
varobj_set_frozen (struct varobj *var, int frozen)
{
/* Creates a list of the immediate children of a variable object;
the return code is the number of such children or -1 on error */
-int
-varobj_list_children (struct varobj *var, struct varobj ***childlist)
+VEC (varobj_p)*
+varobj_list_children (struct varobj *var)
{
struct varobj *child;
char *name;
int i;
- /* sanity check: have we been passed a pointer? */
- if (childlist == NULL)
- return -1;
-
- *childlist = NULL;
-
if (var->num_children == -1)
var->num_children = number_of_children (var);
/* If that failed, give up. */
if (var->num_children == -1)
- return -1;
+ return var->children;
/* If we're called when the list of children is not yet initialized,
allocate enough elements in it. */
while (VEC_length (varobj_p, var->children) < var->num_children)
VEC_safe_push (varobj_p, var->children, NULL);
- /* List of children */
- *childlist = xmalloc ((var->num_children + 1) * sizeof (struct varobj *));
-
for (i = 0; i < var->num_children; i++)
{
- varobj_p existing;
-
- /* Mark as the end in case we bail out */
- *((*childlist) + i) = NULL;
-
- existing = VEC_index (varobj_p, var->children, i);
+ varobj_p existing = VEC_index (varobj_p, var->children, i);
if (existing == NULL)
{
existing = create_child (var, i, name);
VEC_replace (varobj_p, var->children, i, existing);
}
-
- *((*childlist) + i) = existing;
}
- /* End of list is marked by a NULL pointer */
- *((*childlist) + i) = NULL;
-
- return var->num_children;
+ return var->children;
}
/* Obtain the type of an object Variable as a string similar to the one gdb
{
int attributes = 0;
- if (var->root->is_valid && variable_editable (var))
+ if (varobj_editable_p (var))
/* FIXME: define masks for attributes */
attributes |= 0x00000001; /* Editable */
return attributes;
}
+char *
+varobj_get_formatted_value (struct varobj *var,
+ enum varobj_display_formats format)
+{
+ return my_value_of_variable (var, format);
+}
+
char *
varobj_get_value (struct varobj *var)
{
- return my_value_of_variable (var);
+ return my_value_of_variable (var, var->format);
}
/* Set the value of an object variable (if it is editable) to the
struct expression *exp;
struct value *value;
int saved_input_radix = input_radix;
+ char *s = expression;
+ int i;
- if (var->value != NULL && variable_editable (var))
- {
- char *s = expression;
- int i;
-
- input_radix = 10; /* ALWAYS reset to decimal temporarily */
- exp = parse_exp_1 (&s, 0, 0);
- if (!gdb_evaluate_expression (exp, &value))
- {
- /* We cannot proceed without a valid expression. */
- xfree (exp);
- return 0;
- }
+ gdb_assert (varobj_editable_p (var));
- /* All types that are editable must also be changeable. */
- gdb_assert (varobj_value_is_changeable_p (var));
-
- /* The value of a changeable variable object must not be lazy. */
- gdb_assert (!value_lazy (var->value));
-
- /* Need to coerce the input. We want to check if the
- value of the variable object will be different
- after assignment, and the first thing value_assign
- does is coerce the input.
- For example, if we are assigning an array to a pointer variable we
- should compare the pointer with the the array's address, not with the
- array's content. */
- value = coerce_array (value);
-
- /* The new value may be lazy. gdb_value_assign, or
- rather value_contents, will take care of this.
- If fetching of the new value will fail, gdb_value_assign
- with catch the exception. */
- if (!gdb_value_assign (var->value, value, &val))
- return 0;
-
- /* If the value has changed, record it, so that next -var-update can
- report this change. If a variable had a value of '1', we've set it
- to '333' and then set again to '1', when -var-update will report this
- variable as changed -- because the first assignment has set the
- 'updated' flag. There's no need to optimize that, because return value
- of -var-update should be considered an approximation. */
- var->updated = install_new_value (var, val, 0 /* Compare values. */);
- input_radix = saved_input_radix;
- return 1;
+ input_radix = 10; /* ALWAYS reset to decimal temporarily */
+ exp = parse_exp_1 (&s, 0, 0);
+ if (!gdb_evaluate_expression (exp, &value))
+ {
+ /* We cannot proceed without a valid expression. */
+ xfree (exp);
+ return 0;
}
- return 0;
+ /* All types that are editable must also be changeable. */
+ gdb_assert (varobj_value_is_changeable_p (var));
+
+ /* The value of a changeable variable object must not be lazy. */
+ gdb_assert (!value_lazy (var->value));
+
+ /* Need to coerce the input. We want to check if the
+ value of the variable object will be different
+ after assignment, and the first thing value_assign
+ does is coerce the input.
+ For example, if we are assigning an array to a pointer variable we
+ should compare the pointer with the the array's address, not with the
+ array's content. */
+ value = coerce_array (value);
+
+ /* The new value may be lazy. gdb_value_assign, or
+ rather value_contents, will take care of this.
+ If fetching of the new value will fail, gdb_value_assign
+ with catch the exception. */
+ if (!gdb_value_assign (var->value, value, &val))
+ return 0;
+
+ /* If the value has changed, record it, so that next -var-update can
+ report this change. If a variable had a value of '1', we've set it
+ to '333' and then set again to '1', when -var-update will report this
+ variable as changed -- because the first assignment has set the
+ 'updated' flag. There's no need to optimize that, because return value
+ of -var-update should be considered an approximation. */
+ var->updated = install_new_value (var, val, 0 /* Compare values. */);
+ input_radix = saved_input_radix;
+ return 1;
}
/* Returns a malloc'ed list with all root variable objects */
struct value *new;
VEC (varobj_p) *stack = NULL;
VEC (varobj_p) *result = NULL;
- struct frame_id old_fid;
struct frame_info *fi;
/* sanity check: have we been passed a pointer? */
if ((*varp)->root->rootvar == *varp)
{
- /* Save the selected stack frame, since we will need to change it
- in order to evaluate expressions. */
- old_fid = get_frame_id (deprecated_safe_get_selected_frame ());
-
/* Update the root variable. value_of_root can return NULL
if the variable is no longer around, i.e. we stepped out of
the frame in which a local existed. We are letting the
value_of_root variable dispose of the varobj if the type
has changed. */
- type_changed = 1;
new = value_of_root (varp, &type_changed);
-
- /* Restore selected frame. */
- fi = frame_find_by_id (old_fid);
- if (fi)
- select_frame (fi);
- /* If this is a "use_selected_frame" varobj, and its type has changed,
+ /* If this is a floating varobj, and its type has changed,
them note that it's changed. */
if (type_changed)
VEC_safe_push (varobj_p, result, *varp);
var->root->exp = NULL;
var->root->valid_block = NULL;
var->root->frame = null_frame_id;
- var->root->use_selected_frame = 0;
+ var->root->floating = 0;
var->root->rootvar = NULL;
var->root->is_valid = 1;
return (*var->root->lang->name_of_child) (var, index);
}
-/* What is the ``struct value *'' of the root variable VAR?
- TYPE_CHANGED controls what to do if the type of a
- use_selected_frame = 1 variable changes. On input,
- TYPE_CHANGED = 1 means discard the old varobj, and replace
- it with this one. TYPE_CHANGED = 0 means leave it around.
- NB: In both cases, var_handle will point to the new varobj,
- so if you use TYPE_CHANGED = 0, you will have to stash the
- old varobj pointer away somewhere before calling this.
- On return, TYPE_CHANGED will be 1 if the type has changed, and
- 0 otherwise. */
+/* What is the ``struct value *'' of the root variable VAR?
+ For floating variable object, evaluation can get us a value
+ of different type from what is stored in varobj already. In
+ that case:
+ - *type_changed will be set to 1
+ - old varobj will be freed, and new one will be
+ created, with the same name.
+ - *var_handle will be set to the new varobj
+ Otherwise, *type_changed will be set to 0. */
static struct value *
value_of_root (struct varobj **var_handle, int *type_changed)
{
if (!is_root_p (var))
return NULL;
- if (var->root->use_selected_frame)
+ if (var->root->floating)
{
struct varobj *tmp_var;
char *old_type, *new_type;
new_type = varobj_get_type (tmp_var);
if (strcmp (old_type, new_type) == 0)
{
+ /* The expression presently stored inside var->root->exp
+ remembers the locations of local variables relatively to
+ the frame where the expression was created (in DWARF location
+ button, for example). Naturally, those locations are not
+ 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;
+
varobj_delete (tmp_var, NULL, 0);
*type_changed = 0;
}
else
{
- if (*type_changed)
- {
- tmp_var->obj_name =
- savestring (var->obj_name, strlen (var->obj_name));
- varobj_delete (var, NULL, 0);
- }
- else
- {
- tmp_var->obj_name = varobj_gen_name ();
- }
+ tmp_var->obj_name =
+ savestring (var->obj_name, strlen (var->obj_name));
+ varobj_delete (var, NULL, 0);
+
install_variable (tmp_var);
*var_handle = tmp_var;
var = *var_handle;
return value;
}
-/* Is this variable editable? Use the variable's type to make
- this determination. */
-static int
-variable_editable (struct varobj *var)
-{
- return (*var->root->lang->variable_editable) (var);
-}
-
/* GDB already has a command called "value_of_variable". Sigh. */
static char *
-my_value_of_variable (struct varobj *var)
+my_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
if (var->root->is_valid)
- return (*var->root->lang->value_of_variable) (var);
+ return (*var->root->lang->value_of_variable) (var, format);
else
return NULL;
}
stb = mem_fileopen ();
old_chain = make_cleanup_ui_file_delete (stb);
- common_val_print (value, stb, format_code[(int) format], 1, 0, 0);
+ common_val_print (value, stb, format_code[(int) format], 1, 0, 0,
+ current_language);
thevalue = ui_file_xstrdup (stb, &dummy);
do_cleanups (old_chain);
return thevalue;
}
+int
+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;
+
+ type = get_value_type (var);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_METHOD:
+ return 0;
+ break;
+
+ default:
+ return 1;
+ break;
+ }
+}
+
/* Return non-zero if changes in value of VAR
must be detected and reported by -var-update.
Return zero is -var-update should never report
return r;
}
+/* Return 1 if that varobj is floating, that is is always evaluated in the
+ selected frame, and not bound to thread/frame. Such variable objects
+ are created using '@' as frame specifier to -var-create. */
+int
+varobj_floating_p (struct varobj *var)
+{
+ return var->root->floating;
+}
+
/* Given the value and the type of a variable object,
adjust the value and type to those necessary
for getting children of the variable object.
|| TYPE_CODE (target_type) == TYPE_CODE_UNION)
{
if (value && *value)
- gdb_value_ind (*value, value);
+ {
+ int success = gdb_value_ind (*value, value);
+ if (!success)
+ *value = NULL;
+ }
*type = target_type;
if (was_ptr)
*was_ptr = 1;
*cname = xstrprintf ("*%s", parent->name);
if (cvalue && value)
- gdb_value_ind (value, cvalue);
+ {
+ int success = gdb_value_ind (value, cvalue);
+ if (!success)
+ *cvalue = NULL;
+ }
/* Don't use get_target_type because it calls
check_typedef and here, we want to show the true
return child->path_expr;
}
+/* If frame associated with VAR can be found, switch
+ to it and return 1. Otherwise, return 0. */
+static int
+check_scope (struct varobj *var)
+{
+ struct frame_info *fi;
+ int scope;
+
+ fi = frame_find_by_id (var->root->frame);
+ scope = fi != NULL;
+
+ 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;
+ else
+ select_frame (fi);
+ }
+ return scope;
+}
+
static struct value *
c_value_of_root (struct varobj **var_handle)
{
struct value *new_val = NULL;
struct varobj *var = *var_handle;
struct frame_info *fi;
- int within_scope;
-
+ int within_scope = 0;
+ struct cleanup *back_to;
+
/* Only root variables can be updated... */
if (!is_root_p (var))
/* Not a root var */
return NULL;
+ back_to = make_cleanup_restore_current_thread (
+ inferior_ptid, get_frame_id (deprecated_safe_get_selected_frame ()));
/* Determine whether the variable is still around. */
- if (var->root->valid_block == NULL || var->root->use_selected_frame)
+ if (var->root->valid_block == NULL || var->root->floating)
within_scope = 1;
+ else if (var->root->thread_id == 0)
+ {
+ /* The program was single-threaded when the variable object was
+ created. Technically, it's possible that the program became
+ multi-threaded since then, but we don't support such
+ scenario yet. */
+ within_scope = check_scope (var);
+ }
else
{
- fi = frame_find_by_id (var->root->frame);
- within_scope = fi != NULL;
- /* FIXME: select_frame could fail */
- if (fi)
+ ptid_t ptid = thread_id_to_pid (var->root->thread_id);
+ if (in_thread_list (ptid))
{
- CORE_ADDR pc = get_frame_pc (fi);
- if (pc < BLOCK_START (var->root->valid_block) ||
- pc >= BLOCK_END (var->root->valid_block))
- within_scope = 0;
- else
- select_frame (fi);
- }
+ switch_to_thread (ptid);
+ within_scope = check_scope (var);
+ }
}
if (within_scope)
return new_val;
}
+ do_cleanups (back_to);
+
return NULL;
}
return type;
}
-static int
-c_variable_editable (struct varobj *var)
-{
- switch (TYPE_CODE (get_value_type (var)))
- {
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- case TYPE_CODE_ARRAY:
- case TYPE_CODE_FUNC:
- case TYPE_CODE_METHOD:
- return 0;
- break;
-
- default:
- return 1;
- break;
- }
-}
-
static char *
-c_value_of_variable (struct varobj *var)
+c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
/* BOGUS: if val_print sees a struct/class, or a reference to one,
it will print out its children instead of "{...}". So we need to
gdb_assert (varobj_value_is_changeable_p (var));
gdb_assert (!value_lazy (var->value));
- return value_get_print_value (var->value, var->format);
+
+ /* If the specified format is the current one,
+ we can reuse print_value */
+ if (format == var->format)
+ return xstrdup (var->print_value);
+ else
+ return value_get_print_value (var->value, format);
}
}
}
adjust_value_for_child_access (&value, &type, &was_ptr);
if (TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ || TYPE_CODE (type) == TYPE_CODE_UNION)
{
char *join = was_ptr ? "->" : ".";
if (CPLUS_FAKE_CHILD (parent))
return type;
}
-static int
-cplus_variable_editable (struct varobj *var)
-{
- if (CPLUS_FAKE_CHILD (var))
- return 0;
-
- return c_variable_editable (var);
-}
-
static char *
-cplus_value_of_variable (struct varobj *var)
+cplus_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
/* If we have one of our special types, don't print out
if (CPLUS_FAKE_CHILD (var))
return xstrdup ("");
- return c_value_of_variable (var);
+ return c_value_of_variable (var, format);
}
\f
/* Java */
return cplus_type_of_child (parent, index);
}
-static int
-java_variable_editable (struct varobj *var)
-{
- return cplus_variable_editable (var);
-}
-
static char *
-java_value_of_variable (struct varobj *var)
+java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
- return cplus_value_of_variable (var);
+ return cplus_value_of_variable (var, format);
}
\f
extern void _initialize_varobj (void);
varp = all_rootvarobj;
while (*varp != NULL)
{
+ /* Floating varobjs are reparsed on each stop, so we don't care if
+ the presently parsed expression refers to something that's gone. */
+ if ((*varp)->root->floating)
+ continue;
+
/* global var must be re-evaluated. */
if ((*varp)->root->valid_block == NULL)
{