X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fvarobj.c;h=c4d02c96c5e1bdfe41c7f10bc06949e54af463b2;hb=3c0ee1a46468d89b8865cd70616af4558c499b16;hp=54c2a02efdf3d75c0fc3730d1dc5923bf9c59381;hpb=61d8f2758f5881aa0138e31b45105515e98eb715;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/varobj.c b/gdb/varobj.c index 54c2a02efd..c4d02c96c5 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -1,7 +1,7 @@ /* Implementation of the GDB variable objects API. Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009 Free Software Foundation, Inc. + 2009, 2010 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,12 +29,20 @@ #include "gdb_assert.h" #include "gdb_string.h" +#include "gdb_regex.h" #include "varobj.h" #include "vec.h" #include "gdbthread.h" #include "inferior.h" +#if HAVE_PYTHON +#include "python/python.h" +#include "python/python-internal.h" +#else +typedef int PyObject; +#endif + /* Non-zero if we want to see trace of varobj level stuff. */ int varobjdebug = 0; @@ -52,6 +60,15 @@ char *varobj_format_string[] = /* String representations of gdb's known languages */ char *varobj_language_string[] = { "unknown", "C", "C++", "Java" }; +/* True if we want to allow Python-based pretty-printing. */ +static int pretty_printing = 0; + +void +varobj_enable_pretty_printing (void) +{ + pretty_printing = 1; +} + /* Data structures */ /* Every root variable has one of these structures saved in its @@ -138,6 +155,12 @@ struct varobj /* Children of this object. */ VEC (varobj_p) *children; + /* Whether the children of this varobj were requested. This field is + used to decide if dynamic varobj should recompute their children. + In the event that the frontend never asked for the children, we + can avoid that. */ + int children_requested; + /* Description of the root variable. Points to root variable for children. */ struct varobj_root *root; @@ -159,6 +182,32 @@ struct varobj not fetched if either the variable is frozen, or any parents is frozen. */ int not_fetched; + + /* Sub-range of children which the MI consumer has requested. If + FROM < 0 or TO < 0, means that all children have been + requested. */ + int from; + int to; + + /* The pretty-printer constructor. If NULL, then the default + pretty-printer will be looked up. If None, then no + pretty-printer will be installed. */ + PyObject *constructor; + + /* The pretty-printer that has been constructed. If NULL, then a + new printer object is needed, and one will be constructed. */ + PyObject *pretty_printer; + + /* The iterator returned by the printer's 'children' method, or NULL + if not available. */ + PyObject *child_iter; + + /* We request one extra item from the iterator, so that we can + report to the caller whether there are more items than we have + already reported. However, we don't want to install this value + when we read it, because that will mess up future updates. So, + we stash it here instead. */ + PyObject *saved_item; }; struct cpstack @@ -190,6 +239,10 @@ static void uninstall_variable (struct varobj *); static struct varobj *create_child (struct varobj *, int, char *); +static struct varobj * +create_child_with_value (struct varobj *parent, int index, const char *name, + struct value *value); + /* Utility routines */ static struct varobj *new_variable (void); @@ -233,12 +286,20 @@ 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); + enum varobj_display_formats format, + struct varobj *var); static int varobj_value_is_changeable_p (struct varobj *var); static int is_root_p (struct varobj *var); +#if HAVE_PYTHON + +static struct varobj * +varobj_add_child (struct varobj *var, const char *name, struct value *value); + +#endif /* HAVE_PYTHON */ + /* C implementation */ static int c_number_of_children (struct varobj *var); @@ -397,7 +458,6 @@ static int format_code[] = { 0, 't', 'd', 'x', 'o' }; /* Header of the list of root variable objects */ static struct varobj_root *rootlist; -static int rootcount = 0; /* number of root varobjs in the list */ /* Prime number indicating the number of buckets in the hash table */ /* A prime large enough to avoid too many colisions */ @@ -418,6 +478,17 @@ is_root_p (struct varobj *var) return (var->root->rootvar == var); } +#ifdef HAVE_PYTHON +/* Helper function to install a Python environment suitable for + use during operations on VAR. */ +struct cleanup * +varobj_ensure_python_env (struct varobj *var) +{ + return ensure_python_env (var->root->exp->gdbarch, + var->root->exp->language_defn); +} +#endif + /* Creates a varobj (not its children) */ /* Return the full FRAME which corresponds to the given CORE_ADDR @@ -435,7 +506,16 @@ find_frame_addr_in_frame_chain (CORE_ADDR frame_addr) frame != NULL; frame = get_prev_frame (frame)) { - if (get_frame_base_address (frame) == frame_addr) + /* The CORE_ADDR we get as argument was parsed from a string GDB + output as $fp. This output got truncated to gdbarch_addr_bit. + Truncate the frame base address in the same manner before + comparing it against our argument. */ + CORE_ADDR frame_base = get_frame_base_address (frame); + int addr_bit = gdbarch_addr_bit (get_frame_arch (frame)); + if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT)) + frame_base &= ((CORE_ADDR) 1 << addr_bit) - 1; + + if (frame_base == frame_addr) return frame; } @@ -461,7 +541,6 @@ varobj_create (char *objname, char *p; enum varobj_languages lang; struct value *value = NULL; - int expr_len; /* Parse and evaluate the expression, filling in as much of the variable's data as possible. */ @@ -512,17 +591,23 @@ varobj_create (char *objname, var->format = variable_default_display (var); var->root->valid_block = innermost_block; - expr_len = strlen (expression); - var->name = savestring (expression, expr_len); + var->name = xstrdup (expression); /* For a root var, the name and the expr are the same. */ - var->path_expr = savestring (expression, expr_len); + var->path_expr = xstrdup (expression); /* 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 (innermost_block && fi != NULL) + if (innermost_block) { + /* User could specify explicit FRAME-ADDR which was not found but + EXPRESSION is frame specific and we would not be able to evaluate + it correctly next time. With VALID_BLOCK set we must also set + FRAME and THREAD_ID. */ + if (fi == NULL) + error (_("Failed to find the specified frame")); + var->root->frame = get_frame_id (fi); var->root->thread_id = pid_to_thread_id (inferior_ptid); old_fi = get_selected_frame (NULL); @@ -552,7 +637,7 @@ varobj_create (char *objname, var->root->rootvar = var; /* Reset the selected frame */ - if (fi != NULL) + if (old_fi != NULL) select_frame (old_fi); } @@ -561,7 +646,7 @@ varobj_create (char *objname, if ((var != NULL) && (objname != NULL)) { - var->obj_name = savestring (objname, strlen (objname)); + var->obj_name = xstrdup (objname); /* If a varobj name is duplicated, the install will fail so we must clenup */ @@ -678,6 +763,28 @@ varobj_delete (struct varobj *var, char ***dellist, int only_children) return delcount; } +#if HAVE_PYTHON + +/* Convenience function for varobj_set_visualizer. Instantiate a + pretty-printer for a given value. */ +static PyObject * +instantiate_pretty_printer (PyObject *constructor, struct value *value) +{ + PyObject *val_obj = NULL; + PyObject *printer; + + val_obj = value_to_value_object (value); + if (! val_obj) + return NULL; + + printer = PyObject_CallFunctionObjArgs (constructor, val_obj, NULL); + Py_DECREF (val_obj); + return printer; + return NULL; +} + +#endif + /* Set/Get variable object display format */ enum varobj_display_formats @@ -702,7 +809,7 @@ varobj_set_display_format (struct varobj *var, && var->value && !value_lazy (var->value)) { xfree (var->print_value); - var->print_value = value_get_print_value (var->value, var->format); + var->print_value = value_get_print_value (var->value, var->format, var); } return var->format; @@ -714,6 +821,34 @@ varobj_get_display_format (struct varobj *var) return var->format; } +char * +varobj_get_display_hint (struct varobj *var) +{ + char *result = NULL; + +#if HAVE_PYTHON + struct cleanup *back_to = varobj_ensure_python_env (var); + + if (var->pretty_printer) + result = gdbpy_get_display_hint (var->pretty_printer); + + do_cleanups (back_to); +#endif + + return result; +} + +/* Return true if the varobj has items after TO, false otherwise. */ + +int +varobj_has_more (struct varobj *var, int to) +{ + if (VEC_length (varobj_p, var->children) > to) + return 1; + return ((to == -1 || VEC_length (varobj_p, var->children) == to) + && var->saved_item != NULL); +} + /* 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 @@ -746,25 +881,257 @@ varobj_get_frozen (struct varobj *var) return var->frozen; } +/* A helper function that restricts a range to what is actually + available in a VEC. This follows the usual rules for the meaning + of FROM and TO -- if either is negative, the entire range is + used. */ + +static void +restrict_range (VEC (varobj_p) *children, int *from, int *to) +{ + if (*from < 0 || *to < 0) + { + *from = 0; + *to = VEC_length (varobj_p, children); + } + else + { + if (*from > VEC_length (varobj_p, children)) + *from = VEC_length (varobj_p, children); + if (*to > VEC_length (varobj_p, children)) + *to = VEC_length (varobj_p, children); + if (*from > *to) + *from = *to; + } +} + +#if HAVE_PYTHON + +/* A helper for update_dynamic_varobj_children that installs a new + child when needed. */ + +static void +install_dynamic_child (struct varobj *var, + VEC (varobj_p) **changed, + VEC (varobj_p) **new, + VEC (varobj_p) **unchanged, + int *cchanged, + int index, + const char *name, + struct value *value) +{ + if (VEC_length (varobj_p, var->children) < index + 1) + { + /* There's no child yet. */ + struct varobj *child = varobj_add_child (var, name, value); + if (new) + { + VEC_safe_push (varobj_p, *new, child); + *cchanged = 1; + } + } + else + { + varobj_p existing = VEC_index (varobj_p, var->children, index); + if (install_new_value (existing, value, 0)) + { + if (changed) + VEC_safe_push (varobj_p, *changed, existing); + } + else if (unchanged) + VEC_safe_push (varobj_p, *unchanged, existing); + } +} + +static int +dynamic_varobj_has_child_method (struct varobj *var) +{ + struct cleanup *back_to; + PyObject *printer = var->pretty_printer; + int result; + + back_to = varobj_ensure_python_env (var); + result = PyObject_HasAttr (printer, gdbpy_children_cst); + do_cleanups (back_to); + return result; +} + +#endif + +static int +update_dynamic_varobj_children (struct varobj *var, + VEC (varobj_p) **changed, + VEC (varobj_p) **new, + VEC (varobj_p) **unchanged, + int *cchanged, + int update_children, + int from, + int to) +{ +#if HAVE_PYTHON + struct cleanup *back_to; + PyObject *children; + int i; + PyObject *printer = var->pretty_printer; + + back_to = varobj_ensure_python_env (var); + + *cchanged = 0; + if (!PyObject_HasAttr (printer, gdbpy_children_cst)) + { + do_cleanups (back_to); + return 0; + } + + if (update_children || !var->child_iter) + { + children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst, + NULL); + + if (!children) + { + gdbpy_print_stack (); + error (_("Null value returned for children")); + } + + make_cleanup_py_decref (children); + + if (!PyIter_Check (children)) + error (_("Returned value is not iterable")); + + Py_XDECREF (var->child_iter); + var->child_iter = PyObject_GetIter (children); + if (!var->child_iter) + { + gdbpy_print_stack (); + error (_("Could not get children iterator")); + } + + Py_XDECREF (var->saved_item); + var->saved_item = NULL; + + i = 0; + } + else + i = VEC_length (varobj_p, var->children); + + /* We ask for one extra child, so that MI can report whether there + are more children. */ + for (; to < 0 || i < to + 1; ++i) + { + PyObject *item; + + /* See if there was a leftover from last time. */ + if (var->saved_item) + { + item = var->saved_item; + var->saved_item = NULL; + } + else + item = PyIter_Next (var->child_iter); + + if (!item) + break; + + /* We don't want to push the extra child on any report list. */ + if (to < 0 || i < to) + { + PyObject *py_v; + char *name; + struct value *v; + struct cleanup *inner; + int can_mention = from < 0 || i >= from; + + inner = make_cleanup_py_decref (item); + + if (!PyArg_ParseTuple (item, "sO", &name, &py_v)) + error (_("Invalid item from the child list")); + + v = convert_value_from_python (py_v); + install_dynamic_child (var, can_mention ? changed : NULL, + can_mention ? new : NULL, + can_mention ? unchanged : NULL, + can_mention ? cchanged : NULL, i, name, v); + do_cleanups (inner); + } + else + { + Py_XDECREF (var->saved_item); + var->saved_item = item; + + /* We want to truncate the child list just before this + element. */ + break; + } + } + + if (i < VEC_length (varobj_p, var->children)) + { + int j; + *cchanged = 1; + for (j = i; j < VEC_length (varobj_p, var->children); ++j) + varobj_delete (VEC_index (varobj_p, var->children, j), NULL, 0); + VEC_truncate (varobj_p, var->children, i); + } + + /* If there are fewer children than requested, note that the list of + children changed. */ + if (to >= 0 && VEC_length (varobj_p, var->children) < to) + *cchanged = 1; + + var->num_children = VEC_length (varobj_p, var->children); + + do_cleanups (back_to); + + return 1; +#else + gdb_assert (0 && "should never be called if Python is not enabled"); +#endif +} int varobj_get_num_children (struct varobj *var) { if (var->num_children == -1) - var->num_children = number_of_children (var); + { + if (var->pretty_printer) + { + int dummy; + + /* If we have a dynamic varobj, don't report -1 children. + So, try to fetch some children first. */ + update_dynamic_varobj_children (var, NULL, NULL, NULL, &dummy, + 0, 0, 0); + } + else + var->num_children = number_of_children (var); + } - return var->num_children; + return var->num_children >= 0 ? var->num_children : 0; } /* Creates a list of the immediate children of a variable object; the return code is the number of such children or -1 on error */ VEC (varobj_p)* -varobj_list_children (struct varobj *var) +varobj_list_children (struct varobj *var, int *from, int *to) { struct varobj *child; char *name; - int i; + int i, children_changed; + + var->children_requested = 1; + + if (var->pretty_printer) + { + /* This, in theory, can result in the number of children changing without + frontend noticing. But well, calling -var-list-children on the same + varobj twice is not something a sane frontend would do. */ + update_dynamic_varobj_children (var, NULL, NULL, NULL, &children_changed, + 0, 0, *to); + restrict_range (var->children, from, to); + return var->children; + } if (var->num_children == -1) var->num_children = number_of_children (var); @@ -793,38 +1160,37 @@ varobj_list_children (struct varobj *var) } } + restrict_range (var->children, from, to); return var->children; } +#if HAVE_PYTHON + +static struct varobj * +varobj_add_child (struct varobj *var, const char *name, struct value *value) +{ + varobj_p v = create_child_with_value (var, + VEC_length (varobj_p, var->children), + name, value); + VEC_safe_push (varobj_p, var->children, v); + return v; +} + +#endif /* HAVE_PYTHON */ + /* Obtain the type of an object Variable as a string similar to the one gdb prints on the console */ char * varobj_get_type (struct varobj *var) { - struct value *val; - struct cleanup *old_chain; - struct ui_file *stb; - char *thetype; - long length; - /* For the "fake" variables, do not return a type. (It's type is 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 (); - old_chain = make_cleanup_ui_file_delete (stb); - - /* To print the type, we simply create a zero ``struct value *'' and - cast it to our type. We then typeprint this variable. */ - val = value_zero (var->type, not_lval); - type_print (value_type (val), "", stb, -1); - - thetype = ui_file_xstrdup (stb, &length); - do_cleanups (old_chain); - return thetype; + return type_to_string (var->type); } /* Obtain the type of an object variable. */ @@ -870,6 +1236,12 @@ varobj_get_attributes (struct varobj *var) return attributes; } +int +varobj_pretty_printed_p (struct varobj *var) +{ + return var->pretty_printer != NULL; +} + char * varobj_get_formatted_value (struct varobj *var, enum varobj_display_formats format) @@ -947,35 +1319,114 @@ varobj_set_value (struct varobj *var, char *expression) return 1; } -/* Returns a malloc'ed list with all root variable objects */ -int -varobj_list (struct varobj ***varlist) +#if HAVE_PYTHON + +/* A helper function to install a constructor function and visualizer + in a varobj. */ + +static void +install_visualizer (struct varobj *var, PyObject *constructor, + PyObject *visualizer) { - struct varobj **cv; - struct varobj_root *croot; - int mycount = rootcount; + Py_XDECREF (var->constructor); + var->constructor = constructor; + + Py_XDECREF (var->pretty_printer); + var->pretty_printer = visualizer; + + Py_XDECREF (var->child_iter); + var->child_iter = NULL; +} + +/* Install the default visualizer for VAR. */ + +static void +install_default_visualizer (struct varobj *var) +{ + if (pretty_printing) + { + PyObject *pretty_printer = NULL; + + if (var->value) + { + pretty_printer = gdbpy_get_varobj_pretty_printer (var->value); + if (! pretty_printer) + { + gdbpy_print_stack (); + error (_("Cannot instantiate printer for default visualizer")); + } + } + + if (pretty_printer == Py_None) + { + Py_DECREF (pretty_printer); + pretty_printer = NULL; + } + + install_visualizer (var, NULL, pretty_printer); + } +} + +/* Instantiate and install a visualizer for VAR using CONSTRUCTOR to + make a new object. */ - /* Alloc (rootcount + 1) entries for the result */ - *varlist = xmalloc ((rootcount + 1) * sizeof (struct varobj *)); +static void +construct_visualizer (struct varobj *var, PyObject *constructor) +{ + PyObject *pretty_printer; - cv = *varlist; - croot = rootlist; - while ((croot != NULL) && (mycount > 0)) + Py_INCREF (constructor); + if (constructor == Py_None) + pretty_printer = NULL; + else { - *cv = croot->rootvar; - mycount--; - cv++; - croot = croot->next; + pretty_printer = instantiate_pretty_printer (constructor, var->value); + if (! pretty_printer) + { + gdbpy_print_stack (); + Py_DECREF (constructor); + constructor = Py_None; + Py_INCREF (constructor); + } + + if (pretty_printer == Py_None) + { + Py_DECREF (pretty_printer); + pretty_printer = NULL; + } } - /* Mark the end of the list */ - *cv = NULL; - if (mycount || (croot != NULL)) - warning - ("varobj_list: assertion failed - wrong tally of root vars (%d:%d)", - rootcount, mycount); + install_visualizer (var, constructor, pretty_printer); +} + +#endif /* HAVE_PYTHON */ + +/* A helper function for install_new_value. This creates and installs + a visualizer for VAR, if appropriate. */ - return rootcount; +static void +install_new_value_visualizer (struct varobj *var) +{ +#if HAVE_PYTHON + /* If the constructor is None, then we want the raw value. If VAR + does not have a value, just skip this. */ + if (var->constructor != Py_None && var->value) + { + struct cleanup *cleanup; + PyObject *pretty_printer = NULL; + + cleanup = varobj_ensure_python_env (var); + + if (!var->constructor) + install_default_visualizer (var); + else + construct_visualizer (var, var->constructor); + + do_cleanups (cleanup); + } +#else + /* Do nothing. */ +#endif } /* Assign a new value to a variable object. If INITIAL is non-zero, @@ -1005,16 +1456,20 @@ install_new_value (struct varobj *var, struct value *value, int initial) a type. */ gdb_assert (var->type || CPLUS_FAKE_CHILD (var)); changeable = varobj_value_is_changeable_p (var); + + /* If the type has custom visualizer, we consider it to be always + changeable. FIXME: need to make sure this behaviour will not + mess up read-sensitive values. */ + if (var->pretty_printer) + changeable = 1; + need_to_fetch = changeable; /* We are not interested in the address of references, and given that in C++ a reference is not rebindable, it cannot meaningfully change. So, get hold of the real value. */ if (value) - { - value = coerce_ref (value); - release_value (value); - } + value = coerce_ref (value); if (var->type && TYPE_CODE (var->type) == TYPE_CODE_UNION) /* For unions, we need to fetch the value implicitly because @@ -1056,12 +1511,13 @@ 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 (value && !value_lazy (value) && !var->pretty_printer) + print_value = value_get_print_value (value, var->format, var); /* 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 @@ -1076,7 +1532,7 @@ install_new_value (struct varobj *var, struct value *value, int initial) { changed = 1; } - else + else if (! var->pretty_printer) { /* Try to compare the values. That requires that both values are non-lazy. */ @@ -1121,20 +1577,93 @@ install_new_value (struct varobj *var, struct value *value, int initial) 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 != NULL) + value_incref (value); if (value && value_lazy (value) && intentionally_not_fetched) var->not_fetched = 1; else var->not_fetched = 0; var->updated = 0; + install_new_value_visualizer (var); + + /* If we installed a pretty-printer, re-compare the printed version + to see if the variable changed. */ + if (var->pretty_printer) + { + xfree (print_value); + print_value = value_get_print_value (var->value, var->format, var); + if ((var->print_value == NULL && print_value != NULL) + || (var->print_value != NULL && print_value == NULL) + || (var->print_value != NULL && print_value != NULL + && strcmp (var->print_value, print_value) != 0)) + changed = 1; + } + if (var->print_value) + xfree (var->print_value); + var->print_value = print_value; + gdb_assert (!var->value || value_type (var->value)); return changed; } +/* Return the requested range for a varobj. VAR is the varobj. FROM + and TO are out parameters; *FROM and *TO will be set to the + selected sub-range of VAR. If no range was selected using + -var-set-update-range, then both will be -1. */ +void +varobj_get_child_range (struct varobj *var, int *from, int *to) +{ + *from = var->from; + *to = var->to; +} + +/* Set the selected sub-range of children of VAR to start at index + FROM and end at index TO. If either FROM or TO is less than zero, + this is interpreted as a request for all children. */ +void +varobj_set_child_range (struct varobj *var, int from, int to) +{ + var->from = from; + var->to = to; +} + +void +varobj_set_visualizer (struct varobj *var, const char *visualizer) +{ +#if HAVE_PYTHON + PyObject *mainmod, *globals, *pretty_printer, *constructor; + struct cleanup *back_to, *value; + + back_to = varobj_ensure_python_env (var); + + mainmod = PyImport_AddModule ("__main__"); + globals = PyModule_GetDict (mainmod); + Py_INCREF (globals); + make_cleanup_py_decref (globals); + + constructor = PyRun_String (visualizer, Py_eval_input, globals, globals); + + if (! constructor) + { + gdbpy_print_stack (); + error (_("Could not evaluate visualizer expression: %s"), visualizer); + } + + construct_visualizer (var, constructor); + Py_XDECREF (constructor); + + /* If there are any children now, wipe them. */ + varobj_delete (var, NULL, 1 /* children only */); + var->num_children = -1; + + do_cleanups (back_to); +#else + error (_("Python support required")); +#endif +} + /* Update the values for a variable and its children. This is a two-pronged attack. First, re-parse the value for the root's expression to see if it's changed. Then go all the way @@ -1160,7 +1689,7 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) struct varobj **cv; struct varobj **templist = NULL; struct value *new; - VEC (varobj_p) *stack = NULL; + VEC (varobj_update_result) *stack = NULL; VEC (varobj_update_result) *result = NULL; struct frame_info *fi; @@ -1174,7 +1703,8 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) if (!(*varp)->root->is_valid) { - varobj_update_result r = {*varp}; + varobj_update_result r = {0}; + r.varobj = *varp; r.status = VAROBJ_INVALID; VEC_safe_push (varobj_update_result, result, &r); return result; @@ -1182,7 +1712,8 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) if ((*varp)->root->rootvar == *varp) { - varobj_update_result r = {*varp}; + varobj_update_result r = {0}; + r.varobj = *varp; r.status = VAROBJ_IN_SCOPE; /* Update the root variable. value_of_root can return NULL @@ -1199,20 +1730,125 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) if (new == NULL) r.status = VAROBJ_NOT_IN_SCOPE; - - if (r.type_changed || r.changed) - VEC_safe_push (varobj_update_result, result, &r); + r.value_installed = 1; if (r.status == VAROBJ_NOT_IN_SCOPE) - return result; + { + if (r.type_changed || r.changed) + VEC_safe_push (varobj_update_result, result, &r); + return result; + } + + VEC_safe_push (varobj_update_result, stack, &r); + } + else + { + varobj_update_result r = {0}; + r.varobj = *varp; + VEC_safe_push (varobj_update_result, stack, &r); } - - VEC_safe_push (varobj_p, stack, *varp); /* Walk through the children, reconstructing them all. */ - while (!VEC_empty (varobj_p, stack)) + while (!VEC_empty (varobj_update_result, stack)) { - v = VEC_pop (varobj_p, stack); + varobj_update_result r = *(VEC_last (varobj_update_result, stack)); + struct varobj *v = r.varobj; + + VEC_pop (varobj_update_result, stack); + + /* Update this variable, unless it's a root, which is already + updated. */ + if (!r.value_installed) + { + new = value_of_child (v->parent, v->index); + if (install_new_value (v, new, 0 /* type not changed */)) + { + r.changed = 1; + v->updated = 0; + } + } + + /* We probably should not get children of a varobj that has a + pretty-printer, but for which -var-list-children was never + invoked. */ + if (v->pretty_printer) + { + VEC (varobj_p) *changed = 0, *new = 0, *unchanged = 0; + int i, children_changed = 0; + + if (v->frozen) + continue; + + if (!v->children_requested) + { + int dummy; + + /* If we initially did not have potential children, but + now we do, consider the varobj as changed. + Otherwise, if children were never requested, consider + it as unchanged -- presumably, such varobj is not yet + expanded in the UI, so we need not bother getting + it. */ + if (!varobj_has_more (v, 0)) + { + update_dynamic_varobj_children (v, NULL, NULL, NULL, + &dummy, 0, 0, 0); + if (varobj_has_more (v, 0)) + r.changed = 1; + } + + if (r.changed) + VEC_safe_push (varobj_update_result, result, &r); + + continue; + } + + /* If update_dynamic_varobj_children returns 0, then we have + a non-conforming pretty-printer, so we skip it. */ + if (update_dynamic_varobj_children (v, &changed, &new, &unchanged, + &children_changed, 1, + v->from, v->to)) + { + if (children_changed || new) + { + r.children_changed = 1; + r.new = new; + } + /* Push in reverse order so that the first child is + popped from the work stack first, and so will be + added to result first. This does not affect + correctness, just "nicer". */ + for (i = VEC_length (varobj_p, changed) - 1; i >= 0; --i) + { + varobj_p tmp = VEC_index (varobj_p, changed, i); + varobj_update_result r = {0}; + r.varobj = tmp; + r.changed = 1; + r.value_installed = 1; + VEC_safe_push (varobj_update_result, stack, &r); + } + for (i = VEC_length (varobj_p, unchanged) - 1; i >= 0; --i) + { + varobj_p tmp = VEC_index (varobj_p, unchanged, i); + if (!tmp->frozen) + { + varobj_update_result r = {0}; + r.varobj = tmp; + r.value_installed = 1; + VEC_safe_push (varobj_update_result, stack, &r); + } + } + if (r.changed || r.children_changed) + VEC_safe_push (varobj_update_result, result, &r); + + /* Free CHANGED and UNCHANGED, but not NEW, because NEW + has been put into the result vector. */ + VEC_free (varobj_p, changed); + VEC_free (varobj_p, unchanged); + + continue; + } + } /* Push any children. Use reverse order so that the first child is popped from the work stack first, and so @@ -1223,26 +1859,19 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) varobj_p c = VEC_index (varobj_p, v->children, i); /* Child may be NULL if explicitly deleted by -var-delete. */ if (c != NULL && !c->frozen) - VEC_safe_push (varobj_p, stack, c); - } - - /* Update this variable, unless it's a root, which is already - updated. */ - if (v->root->rootvar != v) - { - new = value_of_child (v->parent, v->index); - if (install_new_value (v, new, 0 /* type not changed */)) { - /* Note that it's changed */ - varobj_update_result r = {v}; - r.changed = 1; - VEC_safe_push (varobj_update_result, result, &r); - v->updated = 0; + varobj_update_result r = {0}; + r.varobj = c; + VEC_safe_push (varobj_update_result, stack, &r); } } + + if (r.changed || r.type_changed) + VEC_safe_push (varobj_update_result, result, &r); } - VEC_free (varobj_p, stack); + VEC_free (varobj_update_result, stack); + return result; } @@ -1355,7 +1984,6 @@ install_variable (struct varobj *var) else var->root->next = rootlist; rootlist = var->root; - rootcount++; } return 1; /* OK */ @@ -1432,7 +2060,6 @@ uninstall_variable (struct varobj *var) else prer->next = cr->next; } - rootcount--; } } @@ -1440,17 +2067,24 @@ uninstall_variable (struct varobj *var) /* Create and install a child of the parent of the given name */ static struct varobj * create_child (struct varobj *parent, int index, char *name) +{ + return create_child_with_value (parent, index, name, + value_of_child (parent, index)); +} + +static struct varobj * +create_child_with_value (struct varobj *parent, int index, const char *name, + struct value *value) { struct varobj *child; char *childs_name; - struct value *value; child = new_variable (); /* name is allocated by name_of_child */ - child->name = name; + /* FIXME: xstrdup should not be here. */ + child->name = xstrdup (name); child->index = index; - value = value_of_child (parent, index); child->parent = parent; child->root = parent->root; childs_name = xstrprintf ("%s.%s", parent->obj_name, name); @@ -1499,6 +2133,13 @@ new_variable (void) var->print_value = NULL; var->frozen = 0; var->not_fetched = 0; + var->children_requested = 0; + var->from = -1; + var->to = -1; + var->constructor = 0; + var->pretty_printer = 0; + var->child_iter = 0; + var->saved_item = 0; return var; } @@ -1524,6 +2165,18 @@ new_root_variable (void) static void free_variable (struct varobj *var) { +#if HAVE_PYTHON + if (var->pretty_printer) + { + struct cleanup *cleanup = varobj_ensure_python_env (var); + Py_XDECREF (var->constructor); + Py_XDECREF (var->pretty_printer); + Py_XDECREF (var->child_iter); + Py_XDECREF (var->saved_item); + do_cleanups (cleanup); + } +#endif + value_free (var->value); /* Free the expression if this is a root variable. */ @@ -1765,8 +2418,9 @@ value_of_root (struct varobj **var_handle, int *type_changed) } else { - tmp_var->obj_name = - savestring (var->obj_name, strlen (var->obj_name)); + tmp_var->obj_name = xstrdup (var->obj_name); + tmp_var->from = var->from; + tmp_var->to = var->to; varobj_delete (var, NULL, 0); install_variable (tmp_var); @@ -1801,30 +2455,113 @@ static char * 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, format); + { + if (var->pretty_printer) + return value_get_print_value (var->value, var->format, var); + return (*var->root->lang->value_of_variable) (var, format); + } else return NULL; } static char * -value_get_print_value (struct value *value, enum varobj_display_formats format) +value_get_print_value (struct value *value, enum varobj_display_formats format, + struct varobj *var) { - long dummy; struct ui_file *stb; struct cleanup *old_chain; - char *thevalue; + gdb_byte *thevalue = NULL; struct value_print_options opts; + struct type *type = NULL; + long len = 0; + char *encoding = NULL; + struct gdbarch *gdbarch = NULL; if (value == NULL) return NULL; + gdbarch = get_type_arch (value_type (value)); +#if HAVE_PYTHON + { + struct cleanup *back_to = varobj_ensure_python_env (var); + PyObject *value_formatter = var->pretty_printer; + + if (value_formatter) + { + /* First check to see if we have any children at all. If so, + we simply return {...}. */ + if (dynamic_varobj_has_child_method (var)) + return xstrdup ("{...}"); + + if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst)) + { + char *hint; + struct value *replacement; + int string_print = 0; + PyObject *output = NULL; + + hint = gdbpy_get_display_hint (value_formatter); + if (hint) + { + if (!strcmp (hint, "string")) + string_print = 1; + xfree (hint); + } + + output = apply_varobj_pretty_printer (value_formatter, + &replacement); + if (output) + { + if (gdbpy_is_lazy_string (output)) + { + thevalue = gdbpy_extract_lazy_string (output, &type, + &len, &encoding); + string_print = 1; + } + else + { + PyObject *py_str + = python_string_to_target_python_string (output); + if (py_str) + { + char *s = PyString_AsString (py_str); + len = PyString_Size (py_str); + thevalue = xmemdup (s, len + 1, len + 1); + type = builtin_type (gdbarch)->builtin_char; + Py_DECREF (py_str); + } + } + Py_DECREF (output); + } + if (thevalue && !string_print) + { + do_cleanups (back_to); + xfree (encoding); + return thevalue; + } + if (replacement) + value = replacement; + } + } + do_cleanups (back_to); + } +#endif + stb = mem_fileopen (); old_chain = make_cleanup_ui_file_delete (stb); get_formatted_print_options (&opts, format_code[(int) format]); opts.deref_ref = 0; - common_val_print (value, stb, 0, &opts, current_language); - thevalue = ui_file_xstrdup (stb, &dummy); + opts.raw = 1; + if (thevalue) + { + make_cleanup (xfree, thevalue); + make_cleanup (xfree, encoding); + LA_PRINT_STRING (stb, type, thevalue, len, encoding, 0, &opts); + } + else + common_val_print (value, stb, 0, &opts, current_language); + thevalue = ui_file_xstrdup (stb, NULL); do_cleanups (old_chain); return thevalue; @@ -1914,7 +2651,7 @@ varobj_floating_p (struct varobj *var) value is not known. If WAS_PTR is not NULL, set *WAS_PTR to 0 or 1 - depending on whether pointer was deferenced + depending on whether pointer was dereferenced in this function. */ static void adjust_value_for_child_access (struct value **value, @@ -2015,7 +2752,7 @@ c_number_of_children (struct varobj *var) static char * c_name_of_variable (struct varobj *parent) { - return savestring (parent->name, strlen (parent->name)); + return xstrdup (parent->name); } /* Return the value of element TYPE_INDEX of a structure @@ -2089,24 +2826,25 @@ c_describe_child (struct varobj *parent, int index, { case TYPE_CODE_ARRAY: if (cname) - *cname = xstrprintf ("%d", index - + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type))); + *cname = xstrdup (int_string (index + + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)), + 10, 1, 0, 0)); if (cvalue && value) { int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)); - struct value *indval = - value_from_longest (builtin_type_int32, (LONGEST) real_index); - gdb_value_subscript (value, indval, cvalue); + gdb_value_subscript (value, real_index, cvalue); } 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))); + *cfull_expression = + xstrprintf ("(%s)[%s]", parent_expression, + int_string (index + + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)), + 10, 1, 0, 0)); break; @@ -2114,10 +2852,7 @@ c_describe_child (struct varobj *parent, int index, case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: if (cname) - { - char *string = TYPE_FIELD_NAME (type, index); - *cname = savestring (string, strlen (string)); - } + *cname = xstrdup (TYPE_FIELD_NAME (type, index)); if (cvalue && value) { @@ -2283,6 +3018,11 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format) catch that case explicitly. */ struct type *type = get_type (var); + /* If we have a custom formatter, return whatever string it has + produced. */ + if (var->pretty_printer && var->print_value) + return xstrdup (var->print_value); + /* Strip top-level references. */ while (TYPE_CODE (type) == TYPE_CODE_REF) type = check_typedef (TYPE_TARGET_TYPE (type)); @@ -2327,7 +3067,7 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format) if (format == var->format) return xstrdup (var->print_value); else - return value_get_print_value (var->value, format); + return value_get_print_value (var->value, format, var); } } } @@ -2399,16 +3139,21 @@ cplus_number_of_children (struct varobj *var) static void cplus_class_num_children (struct type *type, int children[3]) { - int i; + int i, vptr_fieldno; + struct type *basetype = NULL; children[v_public] = 0; children[v_private] = 0; children[v_protected] = 0; + vptr_fieldno = get_vptr_fieldno (type, &basetype); for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++) { - /* If we have a virtual table pointer, omit it. */ - if (TYPE_VPTR_BASETYPE (type) == type && TYPE_VPTR_FIELDNO (type) == i) + /* If we have a virtual table pointer, omit it. Even if virtual + table pointers are not specifically marked in the debug info, + they should be artificial. */ + if ((type == basetype && i == vptr_fieldno) + || TYPE_FIELD_ARTIFICIAL (type, i)) continue; if (TYPE_FIELD_PROTECTED (type, i)) @@ -2495,6 +3240,10 @@ cplus_describe_child (struct varobj *parent, int index, find the indexed field. */ int type_index = TYPE_N_BASECLASSES (type); enum accessibility acc = public_field; + int vptr_fieldno; + struct type *basetype = NULL; + + vptr_fieldno = get_vptr_fieldno (type, &basetype); if (strcmp (parent->name, "private") == 0) acc = private_field; else if (strcmp (parent->name, "protected") == 0) @@ -2502,8 +3251,8 @@ cplus_describe_child (struct varobj *parent, int index, while (index >= 0) { - if (TYPE_VPTR_BASETYPE (type) == type - && type_index == TYPE_VPTR_FIELDNO (type)) + if ((type == basetype && type_index == vptr_fieldno) + || TYPE_FIELD_ARTIFICIAL (type, type_index)) ; /* ignore vptr */ else if (match_accessibility (type, type_index, acc)) --index; @@ -2532,10 +3281,7 @@ cplus_describe_child (struct varobj *parent, int index, *cname = xstrdup (TYPE_FIELD_NAME (type, index)); if (cvalue && value) - { - *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value); - release_value (*cvalue); - } + *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value); if (ctype) { @@ -2740,6 +3486,24 @@ java_value_of_variable (struct varobj *var, enum varobj_display_formats format) { return cplus_value_of_variable (var, format); } + +/* Iterate all the existing _root_ VAROBJs and call the FUNC callback for them + with an arbitrary caller supplied DATA pointer. */ + +void +all_root_varobjs (void (*func) (struct varobj *var, void *data), void *data) +{ + struct varobj_root *var_root, *var_root_next; + + /* Iterate "safely" - handle if the callee deletes its passed VAROBJ. */ + + for (var_root = rootlist; var_root != NULL; var_root = var_root_next) + { + var_root_next = var_root->next; + + (*func) (var_root->rootvar, data); + } +} extern void _initialize_varobj (void); void @@ -2760,51 +3524,45 @@ When non-zero, varobj debugging is enabled."), &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". */ +/* Invalidate varobj VAR if it is tied to locals and re-create it if it is + defined on globals. It is a helper for varobj_invalidate. */ -void -varobj_invalidate (void) +static void +varobj_invalidate_iter (struct varobj *var, void *unused) { - struct varobj **all_rootvarobj; - struct varobj **varp; + /* Floating varobjs are reparsed on each stop, so we don't care if the + presently parsed expression refers to something that's gone. */ + if (var->root->floating) + return; - if (varobj_list (&all_rootvarobj) > 0) + /* global var must be re-evaluated. */ + if (var->root->valid_block == NULL) { - 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; + struct varobj *tmp_var; - varp++; + /* Try to create a varobj with same expression. If we succeed + replace the old varobj, otherwise invalidate it. */ + tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0, + USE_CURRENT_FRAME); + if (tmp_var != NULL) + { + tmp_var->obj_name = xstrdup (var->obj_name); + varobj_delete (var, NULL, 0); + install_variable (tmp_var); } + else + var->root->is_valid = 0; } - xfree (all_rootvarobj); - return; + else /* locals must be invalidated. */ + var->root->is_valid = 0; +} + +/* 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) +{ + all_root_varobjs (varobj_invalidate_iter, NULL); }