X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fvarobj.c;h=f3d3b5abef637cb1fe7f2673aea4a6546770c035;hb=ebd3bcc1327e6a7de6daf6536134cb20be9c2cfd;hp=d6125c6e448fe896378e0e44801d1133c3c2b586;hpb=7a4d50bfe016959b5bb6e11433b0d38899c02458;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/varobj.c b/gdb/varobj.c index d6125c6e44..f3d3b5abef 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -1,6 +1,6 @@ /* 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 @@ -31,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. */ @@ -62,12 +64,21 @@ 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. */ @@ -83,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. */ @@ -221,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); @@ -248,9 +254,8 @@ 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 */ @@ -270,9 +275,8 @@ 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 */ @@ -290,9 +294,8 @@ 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 */ @@ -324,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. */ @@ -343,7 +344,6 @@ static struct language_specific languages[vlang_end] = { c_value_of_root, c_value_of_child, c_type_of_child, - c_variable_editable, c_value_of_variable} , /* C */ @@ -356,7 +356,6 @@ static struct language_specific languages[vlang_end] = { c_value_of_root, c_value_of_child, c_type_of_child, - c_variable_editable, c_value_of_variable} , /* C++ */ @@ -369,7 +368,6 @@ static struct language_specific languages[vlang_end] = { cplus_value_of_root, cplus_value_of_child, cplus_type_of_child, - cplus_variable_editable, cplus_value_of_variable} , /* Java */ @@ -382,7 +380,6 @@ static struct language_specific languages[vlang_end] = { java_value_of_root, java_value_of_child, java_type_of_child, - java_variable_editable, java_value_of_variable} }; @@ -481,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) @@ -516,14 +513,15 @@ varobj_create (char *objname, 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)) @@ -692,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; } @@ -701,6 +706,19 @@ 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) { @@ -733,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) { @@ -779,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 @@ -856,17 +855,24 @@ varobj_get_attributes (struct varobj *var) { 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 @@ -886,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 */ @@ -1145,7 +1147,6 @@ 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? */ @@ -1164,24 +1165,14 @@ varobj_update (struct varobj **varp, struct varobj ***changelist, 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); @@ -1292,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); @@ -1523,7 +1516,7 @@ 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; @@ -1718,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) { @@ -1744,7 +1736,7 @@ 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; @@ -1759,21 +1751,25 @@ value_of_root (struct varobj **var_handle, int *type_changed) 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; @@ -1801,20 +1797,12 @@ 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) { 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; } @@ -1840,6 +1828,33 @@ value_get_print_value (struct value *value, enum varobj_display_formats format) 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 @@ -1875,6 +1890,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. @@ -1918,7 +1942,11 @@ 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; @@ -2112,7 +2140,11 @@ 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 @@ -2151,37 +2183,65 @@ c_path_expr_of_child (struct varobj *child) 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) @@ -2192,6 +2252,8 @@ c_value_of_root (struct varobj **var_handle) return new_val; } + do_cleanups (back_to); + return NULL; } @@ -2212,27 +2274,8 @@ c_type_of_child (struct varobj *parent, int index) 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 @@ -2277,7 +2320,13 @@ c_value_of_variable (struct varobj *var) 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); } } } @@ -2432,7 +2481,7 @@ cplus_describe_child (struct varobj *parent, int index, 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)) @@ -2602,17 +2651,8 @@ cplus_type_of_child (struct varobj *parent, int index) 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 @@ -2620,7 +2660,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 */ @@ -2694,16 +2734,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); @@ -2739,6 +2773,11 @@ varobj_invalidate (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) {