X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fvarobj.c;h=317f6b47fc3e9a3b7050f1e9a658136b8b148856;hb=725a9891bcc665280fb0f749d47416c8e6ea94b7;hp=ccca0511a2ca7880174913e4bed390ce28d058a7;hpb=2024f65ab8bec1dd6d60cfbd92cca9125d3d8a1b;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/varobj.c b/gdb/varobj.c index ccca0511a2..317f6b47fc 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -1,11 +1,11 @@ /* 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 it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,9 +14,7 @@ GNU General Public License for more details. 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., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "exceptions.h" @@ -33,6 +31,8 @@ #include "varobj.h" #include "vec.h" +#include "gdbthread.h" +#include "inferior.h" /* Non-zero if we want to see trace of varobj level stuff. */ @@ -64,12 +64,25 @@ struct varobj_root /* 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. */ + int is_valid; /* Language info for this variable and its children */ struct language_specific *lang; @@ -81,10 +94,6 @@ struct varobj_root 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. */ @@ -97,6 +106,10 @@ struct varobj /* NOTE: This is the "expression" */ char *name; + /* Alloc'd expression for this child. Can be used to create a + root variable corresponding to this child. */ + char *path_expr; + /* The alloc'd name for this variable's object. This is here for convenience when constructing this object's children. */ char *obj_name; @@ -104,7 +117,9 @@ struct varobj /* Index of this variable in its parent or -1 */ int index; - /* The type of this variable. This may NEVER be NULL. */ + /* The type of this variable. This can be NULL + for artifial variable objects -- currently, the "accessibility" + variable objects in C++. */ struct type *type; /* The value of this expression or subexpression. A NULL value @@ -133,6 +148,16 @@ struct varobj /* Last print value. */ char *print_value; + + /* Is this variable frozen. Frozen variables are never implicitly + updated by -var-update * + or -var-update . */ + int frozen; + + /* Is the value of this variable intentionally not fetched? It is + not fetched if either the variable is frozen, or any parents is + frozen. */ + int not_fetched; }; struct cpstack @@ -203,9 +228,8 @@ static struct value *value_of_root (struct varobj **var_handle, int *); 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); @@ -222,15 +246,16 @@ static char *c_name_of_variable (struct varobj *parent); static char *c_name_of_child (struct varobj *parent, int index); +static char *c_path_expr_of_child (struct varobj *child); + static struct value *c_value_of_root (struct varobj **var_handle); static struct value *c_value_of_child (struct varobj *parent, int index); 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 */ @@ -242,15 +267,16 @@ static char *cplus_name_of_variable (struct varobj *parent); static char *cplus_name_of_child (struct varobj *parent, int index); +static char *cplus_path_expr_of_child (struct varobj *child); + static struct value *cplus_value_of_root (struct varobj **var_handle); static struct value *cplus_value_of_child (struct varobj *parent, int index); 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 */ @@ -260,15 +286,16 @@ static char *java_name_of_variable (struct varobj *parent); static char *java_name_of_child (struct varobj *parent, int index); +static char *java_path_expr_of_child (struct varobj *child); + static struct value *java_value_of_root (struct varobj **var_handle); static struct value *java_value_of_child (struct varobj *parent, int index); 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 */ @@ -287,6 +314,10 @@ struct language_specific /* The name of the INDEX'th child of PARENT. */ char *(*name_of_child) (struct varobj * parent, int index); + /* Returns the rooted expression of CHILD, which is a variable + obtain that has some parent. */ + char *(*path_expr_of_child) (struct varobj * child); + /* The ``struct value *'' of the root variable ROOT. */ struct value *(*value_of_root) (struct varobj ** root_handle); @@ -296,11 +327,9 @@ struct language_specific /* 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. */ @@ -311,10 +340,10 @@ static struct language_specific languages[vlang_end] = { c_number_of_children, c_name_of_variable, c_name_of_child, + c_path_expr_of_child, c_value_of_root, c_value_of_child, c_type_of_child, - c_variable_editable, c_value_of_variable} , /* C */ @@ -323,10 +352,10 @@ static struct language_specific languages[vlang_end] = { c_number_of_children, c_name_of_variable, c_name_of_child, + c_path_expr_of_child, c_value_of_root, c_value_of_child, c_type_of_child, - c_variable_editable, c_value_of_variable} , /* C++ */ @@ -335,10 +364,10 @@ static struct language_specific languages[vlang_end] = { cplus_number_of_children, cplus_name_of_variable, cplus_name_of_child, + cplus_path_expr_of_child, cplus_value_of_root, cplus_value_of_child, cplus_type_of_child, - cplus_variable_editable, cplus_value_of_variable} , /* Java */ @@ -347,10 +376,10 @@ static struct language_specific languages[vlang_end] = { java_number_of_children, java_name_of_variable, java_name_of_child, + java_path_expr_of_child, java_value_of_root, java_value_of_child, java_type_of_child, - java_variable_editable, java_value_of_variable} }; @@ -429,14 +458,15 @@ varobj_create (char *objname, { char *p; enum varobj_languages lang; - struct value *value; + struct value *value = NULL; + int expr_len; /* Parse and evaluate the expression, filling in as much of the variable's data as possible */ /* Allow creator to specify context of variable */ if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME)) - fi = deprecated_selected_frame; + fi = deprecated_safe_get_selected_frame (); else /* FIXME: cagney/2002-11-23: This code should be doing a lookup using the frame ID and not just the frame's @@ -448,7 +478,7 @@ varobj_create (char *objname, /* 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) @@ -474,28 +504,36 @@ varobj_create (char *objname, var->format = variable_default_display (var); var->root->valid_block = innermost_block; - var->name = savestring (expression, strlen (expression)); + expr_len = strlen (expression); + var->name = savestring (expression, expr_len); + /* For a root var, the name and the expr are the same. */ + var->path_expr = savestring (expression, expr_len); /* When the frame is different from the current frame, 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); - old_fi = deprecated_selected_frame; - select_frame (fi); + var->root->thread_id = pid_to_thread_id (inferior_ptid); + old_fi = get_selected_frame (NULL); + 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)) - /* Error getting the value. Try to at least get the - right type. */ - value = evaluate_type (var->root->exp); + { + /* 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->type = value_type (value); - var->type = value_type (value); install_new_value (var, value, 1 /* Initial assignment */); /* Set language info */ @@ -652,6 +690,13 @@ varobj_set_display_format (struct varobj *var, 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; } @@ -661,6 +706,39 @@ varobj_get_display_format (struct varobj *var) 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) +{ + /* When a variable is unfrozen, we don't fetch its value. + The 'not_fetched' flag remains set, so next -var-update + won't complain. + + We don't fetch the value, because for structures the client + should do -var-update anyway. It would be bad to have different + client-size logic for structure and other types. */ + var->frozen = frozen; +} + +int +varobj_get_frozen (struct varobj *var) +{ + return var->frozen; +} + + int varobj_get_num_children (struct varobj *var) { @@ -673,42 +751,28 @@ varobj_get_num_children (struct varobj *var) /* 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) { @@ -719,14 +783,9 @@ varobj_list_children (struct varobj *var, struct varobj ***childlist) 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 @@ -742,8 +801,9 @@ varobj_get_type (struct varobj *var) long length; /* For the "fake" variables, do not return a type. (It's type is - NULL, too.) */ - if (CPLUS_FAKE_CHILD (var)) + NULL, too.) + Do not return a type for invalid variables as well. */ + if (CPLUS_FAKE_CHILD (var) || !var->root->is_valid) return NULL; stb = mem_fileopen (); @@ -767,6 +827,23 @@ varobj_get_gdb_type (struct varobj *var) return var->type; } +/* Return a pointer to the full rooted expression of varobj VAR. + If it has not been computed yet, compute it. */ +char * +varobj_get_path_expr (struct varobj *var) +{ + if (var->path_expr != NULL) + return var->path_expr; + else + { + /* For root varobjs, we initialize path_expr + when creating varobj, so here it should be + child varobj. */ + gdb_assert (!is_root_p (var)); + return (*var->root->lang->path_expr_of_child) (var); + } +} + enum varobj_languages varobj_get_language (struct varobj *var) { @@ -778,17 +855,24 @@ varobj_get_attributes (struct varobj *var) { int attributes = 0; - if (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 @@ -808,55 +892,51 @@ varobj_set_value (struct varobj *var, char *expression) 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 */ @@ -906,6 +986,8 @@ install_new_value (struct varobj *var, struct value *value, int initial) int changeable; int need_to_fetch; int changed = 0; + int intentionally_not_fetched = 0; + char *print_value = NULL; /* We need to know the varobj's type to decide if the value should be fetched or not. C++ fake children (public/protected/private) don't have @@ -941,7 +1023,20 @@ install_new_value (struct varobj *var, struct value *value, int initial) will be lazy, which means we've lost that old value. */ if (need_to_fetch && value && value_lazy (value)) { - if (!gdb_value_fetch_lazy (value)) + struct varobj *parent = var->parent; + int frozen = var->frozen; + for (; !frozen && parent; parent = parent->parent) + frozen |= parent->frozen; + + if (frozen && initial) + { + /* For variables that are frozen, or are children of frozen + variables, we don't do fetch on initial assignment. + For non-initial assignemnt we do the fetch, since it means we're + explicitly asked to compare the new value with the old one. */ + intentionally_not_fetched = 1; + } + else if (!gdb_value_fetch_lazy (value)) { /* Set the value to NULL, so that for the next -var-update, we don't try to compare the new value with this value, @@ -950,12 +1045,17 @@ install_new_value (struct varobj *var, struct value *value, int initial) } } + /* Below, we'll be comparing string rendering of old and new + values. Don't get string rendering if the value is + lazy -- if it is, the code above has decided that the value + should not be fetched. */ + if (value && !value_lazy (value)) + print_value = value_get_print_value (value, var->format); + /* If the type is changeable, compare the old and the new values. If this is the initial assignment, we don't have any old value to compare with. */ - if (initial) - var->print_value = value_get_print_value (value, var->format); - else if (changeable) + if (!initial && changeable) { /* If the value of the varobj was changed by -var-set-value, then the value in the varobj and in the target is the same. However, that value @@ -963,49 +1063,51 @@ install_new_value (struct varobj *var, struct value *value, int initial) -var-update. So need to the varobj as changed. */ if (var->updated) { - xfree (var->print_value); - var->print_value = value_get_print_value (value, var->format); changed = 1; } else { /* Try to compare the values. That requires that both values are non-lazy. */ - - /* Quick comparison of NULL values. */ - if (var->value == NULL && value == NULL) + if (var->not_fetched && value_lazy (var->value)) + { + /* This is a frozen varobj and the value was never read. + Presumably, UI shows some "never read" indicator. + Now that we've fetched the real value, we need to report + this varobj as changed so that UI can show the real + value. */ + changed = 1; + } + else if (var->value == NULL && value == NULL) /* Equal. */ ; else if (var->value == NULL || value == NULL) { - xfree (var->print_value); - var->print_value = value_get_print_value (value, var->format); changed = 1; } else { - char *print_value; gdb_assert (!value_lazy (var->value)); gdb_assert (!value_lazy (value)); - print_value = value_get_print_value (value, var->format); gdb_assert (var->print_value != NULL && print_value != NULL); if (strcmp (var->print_value, print_value) != 0) - { - xfree (var->print_value); - var->print_value = print_value; - changed = 1; - } - else - xfree (print_value); + changed = 1; } } } /* We must always keep the new value, since children depend on it. */ - if (var->value != NULL) + if (var->value != NULL && var->value != value) value_free (var->value); var->value = value; + if (var->print_value) + xfree (var->print_value); + var->print_value = print_value; + if (value && value_lazy (value) && intentionally_not_fetched) + var->not_fetched = 1; + else + var->not_fetched = 0; var->updated = 0; gdb_assert (!var->value || value_type (var->value)); @@ -1018,23 +1120,25 @@ install_new_value (struct varobj *var, struct value *value, int initial) expression to see if it's changed. Then go all the way through its children, reconstructing them and noting if they've changed. - Return value: - -1 if there was an error updating the varobj - -2 if the type changed - Otherwise it is the number of children + parent changed + Return value: + < 0 for error values, see varobj.h. + Otherwise it is the number of children + parent changed. - Only root variables can be updated... + The EXPLICIT parameter specifies if this call is result + of MI request to update this specific variable, or + result of implicit -var-update *. For implicit request, we don't + update frozen variables. NOTE: This function may delete the caller's varobj. If it - returns -2, then it has done this and VARP will be modified - to point to the new varobj. */ + returns TYPE_CHANGED, then it has done this and VARP will be modified + to point to the new varobj. */ int -varobj_update (struct varobj **varp, struct varobj ***changelist) +varobj_update (struct varobj **varp, struct varobj ***changelist, + int explicit) { int changed = 0; - int error = 0; - int type_changed; + int type_changed = 0; int i; int vleft; struct varobj *v; @@ -1043,59 +1147,56 @@ varobj_update (struct varobj **varp, struct varobj ***changelist) 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 (changelist == NULL) - return -1; + /* sanity check: have we been passed a pointer? */ + gdb_assert (changelist); - /* Only root variables can be updated... */ - if (!is_root_p (*varp)) - /* Not a root var */ - return -1; - - /* Save the selected stack frame, since we will need to change it - in order to evaluate expressions. */ - old_fid = get_frame_id (deprecated_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); + /* Frozen means frozen -- we don't check for any change in + this varobj, including its going out of scope, or + changing type. One use case for frozen varobjs is + retaining previously evaluated expressions, and we don't + want them to be reevaluated at all. */ + if (!explicit && (*varp)->frozen) + return 0; - /* If this is a "use_selected_frame" varobj, and its type has changed, - them note that it's changed. */ - if (type_changed) - VEC_safe_push (varobj_p, result, *varp); + if (!(*varp)->root->is_valid) + return INVALID; - if (install_new_value ((*varp), new, type_changed)) + if ((*varp)->root->rootvar == *varp) { - /* If type_changed is 1, install_new_value will never return - non-zero, so we'll never report the same variable twice. */ - gdb_assert (!type_changed); - VEC_safe_push (varobj_p, result, *varp); - } + /* 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. */ + new = value_of_root (varp, &type_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); + + if (install_new_value ((*varp), new, type_changed)) + { + /* If type_changed is 1, install_new_value will never return + non-zero, so we'll never report the same variable twice. */ + gdb_assert (!type_changed); + VEC_safe_push (varobj_p, result, *varp); + } - if (new == NULL) - { - /* This means the varobj itself is out of scope. - Report it. */ - VEC_free (varobj_p, result); - return -1; + if (new == NULL) + { + /* This means the varobj itself is out of scope. + Report it. */ + VEC_free (varobj_p, result); + return NOT_IN_SCOPE; + } } VEC_safe_push (varobj_p, stack, *varp); - /* Walk through the children, reconstructing them all. */ + /* Walk through the children, reconstructing them all. */ while (!VEC_empty (varobj_p, stack)) { v = VEC_pop (varobj_p, stack); @@ -1108,13 +1209,13 @@ varobj_update (struct varobj **varp, struct varobj ***changelist) { varobj_p c = VEC_index (varobj_p, v->children, i); /* Child may be NULL if explicitly deleted by -var-delete. */ - if (c != NULL) + if (c != NULL && !c->frozen) VEC_safe_push (varobj_p, stack, c); } /* Update this variable, unless it's a root, which is already updated. */ - if (v != *varp) + if (v->root->rootvar != v) { new = value_of_child (v->parent, v->index); if (install_new_value (v, new, 0 /* type not changed */)) @@ -1126,7 +1227,7 @@ varobj_update (struct varobj **varp, struct varobj ***changelist) } } - /* Alloc (changed + 1) list entries */ + /* Alloc (changed + 1) list entries. */ changed = VEC_length (varobj_p, result); *changelist = xmalloc ((changed + 1) * sizeof (struct varobj *)); cv = *changelist; @@ -1139,8 +1240,11 @@ varobj_update (struct varobj **varp, struct varobj ***changelist) } *cv = 0; + VEC_free (varobj_p, stack); + VEC_free (varobj_p, result); + if (type_changed) - return -2; + return TYPE_CHANGED; else return changed; } @@ -1179,6 +1283,8 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp, 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) child->parent = NULL; delete_variable_1 (resultp, delcountp, child, 0, only_children_p); @@ -1382,6 +1488,7 @@ new_variable (void) var = (struct varobj *) xmalloc (sizeof (struct varobj)); var->name = NULL; + var->path_expr = NULL; var->obj_name = NULL; var->index = -1; var->type = NULL; @@ -1393,6 +1500,8 @@ new_variable (void) var->root = NULL; var->updated = 0; var->print_value = NULL; + var->frozen = 0; + var->not_fetched = 0; return var; } @@ -1407,8 +1516,9 @@ new_root_variable (void) 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; } @@ -1427,6 +1537,7 @@ free_variable (struct varobj *var) xfree (var->name); xfree (var->obj_name); xfree (var->print_value); + xfree (var->path_expr); xfree (var); } @@ -1600,16 +1711,15 @@ name_of_child (struct varobj *var, int index) 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) { @@ -1626,40 +1736,47 @@ 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; - old_type = varobj_get_type (var); + tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0, USE_SELECTED_FRAME); if (tmp_var == NULL) { return NULL; } + old_type = varobj_get_type (var); 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; *type_changed = 1; } + xfree (old_type); + xfree (new_type); } else { @@ -1680,19 +1797,14 @@ value_of_child (struct varobj *parent, int index) 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) { - return (*var->root->lang->value_of_variable) (var); + if (var->root->is_valid) + return (*var->root->lang->value_of_variable) (var, format); + else + return NULL; } static char * @@ -1709,13 +1821,41 @@ value_get_print_value (struct value *value, enum varobj_display_formats format) 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 @@ -1751,6 +1891,15 @@ varobj_value_is_changeable_p (struct varobj *var) 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. @@ -1761,13 +1910,21 @@ varobj_value_is_changeable_p (struct varobj *var) Both TYPE and *TYPE should be non-null. VALUE can be null if we want to only translate type. *VALUE can be null as well -- if the parent - value is not known. */ + value is not known. + + If WAS_PTR is not NULL, set *WAS_PTR to 0 or 1 + depending on whether pointer was deferenced + in this function. */ static void adjust_value_for_child_access (struct value **value, - struct type **type) + struct type **type, + int *was_ptr) { gdb_assert (type && *type); + if (was_ptr) + *was_ptr = 0; + *type = check_typedef (*type); /* The type of value stored in varobj, that is passed @@ -1786,8 +1943,14 @@ adjust_value_for_child_access (struct value **value, || 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; } } @@ -1804,7 +1967,7 @@ c_number_of_children (struct varobj *var) int children = 0; struct type *target; - adjust_value_for_child_access (NULL, &type); + adjust_value_for_child_access (NULL, &type, NULL); target = get_target_type (type); switch (TYPE_CODE (type)) @@ -1900,10 +2063,13 @@ value_struct_element_index (struct value *value, int type_index) to NULL. */ static void c_describe_child (struct varobj *parent, int index, - char **cname, struct value **cvalue, struct type **ctype) + char **cname, struct value **cvalue, struct type **ctype, + char **cfull_expression) { struct value *value = parent->value; struct type *type = get_value_type (parent); + char *parent_expression = NULL; + int was_ptr; if (cname) *cname = NULL; @@ -1911,8 +2077,12 @@ c_describe_child (struct varobj *parent, int index, *cvalue = NULL; if (ctype) *ctype = NULL; - - adjust_value_for_child_access (&value, &type); + if (cfull_expression) + { + *cfull_expression = NULL; + parent_expression = varobj_get_path_expr (parent); + } + adjust_value_for_child_access (&value, &type, &was_ptr); switch (TYPE_CODE (type)) { @@ -1932,6 +2102,12 @@ c_describe_child (struct varobj *parent, int index, if (ctype) *ctype = get_target_type (type); + if (cfull_expression) + *cfull_expression = xstrprintf ("(%s)[%d]", parent_expression, + index + + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type))); + + break; case TYPE_CODE_STRUCT: @@ -1951,6 +2127,13 @@ c_describe_child (struct varobj *parent, int index, if (ctype) *ctype = TYPE_FIELD_TYPE (type, index); + if (cfull_expression) + { + char *join = was_ptr ? "->" : "."; + *cfull_expression = xstrprintf ("(%s)%s%s", parent_expression, join, + TYPE_FIELD_NAME (type, index)); + } + break; case TYPE_CODE_PTR: @@ -1958,13 +2141,20 @@ c_describe_child (struct varobj *parent, int index, *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 declared type of the variable. */ if (ctype) *ctype = TYPE_TARGET_TYPE (type); + + if (cfull_expression) + *cfull_expression = xstrprintf ("*(%s)", parent_expression); break; @@ -1972,6 +2162,8 @@ c_describe_child (struct varobj *parent, int index, /* This should not happen */ if (cname) *cname = xstrdup ("???"); + if (cfull_expression) + *cfull_expression = xstrdup ("???"); /* Don't set value and type, we don't know then. */ } } @@ -1980,56 +2172,89 @@ static char * c_name_of_child (struct varobj *parent, int index) { char *name; - c_describe_child (parent, index, &name, NULL, NULL); + c_describe_child (parent, index, &name, NULL, NULL, NULL); return name; } +static char * +c_path_expr_of_child (struct varobj *child) +{ + c_describe_child (child->parent, child->index, NULL, NULL, NULL, + &child->path_expr); + 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) { /* We need to catch errors here, because if evaluate - expression fails we just want to make val->error = 1 and - go on */ - if (gdb_evaluate_expression (var->root->exp, &new_val)) - { - release_value (new_val); - } - + expression fails we want to just return NULL. */ + gdb_evaluate_expression (var->root->exp, &new_val); return new_val; } + do_cleanups (back_to); + return NULL; } @@ -2037,9 +2262,7 @@ static struct value * c_value_of_child (struct varobj *parent, int index) { struct value *value = NULL; - c_describe_child (parent, index, NULL, &value, NULL); - if (value != NULL) - release_value (value); + c_describe_child (parent, index, NULL, &value, NULL, NULL); return value; } @@ -2048,31 +2271,12 @@ static struct type * c_type_of_child (struct varobj *parent, int index) { struct type *type = NULL; - c_describe_child (parent, index, NULL, NULL, &type); + c_describe_child (parent, index, NULL, NULL, &type, 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 @@ -2109,9 +2313,21 @@ c_value_of_variable (struct varobj *var) } else { + if (var->not_fetched && value_lazy (var->value)) + /* Frozen variable and no value yet. We don't + implicitly fetch the value. MI response will + use empty string for the value, which is OK. */ + return NULL; + 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); } } } @@ -2132,7 +2348,7 @@ cplus_number_of_children (struct varobj *var) if (!CPLUS_FAKE_CHILD (var)) { type = get_value_type (var); - adjust_value_for_child_access (NULL, &type); + adjust_value_for_child_access (NULL, &type, NULL); if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) || ((TYPE_CODE (type)) == TYPE_CODE_UNION)) @@ -2159,7 +2375,7 @@ cplus_number_of_children (struct varobj *var) int kids[3]; type = get_value_type (var->parent); - adjust_value_for_child_access (NULL, &type); + adjust_value_for_child_access (NULL, &type, NULL); cplus_class_num_children (type, kids); if (strcmp (var->name, "public") == 0) @@ -2230,11 +2446,14 @@ match_accessibility (struct type *type, int index, enum accessibility acc) static void cplus_describe_child (struct varobj *parent, int index, - char **cname, struct value **cvalue, struct type **ctype) + char **cname, struct value **cvalue, struct type **ctype, + char **cfull_expression) { - char *name = 0; + char *name = NULL; struct value *value; struct type *type; + int was_ptr; + char *parent_expression = NULL; if (cname) *cname = NULL; @@ -2242,24 +2461,30 @@ cplus_describe_child (struct varobj *parent, int index, *cvalue = NULL; if (ctype) *ctype = NULL; - + if (cfull_expression) + *cfull_expression = NULL; if (CPLUS_FAKE_CHILD (parent)) { value = parent->parent->value; type = get_value_type (parent->parent); + if (cfull_expression) + parent_expression = varobj_get_path_expr (parent->parent); } else { value = parent->value; type = get_value_type (parent); + if (cfull_expression) + parent_expression = varobj_get_path_expr (parent); } - adjust_value_for_child_access (&value, &type); + 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)) { /* The fields of the class type are ordered as they @@ -2294,6 +2519,11 @@ cplus_describe_child (struct varobj *parent, int index, if (ctype) *ctype = TYPE_FIELD_TYPE (type, type_index); + + if (cfull_expression) + *cfull_expression = xstrprintf ("((%s)%s%s)", parent_expression, + join, + TYPE_FIELD_NAME (type, type_index)); } else if (index < TYPE_N_BASECLASSES (type)) { @@ -2311,10 +2541,27 @@ cplus_describe_child (struct varobj *parent, int index, { *ctype = TYPE_FIELD_TYPE (type, index); } + + if (cfull_expression) + { + char *ptr = was_ptr ? "*" : ""; + /* Cast the parent to the base' type. Note that in gdb, + expression like + (Base1)d + will create an lvalue, for all appearences, so we don't + need to use more fancy: + *(Base1*)(&d) + construct. */ + *cfull_expression = xstrprintf ("(%s(%s%s) %s)", + ptr, + TYPE_FIELD_NAME (type, index), + ptr, + parent_expression); + } } else { - char *access = 0; + char *access = NULL; int children[3]; cplus_class_num_children (type, children); @@ -2353,16 +2600,17 @@ cplus_describe_child (struct varobj *parent, int index, /* error! */ break; } - + + gdb_assert (access); if (cname) *cname = xstrdup (access); - /* Value and type are null here. */ + /* Value and type and full expression are null here. */ } } else { - c_describe_child (parent, index, cname, cvalue, ctype); + c_describe_child (parent, index, cname, cvalue, ctype, cfull_expression); } } @@ -2370,10 +2618,18 @@ static char * cplus_name_of_child (struct varobj *parent, int index) { char *name = NULL; - cplus_describe_child (parent, index, &name, NULL, NULL); + cplus_describe_child (parent, index, &name, NULL, NULL, NULL); return name; } +static char * +cplus_path_expr_of_child (struct varobj *child) +{ + cplus_describe_child (child->parent, child->index, NULL, NULL, NULL, + &child->path_expr); + return child->path_expr; +} + static struct value * cplus_value_of_root (struct varobj **var_handle) { @@ -2384,7 +2640,7 @@ static struct value * cplus_value_of_child (struct varobj *parent, int index) { struct value *value = NULL; - cplus_describe_child (parent, index, NULL, &value, NULL); + cplus_describe_child (parent, index, NULL, &value, NULL, NULL); return value; } @@ -2392,21 +2648,12 @@ static struct type * cplus_type_of_child (struct varobj *parent, int index) { struct type *type = NULL; - cplus_describe_child (parent, index, NULL, NULL, &type); + cplus_describe_child (parent, index, NULL, NULL, &type, NULL); 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 @@ -2414,7 +2661,7 @@ cplus_value_of_variable (struct varobj *var) if (CPLUS_FAKE_CHILD (var)) return xstrdup (""); - return c_value_of_variable (var); + return c_value_of_variable (var, format); } /* Java */ @@ -2464,6 +2711,12 @@ java_name_of_child (struct varobj *parent, int index) return name; } +static char * +java_path_expr_of_child (struct varobj *child) +{ + return NULL; +} + static struct value * java_value_of_root (struct varobj **var_handle) { @@ -2482,16 +2735,10 @@ java_type_of_child (struct varobj *parent, int index) 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); } extern void _initialize_varobj (void); @@ -2512,3 +2759,49 @@ When non-zero, varobj debugging is enabled."), show_varobjdebug, &setlist, &showlist); } + +/* Invalidate the varobjs that are tied to locals and re-create the ones that + are defined on globals. + Invalidated varobjs will be always printed in_scope="invalid". */ +void +varobj_invalidate (void) +{ + struct varobj **all_rootvarobj; + struct varobj **varp; + + if (varobj_list (&all_rootvarobj) > 0) + { + 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) + { + struct varobj *tmp_var; + + /* Try to create a varobj with same expression. If we succeed replace + the old varobj, otherwise invalidate it. */ + tmp_var = varobj_create (NULL, (*varp)->name, (CORE_ADDR) 0, USE_CURRENT_FRAME); + if (tmp_var != NULL) + { + tmp_var->obj_name = xstrdup ((*varp)->obj_name); + varobj_delete (*varp, NULL, 0); + install_variable (tmp_var); + } + else + (*varp)->root->is_valid = 0; + } + else /* locals must be invalidated. */ + (*varp)->root->is_valid = 0; + + varp++; + } + xfree (all_rootvarobj); + } + return; +}