| /* Implementation of the GDB variable objects API. | 
 |  | 
 |    Copyright (C) 1999-2025 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 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    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, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include "value.h" | 
 | #include "expression.h" | 
 | #include "frame.h" | 
 | #include "language.h" | 
 | #include "cli/cli-cmds.h" | 
 | #include "block.h" | 
 | #include "valprint.h" | 
 | #include "gdbsupport/gdb_regex.h" | 
 |  | 
 | #include "varobj.h" | 
 | #include "gdbthread.h" | 
 | #include "inferior.h" | 
 | #include "varobj-iter.h" | 
 | #include "parser-defs.h" | 
 | #include "gdbarch.h" | 
 | #include <algorithm> | 
 | #include "observable.h" | 
 |  | 
 | #if HAVE_PYTHON | 
 | #include "python/python.h" | 
 | #include "python/python-internal.h" | 
 | #else | 
 | typedef int PyObject; | 
 | #endif | 
 |  | 
 | /* See varobj.h.  */ | 
 |  | 
 | unsigned int varobjdebug = 0; | 
 | static void | 
 | show_varobjdebug (struct ui_file *file, int from_tty, | 
 | 		  struct cmd_list_element *c, const char *value) | 
 | { | 
 |   gdb_printf (file, _("Varobj debugging is %s.\n"), value); | 
 | } | 
 |  | 
 | /* String representations of gdb's format codes.  */ | 
 | const char *varobj_format_string[] = | 
 |   { "natural", "binary", "decimal", "hexadecimal", "octal", "zero-hexadecimal" }; | 
 |  | 
 | /* True if we want to allow Python-based pretty-printing.  */ | 
 | static bool pretty_printing = false; | 
 |  | 
 | void | 
 | varobj_enable_pretty_printing (void) | 
 | { | 
 |   pretty_printing = true; | 
 | } | 
 |  | 
 | /* Data structures */ | 
 |  | 
 | /* Every root variable has one of these structures saved in its | 
 |    varobj.  */ | 
 | struct varobj_root | 
 | { | 
 |   /* The expression for this parent.  */ | 
 |   expression_up exp; | 
 |  | 
 |   /* Cached arch from exp, for use in case exp gets invalidated.  */ | 
 |   struct gdbarch *gdbarch = nullptr; | 
 |  | 
 |   /* Cached language from exp, for use in case exp gets invalidated.  */ | 
 |   const struct language_defn *language_defn = nullptr; | 
 |  | 
 |   /* Block for which this expression is valid.  */ | 
 |   const struct block *valid_block = NULL; | 
 |  | 
 |   /* The frame for this expression.  This field is set iff valid_block is | 
 |      not NULL.  */ | 
 |   struct frame_id frame = null_frame_id; | 
 |  | 
 |   /* The global thread ID that this varobj_root belongs 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 = 0; | 
 |  | 
 |   /* If true, 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.  */ | 
 |   bool floating = false; | 
 |  | 
 |   /* Flag that indicates validity: set to false when this varobj_root refers | 
 |      to symbols that do not exist anymore.  */ | 
 |   bool is_valid = true; | 
 |  | 
 |   /* Set to true if the varobj was created as tracking a global.  */ | 
 |   bool global = false; | 
 |  | 
 |   /* Language-related operations for this variable and its | 
 |      children.  */ | 
 |   const struct lang_varobj_ops *lang_ops = NULL; | 
 |  | 
 |   /* The varobj for this root node.  */ | 
 |   struct varobj *rootvar = NULL; | 
 | }; | 
 |  | 
 | /* Dynamic part of varobj.  */ | 
 |  | 
 | struct varobj_dynamic | 
 | { | 
 |   /* 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.  */ | 
 |   bool children_requested = false; | 
 |  | 
 |   /* 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 = NULL; | 
 |  | 
 |   /* The pretty-printer that has been constructed.  If NULL, then a | 
 |      new printer object is needed, and one will be constructed.  */ | 
 |   PyObject *pretty_printer = NULL; | 
 |  | 
 |   /* The iterator returned by the printer's 'children' method, or NULL | 
 |      if not available.  */ | 
 |   std::unique_ptr<varobj_iter> 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.  */ | 
 |   std::unique_ptr<varobj_item> saved_item; | 
 | }; | 
 |  | 
 | /* Private function prototypes */ | 
 |  | 
 | /* Helper functions for the above subcommands.  */ | 
 |  | 
 | static int delete_variable (struct varobj *, bool); | 
 |  | 
 | static void delete_variable_1 (int *, struct varobj *, bool, bool); | 
 |  | 
 | static void install_variable (struct varobj *); | 
 |  | 
 | static void uninstall_variable (struct varobj *); | 
 |  | 
 | static struct varobj *create_child (struct varobj *, int, std::string &); | 
 |  | 
 | static struct varobj * | 
 | create_child_with_value (struct varobj *parent, int index, | 
 | 			 struct varobj_item *item); | 
 |  | 
 | /* Utility routines */ | 
 |  | 
 | static bool update_type_if_necessary (struct varobj *var, | 
 | 				      struct value *new_value); | 
 |  | 
 | static bool install_new_value (struct varobj *var, struct value *value, | 
 | 			       bool initial); | 
 |  | 
 | /* Language-specific routines.  */ | 
 |  | 
 | static int number_of_children (const struct varobj *); | 
 |  | 
 | static std::string name_of_variable (const struct varobj *); | 
 |  | 
 | static std::string name_of_child (struct varobj *, int); | 
 |  | 
 | static struct value *value_of_root (struct varobj **var_handle, bool *); | 
 |  | 
 | static struct value *value_of_child (const struct varobj *parent, int index); | 
 |  | 
 | static std::string my_value_of_variable (struct varobj *var, | 
 | 					 enum varobj_display_formats format); | 
 |  | 
 | static bool is_root_p (const struct varobj *var); | 
 |  | 
 | static struct varobj *varobj_add_child (struct varobj *var, | 
 | 					struct varobj_item *item); | 
 |  | 
 | /* Private data */ | 
 |  | 
 | /* Mappings of varobj_display_formats enums to gdb's format codes.  */ | 
 | static int format_code[] = { 0, 't', 'd', 'x', 'o', 'z' }; | 
 |  | 
 | /* List of root variable objects.  */ | 
 | static std::list<struct varobj_root *> rootlist; | 
 |  | 
 | /* Pointer to the varobj hash table (built at run time).  */ | 
 | static htab_t varobj_table; | 
 |  | 
 |  | 
 |  | 
 | /* API Implementation */ | 
 | static bool | 
 | is_root_p (const struct varobj *var) | 
 | { | 
 |   return (var->root->rootvar == var); | 
 | } | 
 |  | 
 | #ifdef HAVE_PYTHON | 
 |  | 
 | /* See python-internal.h.  */ | 
 | gdbpy_enter_varobj::gdbpy_enter_varobj (const struct varobj *var) | 
 | : gdbpy_enter (var->root->gdbarch, var->root->language_defn) | 
 | { | 
 | } | 
 |  | 
 | #endif | 
 |  | 
 | /* Return the full FRAME which corresponds to the given CORE_ADDR | 
 |    or NULL if no FRAME on the chain corresponds to CORE_ADDR.  */ | 
 |  | 
 | static frame_info_ptr | 
 | find_frame_addr_in_frame_chain (CORE_ADDR frame_addr) | 
 | { | 
 |   frame_info_ptr frame = NULL; | 
 |  | 
 |   if (frame_addr == (CORE_ADDR) 0) | 
 |     return NULL; | 
 |  | 
 |   for (frame = get_current_frame (); | 
 |        frame != NULL; | 
 |        frame = get_prev_frame (frame)) | 
 |     { | 
 |       /* 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; | 
 |     } | 
 |  | 
 |   return NULL; | 
 | } | 
 |  | 
 | /* Creates a varobj (not its children).  */ | 
 |  | 
 | struct varobj * | 
 | varobj_create (const char *objname, | 
 | 	       const char *expression, CORE_ADDR frame, enum varobj_type type) | 
 | { | 
 |   /* Fill out a varobj structure for the (root) variable being constructed.  */ | 
 |   auto var = std::make_unique<varobj> (new varobj_root); | 
 |  | 
 |   if (expression != NULL) | 
 |     { | 
 |       frame_info_ptr fi; | 
 |       struct frame_id old_id = null_frame_id; | 
 |       const struct block *block; | 
 |       const char *p; | 
 |       struct value *value = NULL; | 
 |       CORE_ADDR pc; | 
 |  | 
 |       /* Parse and evaluate the expression, filling in as much of the | 
 | 	 variable's data as possible.  */ | 
 |  | 
 |       if (has_stack_frames ()) | 
 | 	{ | 
 | 	  /* Allow creator to specify context of variable.  */ | 
 | 	  if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME)) | 
 | 	    fi = get_selected_frame (NULL); | 
 | 	  else | 
 | 	    /* FIXME: cagney/2002-11-23: This code should be doing a | 
 | 	       lookup using the frame ID and not just the frame's | 
 | 	       ``address''.  This, of course, means an interface | 
 | 	       change.  However, with out that interface change ISAs, | 
 | 	       such as the ia64 with its two stacks, won't work. | 
 | 	       Similar goes for the case where there is a frameless | 
 | 	       function.  */ | 
 | 	    fi = find_frame_addr_in_frame_chain (frame); | 
 | 	} | 
 |       else | 
 | 	fi = NULL; | 
 |  | 
 |       if (type == USE_SELECTED_FRAME) | 
 | 	var->root->floating = true; | 
 |  | 
 |       pc = 0; | 
 |       block = NULL; | 
 |       if (fi != NULL) | 
 | 	{ | 
 | 	  block = get_frame_block (fi, 0); | 
 | 	  pc = get_frame_pc (fi); | 
 | 	} | 
 |  | 
 |       p = expression; | 
 |  | 
 |       innermost_block_tracker tracker (INNERMOST_BLOCK_FOR_SYMBOLS | 
 | 				       | INNERMOST_BLOCK_FOR_REGISTERS); | 
 |       /* Wrap the call to parse expression, so we can  | 
 | 	 return a sensible error.  */ | 
 |       try | 
 | 	{ | 
 | 	  var->root->exp = parse_exp_1 (&p, pc, block, 0, &tracker); | 
 |  | 
 | 	  /* Cache gdbarch and language_defn as they might be used even | 
 | 	     after var is invalidated and var->root->exp cleared.  */ | 
 | 	  var->root->gdbarch = var->root->exp->gdbarch; | 
 | 	  var->root->language_defn = var->root->exp->language_defn; | 
 | 	} | 
 |  | 
 |       catch (const gdb_exception_error &except) | 
 | 	{ | 
 | 	  return NULL; | 
 | 	} | 
 |  | 
 |       /* Don't allow variables to be created for types.  */ | 
 |       if (var->root->exp->type_p ()) | 
 | 	{ | 
 | 	  gdb_printf (gdb_stderr, "Attempt to use a type name" | 
 | 		      " as an expression.\n"); | 
 | 	  return NULL; | 
 | 	} | 
 |  | 
 |       var->format = FORMAT_NATURAL; | 
 |       var->root->valid_block = | 
 | 	var->root->floating ? NULL : tracker.block (); | 
 |       var->root->global | 
 | 	= var->root->floating ? false : var->root->valid_block == nullptr; | 
 |       var->name = expression; | 
 |       /* For a root var, the name and the expr are the same.  */ | 
 |       var->path_expr = 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 (var->root->valid_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 = inferior_thread ()->global_num; | 
 | 	  old_id = get_frame_id (get_selected_frame (NULL)); | 
 | 	  select_frame (fi);	  | 
 | 	} | 
 |  | 
 |       /* We definitely need to catch errors here.  If evaluation of | 
 | 	 the expression succeeds, we got the value we wanted.  But if | 
 | 	 it fails, we still go on with a call to evaluate_type().  */ | 
 |       try | 
 | 	{ | 
 | 	  value = var->root->exp->evaluate (); | 
 | 	} | 
 |       catch (const gdb_exception_error &except) | 
 | 	{ | 
 | 	  /* Error getting the value.  Try to at least get the | 
 | 	     right type.  */ | 
 | 	  struct value *type_only_value = var->root->exp->evaluate_type (); | 
 |  | 
 | 	  var->type = type_only_value->type (); | 
 | 	} | 
 |  | 
 |       if (value != NULL) | 
 | 	{ | 
 | 	  int real_type_found = 0; | 
 |  | 
 | 	  var->type = value_actual_type (value, 0, &real_type_found); | 
 | 	  if (real_type_found) | 
 | 	    value = value_cast (var->type, value); | 
 | 	} | 
 |  | 
 |       /* Set language info */ | 
 |       var->root->lang_ops = var->root->exp->language_defn->varobj_ops (); | 
 |  | 
 |       install_new_value (var.get (), value, 1 /* Initial assignment */); | 
 |  | 
 |       /* Set ourselves as our root.  */ | 
 |       var->root->rootvar = var.get (); | 
 |  | 
 |       /* Reset the selected frame.  */ | 
 |       if (frame_id_p (old_id)) | 
 | 	select_frame (frame_find_by_id (old_id)); | 
 |     } | 
 |  | 
 |   /* If the variable object name is null, that means this | 
 |      is a temporary variable, so don't install it.  */ | 
 |  | 
 |   if ((var != NULL) && (objname != NULL)) | 
 |     { | 
 |       var->obj_name = objname; | 
 |       install_variable (var.get ()); | 
 |     } | 
 |  | 
 |   return var.release (); | 
 | } | 
 |  | 
 | /* Generates an unique name that can be used for a varobj.  */ | 
 |  | 
 | std::string | 
 | varobj_gen_name (void) | 
 | { | 
 |   static int id = 0; | 
 |  | 
 |   /* Generate a name for this object.  */ | 
 |   id++; | 
 |   return string_printf ("var%d", id); | 
 | } | 
 |  | 
 | /* Given an OBJNAME, returns the pointer to the corresponding varobj.  Call | 
 |    error if OBJNAME cannot be found.  */ | 
 |  | 
 | struct varobj * | 
 | varobj_get_handle (const char *objname) | 
 | { | 
 |   varobj *var = (varobj *) htab_find_with_hash (varobj_table, objname, | 
 | 						htab_hash_string (objname)); | 
 |  | 
 |   if (var == NULL) | 
 |     error (_("Variable object not found")); | 
 |  | 
 |   return var; | 
 | } | 
 |  | 
 | /* Given the handle, return the name of the object.  */ | 
 |  | 
 | const char * | 
 | varobj_get_objname (const struct varobj *var) | 
 | { | 
 |   return var->obj_name.c_str (); | 
 | } | 
 |  | 
 | /* Given the handle, return the expression represented by the | 
 |    object.  */ | 
 |  | 
 | std::string | 
 | varobj_get_expression (const struct varobj *var) | 
 | { | 
 |   return name_of_variable (var); | 
 | } | 
 |  | 
 | /* See varobj.h.  */ | 
 |  | 
 | int | 
 | varobj_delete (struct varobj *var, bool only_children) | 
 | { | 
 |   return delete_variable (var, only_children); | 
 | } | 
 |  | 
 | #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) | 
 | { | 
 |   gdbpy_ref<> val_obj (value_to_value_object (value)); | 
 |   if (val_obj == nullptr) | 
 |     return NULL; | 
 |  | 
 |   return PyObject_CallFunctionObjArgs (constructor, val_obj.get (), NULL); | 
 | } | 
 |  | 
 | #endif | 
 |  | 
 | /* Set/Get variable object display format.  */ | 
 |  | 
 | enum varobj_display_formats | 
 | varobj_set_display_format (struct varobj *var, | 
 | 			   enum varobj_display_formats format) | 
 | { | 
 |   var->format = format; | 
 |  | 
 |   if (varobj_value_is_changeable_p (var)  | 
 |       && var->value != nullptr && !var->value->lazy ()) | 
 |     { | 
 |       var->print_value = varobj_value_get_print_value (var->value.get (), | 
 | 						       var->format, var); | 
 |     } | 
 |  | 
 |   return var->format; | 
 | } | 
 |  | 
 | enum varobj_display_formats | 
 | varobj_get_display_format (const struct varobj *var) | 
 | { | 
 |   return var->format; | 
 | } | 
 |  | 
 | gdb::unique_xmalloc_ptr<char> | 
 | varobj_get_display_hint (const struct varobj *var) | 
 | { | 
 |   gdb::unique_xmalloc_ptr<char> result; | 
 |  | 
 | #if HAVE_PYTHON | 
 |   if (!gdb_python_initialized) | 
 |     return NULL; | 
 |  | 
 |   gdbpy_enter_varobj enter_py (var); | 
 |  | 
 |   if (var->dynamic->pretty_printer != NULL) | 
 |     result = gdbpy_get_display_hint (var->dynamic->pretty_printer); | 
 | #endif | 
 |  | 
 |   return result; | 
 | } | 
 |  | 
 | /* Return true if the varobj has items after TO, false otherwise.  */ | 
 |  | 
 | bool | 
 | varobj_has_more (const struct varobj *var, int to) | 
 | { | 
 |   if (var->children.size () > to) | 
 |     return true; | 
 |  | 
 |   return ((to == -1 || var->children.size () == to) | 
 | 	  && (var->dynamic->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 | 
 |    is always positive.  Otherwise, returns -1.  */ | 
 | int | 
 | varobj_get_thread_id (const 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, bool 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; | 
 | } | 
 |  | 
 | bool | 
 | varobj_get_frozen (const struct varobj *var) | 
 | { | 
 |   return var->frozen; | 
 | } | 
 |  | 
 | /* A helper function that updates the contents of FROM and TO based on the | 
 |    size of the vector CHILDREN.  If the contents of either FROM or TO are | 
 |    negative the entire range is used.  */ | 
 |  | 
 | void | 
 | varobj_restrict_range (const std::vector<varobj *> &children, | 
 | 		       int *from, int *to) | 
 | { | 
 |   int len = children.size (); | 
 |  | 
 |   if (*from < 0 || *to < 0) | 
 |     { | 
 |       *from = 0; | 
 |       *to = len; | 
 |     } | 
 |   else | 
 |     { | 
 |       if (*from > len) | 
 | 	*from = len; | 
 |       if (*to > len) | 
 | 	*to = len; | 
 |       if (*from > *to) | 
 | 	*from = *to; | 
 |     } | 
 | } | 
 |  | 
 | /* A helper for update_dynamic_varobj_children that installs a new | 
 |    child when needed.  */ | 
 |  | 
 | static void | 
 | install_dynamic_child (struct varobj *var, | 
 | 		       std::vector<varobj *> *changed, | 
 | 		       std::vector<varobj *> *type_changed, | 
 | 		       std::vector<varobj *> *newobj, | 
 | 		       std::vector<varobj *> *unchanged, | 
 | 		       bool *cchanged, | 
 | 		       int index, | 
 | 		       struct varobj_item *item) | 
 | { | 
 |   if (var->children.size () < index + 1) | 
 |     { | 
 |       /* There's no child yet.  */ | 
 |       struct varobj *child = varobj_add_child (var, item); | 
 |  | 
 |       if (newobj != NULL) | 
 | 	{ | 
 | 	  newobj->push_back (child); | 
 | 	  *cchanged = true; | 
 | 	} | 
 |     } | 
 |   else | 
 |     { | 
 |       varobj *existing = var->children[index]; | 
 |       bool type_updated = update_type_if_necessary (existing, | 
 | 						    item->value.get ()); | 
 |  | 
 |       if (type_updated) | 
 | 	{ | 
 | 	  if (type_changed != NULL) | 
 | 	    type_changed->push_back (existing); | 
 | 	} | 
 |       if (install_new_value (existing, item->value.get (), 0)) | 
 | 	{ | 
 | 	  if (!type_updated && changed != NULL) | 
 | 	    changed->push_back (existing); | 
 | 	} | 
 |       else if (!type_updated && unchanged != NULL) | 
 | 	unchanged->push_back (existing); | 
 |     } | 
 | } | 
 |  | 
 | /* A factory for creating dynamic varobj's iterators.  Returns an | 
 |    iterator object suitable for iterating over VAR's children.  */ | 
 |  | 
 | static std::unique_ptr<varobj_iter> | 
 | varobj_get_iterator (struct varobj *var) | 
 | { | 
 | #if HAVE_PYTHON | 
 |   if (var->dynamic->pretty_printer) | 
 |     { | 
 |       value_print_options opts; | 
 |       varobj_formatted_print_options (&opts, var->format); | 
 |       return py_varobj_get_iterator (var, var->dynamic->pretty_printer, &opts); | 
 |     } | 
 | #endif | 
 |  | 
 |   gdb_assert_not_reached ("requested an iterator from a non-dynamic varobj"); | 
 | } | 
 |  | 
 | static bool | 
 | update_dynamic_varobj_children (struct varobj *var, | 
 | 				std::vector<varobj *> *changed, | 
 | 				std::vector<varobj *> *type_changed, | 
 | 				std::vector<varobj *> *newobj, | 
 | 				std::vector<varobj *> *unchanged, | 
 | 				bool *cchanged, | 
 | 				bool update_children, | 
 | 				int from, | 
 | 				int to) | 
 | { | 
 |   int i; | 
 |  | 
 |   *cchanged = false; | 
 |  | 
 |   if (update_children || var->dynamic->child_iter == NULL) | 
 |     { | 
 |       var->dynamic->child_iter = varobj_get_iterator (var); | 
 |       var->dynamic->saved_item.reset (nullptr); | 
 |  | 
 |       i = 0; | 
 |  | 
 |       if (var->dynamic->child_iter == NULL) | 
 | 	return false; | 
 |     } | 
 |   else | 
 |     i = var->children.size (); | 
 |  | 
 |   /* We ask for one extra child, so that MI can report whether there | 
 |      are more children.  */ | 
 |   for (; to < 0 || i < to + 1; ++i) | 
 |     { | 
 |       std::unique_ptr<varobj_item> item; | 
 |  | 
 |       /* See if there was a leftover from last time.  */ | 
 |       if (var->dynamic->saved_item != NULL) | 
 | 	item = std::move (var->dynamic->saved_item); | 
 |       else | 
 | 	item = var->dynamic->child_iter->next (); | 
 |  | 
 |       if (item == NULL) | 
 | 	{ | 
 | 	  /* Iteration is done.  Remove iterator from VAR.  */ | 
 | 	  var->dynamic->child_iter.reset (nullptr); | 
 | 	  break; | 
 | 	} | 
 |       /* We don't want to push the extra child on any report list.  */ | 
 |       if (to < 0 || i < to) | 
 | 	{ | 
 | 	  bool can_mention = from < 0 || i >= from; | 
 |  | 
 | 	  install_dynamic_child (var, can_mention ? changed : NULL, | 
 | 				 can_mention ? type_changed : NULL, | 
 | 				 can_mention ? newobj : NULL, | 
 | 				 can_mention ? unchanged : NULL, | 
 | 				 can_mention ? cchanged : NULL, i, | 
 | 				 item.get ()); | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  var->dynamic->saved_item = std::move (item); | 
 |  | 
 | 	  /* We want to truncate the child list just before this | 
 | 	     element.  */ | 
 | 	  break; | 
 | 	} | 
 |     } | 
 |  | 
 |   if (i < var->children.size ()) | 
 |     { | 
 |       *cchanged = true; | 
 |       for (int j = i; j < var->children.size (); ++j) | 
 | 	varobj_delete (var->children[j], 0); | 
 |  | 
 |       var->children.resize (i); | 
 |     } | 
 |  | 
 |   /* If there are fewer children than requested, note that the list of | 
 |      children changed.  */ | 
 |   if (to >= 0 && var->children.size () < to) | 
 |     *cchanged = true; | 
 |  | 
 |   var->num_children = var->children.size (); | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | int | 
 | varobj_get_num_children (struct varobj *var) | 
 | { | 
 |   if (var->num_children == -1) | 
 |     { | 
 |       if (varobj_is_dynamic_p (var)) | 
 | 	{ | 
 | 	  bool 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, NULL, &dummy, | 
 | 					  false, 0, 0); | 
 | 	} | 
 |       else | 
 | 	var->num_children = number_of_children (var); | 
 |     } | 
 |  | 
 |   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.  */ | 
 |  | 
 | const std::vector<varobj *> & | 
 | varobj_list_children (struct varobj *var, int *from, int *to) | 
 | { | 
 |   var->dynamic->children_requested = true; | 
 |  | 
 |   if (varobj_is_dynamic_p (var)) | 
 |     { | 
 |       bool children_changed; | 
 |  | 
 |       /* 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, NULL, | 
 | 				      &children_changed, false, 0, *to); | 
 |       varobj_restrict_range (var->children, from, to); | 
 |       return var->children; | 
 |     } | 
 |  | 
 |   if (var->num_children == -1) | 
 |     var->num_children = number_of_children (var); | 
 |  | 
 |   /* If that failed, give up.  */ | 
 |   if (var->num_children == -1) | 
 |     return var->children; | 
 |  | 
 |   /* If we're called when the list of children is not yet initialized, | 
 |      allocate enough elements in it.  */ | 
 |   while (var->children.size () < var->num_children) | 
 |     var->children.push_back (NULL); | 
 |  | 
 |   for (int i = 0; i < var->num_children; i++) | 
 |     { | 
 |       if (var->children[i] == NULL) | 
 | 	{ | 
 | 	  /* Either it's the first call to varobj_list_children for | 
 | 	     this variable object, and the child was never created, | 
 | 	     or it was explicitly deleted by the client.  */ | 
 | 	  std::string name = name_of_child (var, i); | 
 | 	  var->children[i] = create_child (var, i, name); | 
 | 	} | 
 |     } | 
 |  | 
 |   varobj_restrict_range (var->children, from, to); | 
 |   return var->children; | 
 | } | 
 |  | 
 | static struct varobj * | 
 | varobj_add_child (struct varobj *var, struct varobj_item *item) | 
 | { | 
 |   varobj *v = create_child_with_value (var, var->children.size (), item); | 
 |  | 
 |   var->children.push_back (v); | 
 |  | 
 |   return v; | 
 | } | 
 |  | 
 | /* Obtain the type of an object Variable as a string similar to the one gdb | 
 |    prints on the console.  The caller is responsible for freeing the string. | 
 |    */ | 
 |  | 
 | std::string | 
 | varobj_get_type (struct varobj *var) | 
 | { | 
 |   /* For the "fake" variables, do not return a type.  (Its type is | 
 |      NULL, too.) | 
 |      Do not return a type for invalid variables as well.  */ | 
 |   if (CPLUS_FAKE_CHILD (var) || !var->root->is_valid) | 
 |     return std::string (); | 
 |  | 
 |   return type_to_string (var->type); | 
 | } | 
 |  | 
 | /* Obtain the type of an object variable.  */ | 
 |  | 
 | struct type * | 
 | varobj_get_gdb_type (const struct varobj *var) | 
 | { | 
 |   return var->type; | 
 | } | 
 |  | 
 | /* Is VAR a path expression parent, i.e., can it be used to construct | 
 |    a valid path expression?  */ | 
 |  | 
 | static bool | 
 | is_path_expr_parent (const struct varobj *var) | 
 | { | 
 |   gdb_assert (var->root->lang_ops->is_path_expr_parent != NULL); | 
 |   return var->root->lang_ops->is_path_expr_parent (var); | 
 | } | 
 |  | 
 | /* Is VAR a path expression parent, i.e., can it be used to construct | 
 |    a valid path expression?  By default we assume any VAR can be a path | 
 |    parent.  */ | 
 |  | 
 | bool | 
 | varobj_default_is_path_expr_parent (const struct varobj *var) | 
 | { | 
 |   return true; | 
 | } | 
 |  | 
 | /* Return the path expression parent for VAR.  */ | 
 |  | 
 | const struct varobj * | 
 | varobj_get_path_expr_parent (const struct varobj *var) | 
 | { | 
 |   const struct varobj *parent = var; | 
 |  | 
 |   while (!is_root_p (parent) && !is_path_expr_parent (parent)) | 
 |     parent = parent->parent; | 
 |  | 
 |   /* Computation of full rooted expression for children of dynamic | 
 |      varobjs is not supported.  */ | 
 |   if (varobj_is_dynamic_p (parent)) | 
 |     error (_("Invalid variable object (child of a dynamic varobj)")); | 
 |  | 
 |   return parent; | 
 | } | 
 |  | 
 | /* Return a pointer to the full rooted expression of varobj VAR. | 
 |    If it has not been computed yet, compute it.  */ | 
 |  | 
 | const char * | 
 | varobj_get_path_expr (const struct varobj *var) | 
 | { | 
 |   if (var->path_expr.empty ()) | 
 |     { | 
 |       /* For root varobjs, we initialize path_expr | 
 | 	 when creating varobj, so here it should be | 
 | 	 child varobj.  */ | 
 |       struct varobj *mutable_var = (struct varobj *) var; | 
 |       gdb_assert (!is_root_p (var)); | 
 |  | 
 |       mutable_var->path_expr = (*var->root->lang_ops->path_expr_of_child) (var); | 
 |     } | 
 |  | 
 |   return var->path_expr.c_str (); | 
 | } | 
 |  | 
 | const struct language_defn * | 
 | varobj_get_language (const struct varobj *var) | 
 | { | 
 |   return var->root->exp->language_defn; | 
 | } | 
 |  | 
 | int | 
 | varobj_get_attributes (const struct varobj *var) | 
 | { | 
 |   int attributes = 0; | 
 |  | 
 |   if (varobj_editable_p (var)) | 
 |     /* FIXME: define masks for attributes.  */ | 
 |     attributes |= 0x00000001;	/* Editable */ | 
 |  | 
 |   return attributes; | 
 | } | 
 |  | 
 | /* Return true if VAR is a dynamic varobj.  */ | 
 |  | 
 | bool | 
 | varobj_is_dynamic_p (const struct varobj *var) | 
 | { | 
 |   return var->dynamic->pretty_printer != NULL; | 
 | } | 
 |  | 
 | std::string | 
 | varobj_get_formatted_value (struct varobj *var, | 
 | 			    enum varobj_display_formats format) | 
 | { | 
 |   return my_value_of_variable (var, format); | 
 | } | 
 |  | 
 | std::string | 
 | varobj_get_value (struct varobj *var) | 
 | { | 
 |   return my_value_of_variable (var, var->format); | 
 | } | 
 |  | 
 | /* Set the value of an object variable (if it is editable) to the | 
 |    value of the given expression.  */ | 
 | /* Note: Invokes functions that can call error().  */ | 
 |  | 
 | bool | 
 | varobj_set_value (struct varobj *var, const char *expression) | 
 | { | 
 |   struct value *val = NULL; /* Initialize to keep gcc happy.  */ | 
 |   /* The argument "expression" contains the variable's new value. | 
 |      We need to first construct a legal expression for this -- ugh!  */ | 
 |   /* Does this cover all the bases?  */ | 
 |   struct value *value = NULL; /* Initialize to keep gcc happy.  */ | 
 |   const char *s = expression; | 
 |  | 
 |   gdb_assert (varobj_editable_p (var)); | 
 |  | 
 |   /* ALWAYS reset to decimal temporarily.  */ | 
 |   auto save_input_radix = make_scoped_restore (&input_radix, 10); | 
 |   expression_up exp = parse_exp_1 (&s, 0, 0, 0); | 
 |   try | 
 |     { | 
 |       value = exp->evaluate (); | 
 |     } | 
 |  | 
 |   catch (const gdb_exception_error &except) | 
 |     { | 
 |       /* We cannot proceed without a valid expression.  */ | 
 |       return false; | 
 |     } | 
 |  | 
 |   /* 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 (!var->value->lazy ()); | 
 |  | 
 |   /* 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 array's address, not with the | 
 |      array's content.  */ | 
 |   value = coerce_array (value); | 
 |  | 
 |   /* The new value may be lazy.  value_assign, or | 
 |      rather value_contents, will take care of this.  */ | 
 |   try | 
 |     { | 
 |       val = value_assign (var->value.get (), value); | 
 |     } | 
 |  | 
 |   catch (const gdb_exception_error &except) | 
 |     { | 
 |       return false; | 
 |     } | 
 |  | 
 |   /* 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, false /* Compare values.  */); | 
 |   return true; | 
 | } | 
 |  | 
 | #if HAVE_PYTHON | 
 |  | 
 | /* A helper function to install a constructor function and visualizer | 
 |    in a varobj_dynamic.  */ | 
 |  | 
 | static void | 
 | install_visualizer (struct varobj_dynamic *var, PyObject *constructor, | 
 | 		    PyObject *visualizer) | 
 | { | 
 |   Py_XDECREF (var->constructor); | 
 |   var->constructor = constructor; | 
 |  | 
 |   Py_XDECREF (var->pretty_printer); | 
 |   var->pretty_printer = visualizer; | 
 |  | 
 |   var->child_iter.reset (nullptr); | 
 | } | 
 |  | 
 | /* Install the default visualizer for VAR.  */ | 
 |  | 
 | static void | 
 | install_default_visualizer (struct varobj *var) | 
 | { | 
 |   /* Do not install a visualizer on a CPLUS_FAKE_CHILD.  */ | 
 |   if (CPLUS_FAKE_CHILD (var)) | 
 |     return; | 
 |  | 
 |   if (pretty_printing) | 
 |     { | 
 |       gdbpy_ref<> pretty_printer; | 
 |  | 
 |       if (var->value != nullptr) | 
 | 	{ | 
 | 	  pretty_printer = gdbpy_get_varobj_pretty_printer (var->value.get ()); | 
 | 	  if (pretty_printer == nullptr) | 
 | 	    { | 
 | 	      gdbpy_print_stack (); | 
 | 	      error (_("Cannot instantiate printer for default visualizer")); | 
 | 	    } | 
 | 	} | 
 |  | 
 |       if (pretty_printer == Py_None) | 
 | 	pretty_printer.reset (nullptr); | 
 |    | 
 |       install_visualizer (var->dynamic, NULL, pretty_printer.release ()); | 
 |     } | 
 | } | 
 |  | 
 | /* Instantiate and install a visualizer for VAR using CONSTRUCTOR to | 
 |    make a new object.  */ | 
 |  | 
 | static void | 
 | construct_visualizer (struct varobj *var, PyObject *constructor) | 
 | { | 
 |   PyObject *pretty_printer; | 
 |  | 
 |   /* Do not install a visualizer on a CPLUS_FAKE_CHILD.  */ | 
 |   if (CPLUS_FAKE_CHILD (var)) | 
 |     return; | 
 |  | 
 |   Py_INCREF (constructor); | 
 |   if (constructor == Py_None) | 
 |     pretty_printer = NULL; | 
 |   else | 
 |     { | 
 |       pretty_printer = instantiate_pretty_printer (constructor, | 
 | 						   var->value.get ()); | 
 |       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; | 
 | 	} | 
 |     } | 
 |  | 
 |   install_visualizer (var->dynamic, constructor, pretty_printer); | 
 | } | 
 |  | 
 | #endif /* HAVE_PYTHON */ | 
 |  | 
 | /* A helper function for install_new_value.  This creates and installs | 
 |    a visualizer for VAR, if appropriate.  */ | 
 |  | 
 | 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 (!gdb_python_initialized) | 
 |     return; | 
 |  | 
 |   if (var->dynamic->constructor != Py_None && var->value != NULL) | 
 |     { | 
 |       gdbpy_enter_varobj enter_py (var); | 
 |  | 
 |       if (var->dynamic->constructor == NULL) | 
 | 	install_default_visualizer (var); | 
 |       else | 
 | 	construct_visualizer (var, var->dynamic->constructor); | 
 |     } | 
 | #else | 
 |   /* Do nothing.  */ | 
 | #endif | 
 | } | 
 |  | 
 | /* When using RTTI to determine variable type it may be changed in runtime when | 
 |    the variable value is changed.  This function checks whether type of varobj | 
 |    VAR will change when a new value NEW_VALUE is assigned and if it is so | 
 |    updates the type of VAR.  */ | 
 |  | 
 | static bool | 
 | update_type_if_necessary (struct varobj *var, struct value *new_value) | 
 | { | 
 |   if (new_value) | 
 |     { | 
 |       struct value_print_options opts; | 
 |  | 
 |       get_user_print_options (&opts); | 
 |       if (opts.objectprint) | 
 | 	{ | 
 | 	  struct type *new_type = value_actual_type (new_value, 0, 0); | 
 | 	  std::string new_type_str = type_to_string (new_type); | 
 | 	  std::string curr_type_str = varobj_get_type (var); | 
 |  | 
 | 	  /* Did the type name change?  */ | 
 | 	  if (curr_type_str != new_type_str) | 
 | 	    { | 
 | 	      var->type = new_type; | 
 |  | 
 | 	      /* This information may be not valid for a new type.  */ | 
 | 	      varobj_delete (var, 1); | 
 | 	      var->children.clear (); | 
 | 	      var->num_children = -1; | 
 | 	      return true; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | /* Assign a new value to a variable object.  If INITIAL is true, | 
 |    this is the first assignment after the variable object was just | 
 |    created, or changed type.  In that case, just assign the value  | 
 |    and return false. | 
 |    Otherwise, assign the new value, and return true if the value is | 
 |    different from the current one, false otherwise.  The comparison is | 
 |    done on textual representation of value.  Therefore, some types | 
 |    need not be compared.  E.g.  for structures the reported value is | 
 |    always "{...}", so no comparison is necessary here.  If the old | 
 |    value was NULL and new one is not, or vice versa, we always return true. | 
 |  | 
 |    The VALUE parameter should not be released -- the function will | 
 |    take care of releasing it when needed.  */ | 
 | static bool | 
 | install_new_value (struct varobj *var, struct value *value, bool initial) | 
 | {  | 
 |   bool changeable; | 
 |   bool need_to_fetch; | 
 |   bool changed = false; | 
 |   bool intentionally_not_fetched = false; | 
 |  | 
 |   /* 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 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 behavior will not | 
 |      mess up read-sensitive values.  */ | 
 |   if (var->dynamic->pretty_printer != NULL) | 
 |     changeable = true; | 
 |  | 
 |   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); | 
 |  | 
 |   if (var->type && var->type->code () == TYPE_CODE_UNION) | 
 |     /* For unions, we need to fetch the value implicitly because | 
 |        of implementation of union member fetch.  When gdb | 
 |        creates a value for a field and the value of the enclosing | 
 |        structure is not lazy,  it immediately copies the necessary | 
 |        bytes from the enclosing values.  If the enclosing value is | 
 |        lazy, the call to value_fetch_lazy on the field will read | 
 |        the data from memory.  For unions, that means we'll read the | 
 |        same memory more than once, which is not desirable.  So | 
 |        fetch now.  */ | 
 |     need_to_fetch = true; | 
 |  | 
 |   /* The new value might be lazy.  If the type is changeable, | 
 |      that is we'll be comparing values of this type, fetch the | 
 |      value now.  Otherwise, on the next update the old value | 
 |      will be lazy, which means we've lost that old value.  */ | 
 |   if (need_to_fetch && value && value->lazy ()) | 
 |     { | 
 |       const struct varobj *parent = var->parent; | 
 |       bool 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 assignment we do the fetch, since it means we're | 
 | 	     explicitly asked to compare the new value with the old one.  */ | 
 | 	  intentionally_not_fetched = true; | 
 | 	} | 
 |       else | 
 | 	{ | 
 |  | 
 | 	  try | 
 | 	    { | 
 | 	      value->fetch_lazy (); | 
 | 	    } | 
 |  | 
 | 	  catch (const gdb_exception_error &except) | 
 | 	    { | 
 | 	      /* Set the value to NULL, so that for the next -var-update, | 
 | 		 we don't try to compare the new value with this value, | 
 | 		 that we couldn't even read.  */ | 
 | 	      value = NULL; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Get a reference now, before possibly passing it to any Python | 
 |      code that might release it.  */ | 
 |   value_ref_ptr value_holder; | 
 |   if (value != NULL) | 
 |     value_holder = value_ref_ptr::new_reference (value); | 
 |  | 
 |   /* 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.  */ | 
 |   std::string print_value; | 
 |   if (value != NULL && !value->lazy () | 
 |       && var->dynamic->pretty_printer == NULL) | 
 |     print_value = varobj_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 | 
 |      to compare with.  */ | 
 |   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 is different from the value that the | 
 | 	 varobj had after the previous -var-update.  So need to the | 
 | 	 varobj as changed.  */ | 
 |       if (var->updated) | 
 | 	changed = true; | 
 |       else if (var->dynamic->pretty_printer == NULL) | 
 | 	{ | 
 | 	  /* Try to compare the values.  That requires that both | 
 | 	     values are non-lazy.  */ | 
 | 	  if (var->not_fetched && var->value->lazy ()) | 
 | 	    { | 
 | 	      /* 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 = true; | 
 | 	    } | 
 | 	  else  if (var->value == NULL && value == NULL) | 
 | 	    /* Equal.  */ | 
 | 	    ; | 
 | 	  else if (var->value == NULL || value == NULL) | 
 | 	    { | 
 | 	      changed = true; | 
 | 	    } | 
 | 	  else | 
 | 	    { | 
 | 	      gdb_assert (!var->value->lazy ()); | 
 | 	      gdb_assert (!value->lazy ()); | 
 |  | 
 | 	      gdb_assert (!var->print_value.empty () && !print_value.empty ()); | 
 | 	      if (var->print_value != print_value) | 
 | 		changed = true; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   if (!initial && !changeable) | 
 |     { | 
 |       /* For values that are not changeable, we don't compare the values. | 
 | 	 However, we want to notice if a value was not NULL and now is NULL, | 
 | 	 or vice versa, so that we report when top-level varobjs come in scope | 
 | 	 and leave the scope.  */ | 
 |       changed = (var->value != NULL) != (value != NULL); | 
 |     } | 
 |  | 
 |   /* We must always keep the new value, since children depend on it.  */ | 
 |   var->value = value_holder; | 
 |   if (value && value->lazy () && intentionally_not_fetched) | 
 |     var->not_fetched = true; | 
 |   else | 
 |     var->not_fetched = false; | 
 |   var->updated = false; | 
 |  | 
 |   install_new_value_visualizer (var); | 
 |  | 
 |   /* If we installed a pretty-printer, re-compare the printed version | 
 |      to see if the variable changed.  */ | 
 |   if (var->dynamic->pretty_printer != NULL) | 
 |     { | 
 |       print_value = varobj_value_get_print_value (var->value.get (), | 
 | 						  var->format, var); | 
 |       if (var->print_value != print_value) | 
 | 	changed = true; | 
 |     } | 
 |   var->print_value = print_value; | 
 |  | 
 |   gdb_assert (var->value == nullptr || var->value->type ()); | 
 |  | 
 |   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 (const 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; | 
 |  | 
 |   if (!gdb_python_initialized) | 
 |     return; | 
 |  | 
 |   gdbpy_enter_varobj enter_py (var); | 
 |  | 
 |   mainmod = PyImport_AddModule ("__main__"); | 
 |   gdbpy_ref<> globals | 
 |     = gdbpy_ref<>::new_reference (PyModule_GetDict (mainmod)); | 
 |   gdbpy_ref<> constructor (PyRun_String (visualizer, Py_eval_input, | 
 | 					 globals.get (), globals.get ())); | 
 |  | 
 |   if (constructor == NULL) | 
 |     { | 
 |       gdbpy_print_stack (); | 
 |       error (_("Could not evaluate visualizer expression: %s"), visualizer); | 
 |     } | 
 |  | 
 |   construct_visualizer (var, constructor.get ()); | 
 |  | 
 |   /* If there are any children now, wipe them.  */ | 
 |   varobj_delete (var, 1 /* children only */); | 
 |   var->num_children = -1; | 
 |  | 
 |   /* Also be sure to reset the print value.  */ | 
 |   varobj_set_display_format (var, var->format); | 
 | #else | 
 |   error (_("Python support required")); | 
 | #endif | 
 | } | 
 |  | 
 | /* If NEW_VALUE is the new value of the given varobj (var), return | 
 |    true if var has mutated.  In other words, if the type of | 
 |    the new value is different from the type of the varobj's old | 
 |    value. | 
 |  | 
 |    NEW_VALUE may be NULL, if the varobj is now out of scope.  */ | 
 |  | 
 | static bool | 
 | varobj_value_has_mutated (const struct varobj *var, struct value *new_value, | 
 | 			  struct type *new_type) | 
 | { | 
 |   /* If we haven't previously computed the number of children in var, | 
 |      it does not matter from the front-end's perspective whether | 
 |      the type has mutated or not.  For all intents and purposes, | 
 |      it has not mutated.  */ | 
 |   if (var->num_children < 0) | 
 |     return false; | 
 |  | 
 |   if (var->root->lang_ops->value_has_mutated != NULL) | 
 |     { | 
 |       /* The varobj module, when installing new values, explicitly strips | 
 | 	 references, saying that we're not interested in those addresses. | 
 | 	 But detection of mutation happens before installing the new | 
 | 	 value, so our value may be a reference that we need to strip | 
 | 	 in order to remain consistent.  */ | 
 |       if (new_value != NULL) | 
 | 	new_value = coerce_ref (new_value); | 
 |       return var->root->lang_ops->value_has_mutated (var, new_value, new_type); | 
 |     } | 
 |   else | 
 |     return false; | 
 | } | 
 |  | 
 | /* 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 | 
 |    through its children, reconstructing them and noting if they've | 
 |    changed. | 
 |  | 
 |    The IS_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 TYPE_CHANGED, then it has done this and VARP will be modified | 
 |    to point to the new varobj.  */ | 
 |  | 
 | std::vector<varobj_update_result> | 
 | varobj_update (struct varobj **varp, bool is_explicit) | 
 | { | 
 |   bool type_changed = false; | 
 |   struct value *newobj; | 
 |   std::vector<varobj_update_result> stack; | 
 |   std::vector<varobj_update_result> result; | 
 |  | 
 |   /* 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 (!is_explicit && (*varp)->frozen) | 
 |     return result; | 
 |  | 
 |   if (!(*varp)->root->is_valid) | 
 |     { | 
 |       result.emplace_back (*varp, VAROBJ_INVALID); | 
 |       return result; | 
 |     } | 
 |  | 
 |   if ((*varp)->root->rootvar == *varp) | 
 |     { | 
 |       varobj_update_result r (*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.  */ | 
 |       newobj = value_of_root (varp, &type_changed); | 
 |       if (update_type_if_necessary (*varp, newobj)) | 
 | 	  type_changed = true; | 
 |       r.varobj = *varp; | 
 |       r.type_changed = type_changed; | 
 |       if (install_new_value ((*varp), newobj, type_changed)) | 
 | 	r.changed = true; | 
 |        | 
 |       if (newobj == NULL) | 
 | 	r.status = VAROBJ_NOT_IN_SCOPE; | 
 |       r.value_installed = true; | 
 |  | 
 |       if (r.status == VAROBJ_NOT_IN_SCOPE) | 
 | 	{ | 
 | 	  if (r.type_changed || r.changed) | 
 | 	    result.push_back (std::move (r)); | 
 |  | 
 | 	  return result; | 
 | 	} | 
 |  | 
 |       stack.push_back (std::move (r)); | 
 |     } | 
 |   else | 
 |     stack.emplace_back (*varp); | 
 |  | 
 |   /* Walk through the children, reconstructing them all.  */ | 
 |   while (!stack.empty ()) | 
 |     { | 
 |       varobj_update_result r = std::move (stack.back ()); | 
 |       stack.pop_back (); | 
 |       struct varobj *v = r.varobj; | 
 |  | 
 |       /* Update this variable, unless it's a root, which is already | 
 | 	 updated.  */ | 
 |       if (!r.value_installed) | 
 | 	{ | 
 | 	  struct type *new_type; | 
 |  | 
 | 	  newobj = value_of_child (v->parent, v->index); | 
 | 	  if (update_type_if_necessary (v, newobj)) | 
 | 	    r.type_changed = true; | 
 | 	  if (newobj) | 
 | 	    new_type = newobj->type (); | 
 | 	  else | 
 | 	    new_type = v->root->lang_ops->type_of_child (v->parent, v->index); | 
 |  | 
 | 	  if (varobj_value_has_mutated (v, newobj, new_type)) | 
 | 	    { | 
 | 	      /* The children are no longer valid; delete them now. | 
 | 		 Report the fact that its type changed as well.  */ | 
 | 	      varobj_delete (v, 1 /* only_children */); | 
 | 	      v->num_children = -1; | 
 | 	      v->to = -1; | 
 | 	      v->from = -1; | 
 | 	      v->type = new_type; | 
 | 	      r.type_changed = true; | 
 | 	    } | 
 |  | 
 | 	  if (install_new_value (v, newobj, r.type_changed)) | 
 | 	    { | 
 | 	      r.changed = true; | 
 | 	      v->updated = false; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       /* We probably should not get children of a dynamic varobj, but | 
 | 	 for which -var-list-children was never invoked.  */ | 
 |       if (varobj_is_dynamic_p (v)) | 
 | 	{ | 
 | 	  std::vector<varobj *> changed, type_changed_vec, unchanged, newobj_vec; | 
 | 	  bool children_changed = false; | 
 |  | 
 | 	  if (v->frozen) | 
 | 	    continue; | 
 |  | 
 | 	  if (!v->dynamic->children_requested) | 
 | 	    { | 
 | 	      bool 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, NULL, | 
 | 						  &dummy, false, 0, 0); | 
 | 		  if (varobj_has_more (v, 0)) | 
 | 		    r.changed = true; | 
 | 		} | 
 |  | 
 | 	      if (r.changed) | 
 | 		result.push_back (std::move (r)); | 
 |  | 
 | 	      continue; | 
 | 	    } | 
 |  | 
 | 	  /* If update_dynamic_varobj_children returns false, then we have | 
 | 	     a non-conforming pretty-printer, so we skip it.  */ | 
 | 	  if (update_dynamic_varobj_children (v, &changed, &type_changed_vec, | 
 | 					      &newobj_vec, | 
 | 					      &unchanged, &children_changed, | 
 | 					      true, v->from, v->to)) | 
 | 	    { | 
 | 	      if (children_changed || !newobj_vec.empty ()) | 
 | 		{ | 
 | 		  r.children_changed = true; | 
 | 		  r.newobj = std::move (newobj_vec); | 
 | 		} | 
 | 	      /* 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 (int i = type_changed_vec.size () - 1; i >= 0; --i) | 
 | 		{ | 
 | 		  varobj_update_result item (type_changed_vec[i]); | 
 |  | 
 | 		  /* Type may change only if value was changed.  */ | 
 | 		  item.changed = true; | 
 | 		  item.type_changed = true; | 
 | 		  item.value_installed = true; | 
 |  | 
 | 		  stack.push_back (std::move (item)); | 
 | 		} | 
 | 	      for (int i = changed.size () - 1; i >= 0; --i) | 
 | 		{ | 
 | 		  varobj_update_result item (changed[i]); | 
 |  | 
 | 		  item.changed = true; | 
 | 		  item.value_installed = true; | 
 |  | 
 | 		  stack.push_back (std::move (item)); | 
 | 		} | 
 | 	      for (int i = unchanged.size () - 1; i >= 0; --i) | 
 | 		{ | 
 | 		  if (!unchanged[i]->frozen) | 
 | 		    { | 
 | 		      varobj_update_result item (unchanged[i]); | 
 |  | 
 | 		      item.value_installed = true; | 
 |  | 
 | 		      stack.push_back (std::move (item)); | 
 | 		    } | 
 | 		} | 
 | 	      if (r.changed || r.children_changed) | 
 | 		result.push_back (std::move (r)); | 
 |  | 
 | 	      continue; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       /* Push any children.  Use 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 (int i = v->children.size () - 1; i >= 0; --i) | 
 | 	{ | 
 | 	  varobj *c = v->children[i]; | 
 |  | 
 | 	  /* Child may be NULL if explicitly deleted by -var-delete.  */ | 
 | 	  if (c != NULL && !c->frozen) | 
 | 	    stack.emplace_back (c); | 
 | 	} | 
 |  | 
 |       if (r.changed || r.type_changed) | 
 | 	result.push_back (std::move (r)); | 
 |     } | 
 |  | 
 |   return result; | 
 | } | 
 |  | 
 | /* Helper functions */ | 
 |  | 
 | /* | 
 |  * Variable object construction/destruction | 
 |  */ | 
 |  | 
 | static int | 
 | delete_variable (struct varobj *var, bool only_children_p) | 
 | { | 
 |   int delcount = 0; | 
 |  | 
 |   delete_variable_1 (&delcount, var, only_children_p, | 
 | 		     true /* remove_from_parent_p */ ); | 
 |  | 
 |   return delcount; | 
 | } | 
 |  | 
 | /* Delete the variable object VAR and its children.  */ | 
 | /* IMPORTANT NOTE: If we delete a variable which is a child | 
 |    and the parent is not removed we dump core.  It must be always | 
 |    initially called with remove_from_parent_p set.  */ | 
 | static void | 
 | delete_variable_1 (int *delcountp, struct varobj *var, bool only_children_p, | 
 | 		   bool remove_from_parent_p) | 
 | { | 
 |   /* Delete any children of this variable, too.  */ | 
 |   for (varobj *child : var->children) | 
 |     {    | 
 |       if (!child) | 
 | 	continue; | 
 |  | 
 |       if (!remove_from_parent_p) | 
 | 	child->parent = NULL; | 
 |  | 
 |       delete_variable_1 (delcountp, child, false, only_children_p); | 
 |     } | 
 |   var->children.clear (); | 
 |  | 
 |   /* if we were called to delete only the children we are done here.  */ | 
 |   if (only_children_p) | 
 |     return; | 
 |  | 
 |   /* Otherwise, add it to the list of deleted ones and proceed to do so.  */ | 
 |   /* If the name is empty, this is a temporary variable, that has not | 
 |      yet been installed, don't report it, it belongs to the caller...  */ | 
 |   if (!var->obj_name.empty ()) | 
 |     { | 
 |       *delcountp = *delcountp + 1; | 
 |     } | 
 |  | 
 |   /* If this variable has a parent, remove it from its parent's list.  */ | 
 |   /* OPTIMIZATION: if the parent of this variable is also being deleted,  | 
 |      (as indicated by remove_from_parent_p) we don't bother doing an | 
 |      expensive list search to find the element to remove when we are | 
 |      discarding the list afterwards.  */ | 
 |   if ((remove_from_parent_p) && (var->parent != NULL)) | 
 |     var->parent->children[var->index] = NULL; | 
 |  | 
 |   if (!var->obj_name.empty ()) | 
 |     uninstall_variable (var); | 
 |  | 
 |   /* Free memory associated with this variable.  */ | 
 |   delete var; | 
 | } | 
 |  | 
 | /* Install the given variable VAR with the object name VAR->OBJ_NAME.  */ | 
 | static void | 
 | install_variable (struct varobj *var) | 
 | { | 
 |   hashval_t hash = htab_hash_string (var->obj_name.c_str ()); | 
 |   void **slot = htab_find_slot_with_hash (varobj_table, | 
 | 					  var->obj_name.c_str (), | 
 | 					  hash, INSERT); | 
 |   if (*slot != nullptr) | 
 |     error (_("Duplicate variable object name")); | 
 |  | 
 |   /* Add varobj to hash table.  */ | 
 |   *slot = var; | 
 |  | 
 |   /* If root, add varobj to root list.  */ | 
 |   if (is_root_p (var)) | 
 |     rootlist.push_front (var->root); | 
 | } | 
 |  | 
 | /* Uninstall the object VAR.  */ | 
 | static void | 
 | uninstall_variable (struct varobj *var) | 
 | { | 
 |   hashval_t hash = htab_hash_string (var->obj_name.c_str ()); | 
 |   htab_remove_elt_with_hash (varobj_table, var->obj_name.c_str (), hash); | 
 |  | 
 |   if (varobjdebug) | 
 |     gdb_printf (gdb_stdlog, "Deleting %s\n", var->obj_name.c_str ()); | 
 |  | 
 |   /* If root, remove varobj from root list.  */ | 
 |   if (is_root_p (var)) | 
 |     { | 
 |       auto iter = std::find (rootlist.begin (), rootlist.end (), var->root); | 
 |       rootlist.erase (iter); | 
 |     } | 
 | } | 
 |  | 
 | /* Create and install a child of the parent of the given name. | 
 |  | 
 |    The created VAROBJ takes ownership of the allocated NAME.  */ | 
 |  | 
 | static struct varobj * | 
 | create_child (struct varobj *parent, int index, std::string &name) | 
 | { | 
 |   struct varobj_item item; | 
 |  | 
 |   std::swap (item.name, name); | 
 |   item.value = release_value (value_of_child (parent, index)); | 
 |  | 
 |   return create_child_with_value (parent, index, &item); | 
 | } | 
 |  | 
 | static struct varobj * | 
 | create_child_with_value (struct varobj *parent, int index, | 
 | 			 struct varobj_item *item) | 
 | { | 
 |   varobj *child = new varobj (parent->root); | 
 |  | 
 |   /* NAME is allocated by caller.  */ | 
 |   std::swap (child->name, item->name); | 
 |   child->index = index; | 
 |   child->parent = parent; | 
 |  | 
 |   if (varobj_is_anonymous_child (child)) | 
 |     child->obj_name = string_printf ("%s.%d_anonymous", | 
 | 				     parent->obj_name.c_str (), index); | 
 |   else | 
 |     child->obj_name = string_printf ("%s.%s", | 
 | 				     parent->obj_name.c_str (), | 
 | 				     child->name.c_str ()); | 
 |  | 
 |   install_variable (child); | 
 |  | 
 |   /* Compute the type of the child.  Must do this before | 
 |      calling install_new_value.  */ | 
 |   if (item->value != NULL) | 
 |     /* If the child had no evaluation errors, var->value | 
 |        will be non-NULL and contain a valid type.  */ | 
 |     child->type = value_actual_type (item->value.get (), 0, NULL); | 
 |   else | 
 |     /* Otherwise, we must compute the type.  */ | 
 |     child->type = (*child->root->lang_ops->type_of_child) (child->parent, | 
 | 							   child->index); | 
 |   install_new_value (child, item->value.get (), 1); | 
 |  | 
 |   return child; | 
 | } | 
 |  | 
 |  | 
 | /* | 
 |  * Miscellaneous utility functions. | 
 |  */ | 
 |  | 
 | /* Allocate memory and initialize a new variable.  */ | 
 | varobj::varobj (varobj_root *root_) | 
 | : root (root_), dynamic (new varobj_dynamic) | 
 | { | 
 | } | 
 |  | 
 | /* Free any allocated memory associated with VAR.  */ | 
 |  | 
 | varobj::~varobj () | 
 | { | 
 |   varobj *var = this; | 
 |  | 
 | #if HAVE_PYTHON | 
 |   if (var->dynamic->pretty_printer != NULL) | 
 |     { | 
 |       gdbpy_enter_varobj enter_py (var); | 
 |  | 
 |       Py_XDECREF (var->dynamic->constructor); | 
 |       Py_XDECREF (var->dynamic->pretty_printer); | 
 |     } | 
 | #endif | 
 |  | 
 |   /* This must be deleted before the root object, because Python-based | 
 |      destructors need access to some components.  */ | 
 |   delete var->dynamic; | 
 |  | 
 |   if (is_root_p (var)) | 
 |     delete var->root; | 
 | } | 
 |  | 
 | /* Return the type of the value that's stored in VAR, | 
 |    or that would have being stored there if the | 
 |    value were accessible. | 
 |  | 
 |    This differs from VAR->type in that VAR->type is always | 
 |    the true type of the expression in the source language. | 
 |    The return value of this function is the type we're | 
 |    actually storing in varobj, and using for displaying | 
 |    the values and for comparing previous and new values. | 
 |  | 
 |    For example, top-level references are always stripped.  */ | 
 | struct type * | 
 | varobj_get_value_type (const struct varobj *var) | 
 | { | 
 |   struct type *type; | 
 |  | 
 |   if (var->value != nullptr) | 
 |     type = var->value->type (); | 
 |   else | 
 |     type = var->type; | 
 |  | 
 |   type = check_typedef (type); | 
 |  | 
 |   if (TYPE_IS_REFERENCE (type)) | 
 |     type = get_target_type (type); | 
 |  | 
 |   type = check_typedef (type); | 
 |  | 
 |   return type; | 
 | } | 
 |  | 
 | /* | 
 |  * Language-dependencies | 
 |  */ | 
 |  | 
 | /* Common entry points */ | 
 |  | 
 | /* Return the number of children for a given variable. | 
 |    The result of this function is defined by the language | 
 |    implementation.  The number of children returned by this function | 
 |    is the number of children that the user will see in the variable | 
 |    display.  */ | 
 | static int | 
 | number_of_children (const struct varobj *var) | 
 | { | 
 |   return (*var->root->lang_ops->number_of_children) (var); | 
 | } | 
 |  | 
 | /* What is the expression for the root varobj VAR? */ | 
 |  | 
 | static std::string | 
 | name_of_variable (const struct varobj *var) | 
 | { | 
 |   return (*var->root->lang_ops->name_of_variable) (var); | 
 | } | 
 |  | 
 | /* What is the name of the INDEX'th child of VAR?  */ | 
 |  | 
 | static std::string | 
 | name_of_child (struct varobj *var, int index) | 
 | { | 
 |   return (*var->root->lang_ops->name_of_child) (var, index); | 
 | } | 
 |  | 
 | /* If frame associated with VAR can be found, switch | 
 |    to it and return true.  Otherwise, return false.  */ | 
 |  | 
 | static bool | 
 | check_scope (const struct varobj *var) | 
 | { | 
 |   frame_info_ptr fi; | 
 |   bool scope; | 
 |  | 
 |   fi = frame_find_by_id (var->root->frame); | 
 |   scope = fi != NULL; | 
 |  | 
 |   if (fi) | 
 |     { | 
 |       CORE_ADDR pc = get_frame_pc (fi); | 
 |  | 
 |       if (pc <  var->root->valid_block->start () || | 
 | 	  pc >= var->root->valid_block->end ()) | 
 | 	scope = false; | 
 |       else | 
 | 	select_frame (fi); | 
 |     } | 
 |   return scope; | 
 | } | 
 |  | 
 | /* Helper function to value_of_root.  */ | 
 |  | 
 | static struct value * | 
 | value_of_root_1 (struct varobj **var_handle) | 
 | { | 
 |   struct value *new_val = NULL; | 
 |   struct varobj *var = *var_handle; | 
 |   bool within_scope = false; | 
 | 								  | 
 |   /*  Only root variables can be updated...  */ | 
 |   if (!is_root_p (var)) | 
 |     /* Not a root var.  */ | 
 |     return NULL; | 
 |  | 
 |   scoped_restore_current_thread restore_thread; | 
 |  | 
 |   /* Determine whether the variable is still around.  */ | 
 |   if (var->root->valid_block == NULL || var->root->floating) | 
 |     within_scope = true; | 
 |   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 | 
 |     { | 
 |       thread_info *thread = find_thread_global_id (var->root->thread_id); | 
 |  | 
 |       if (thread != NULL) | 
 | 	{ | 
 | 	  switch_to_thread (thread); | 
 | 	  within_scope = check_scope (var); | 
 | 	} | 
 |     } | 
 |  | 
 |   if (within_scope) | 
 |     { | 
 |  | 
 |       /* We need to catch errors here, because if evaluate | 
 | 	 expression fails we want to just return NULL.  */ | 
 |       try | 
 | 	{ | 
 | 	  new_val = var->root->exp->evaluate (); | 
 | 	} | 
 |       catch (const gdb_exception_error &except) | 
 | 	{ | 
 | 	} | 
 |     } | 
 |  | 
 |   return new_val; | 
 | } | 
 |  | 
 | /* 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, bool *type_changed) | 
 | { | 
 |   struct varobj *var; | 
 |  | 
 |   if (var_handle == NULL) | 
 |     return NULL; | 
 |  | 
 |   var = *var_handle; | 
 |  | 
 |   /* This should really be an exception, since this should | 
 |      only get called with a root variable.  */ | 
 |  | 
 |   if (!is_root_p (var)) | 
 |     return NULL; | 
 |  | 
 |   if (var->root->floating) | 
 |     { | 
 |       struct varobj *tmp_var; | 
 |  | 
 |       tmp_var = varobj_create (NULL, var->name.c_str (), (CORE_ADDR) 0, | 
 | 			       USE_SELECTED_FRAME); | 
 |       if (tmp_var == NULL) | 
 | 	{ | 
 | 	  return NULL; | 
 | 	} | 
 |       std::string old_type = varobj_get_type (var); | 
 |       std::string new_type = varobj_get_type (tmp_var); | 
 |       if (old_type == new_type) | 
 | 	{ | 
 | 	  /* 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.  */ | 
 |  | 
 | 	  std::swap (var->root->exp, tmp_var->root->exp); | 
 |  | 
 | 	  varobj_delete (tmp_var, 0); | 
 | 	  *type_changed = 0; | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  tmp_var->obj_name = var->obj_name; | 
 | 	  tmp_var->from = var->from; | 
 | 	  tmp_var->to = var->to; | 
 | 	  varobj_delete (var, 0); | 
 |  | 
 | 	  install_variable (tmp_var); | 
 | 	  *var_handle = tmp_var; | 
 | 	  var = *var_handle; | 
 | 	  *type_changed = true; | 
 | 	} | 
 |     } | 
 |   else | 
 |     { | 
 |       *type_changed = 0; | 
 |     } | 
 |  | 
 |   { | 
 |     struct value *value; | 
 |  | 
 |     value = value_of_root_1 (var_handle); | 
 |     if (var->value == NULL || value == NULL) | 
 |       { | 
 | 	/* For root varobj-s, a NULL value indicates a scoping issue. | 
 | 	   So, nothing to do in terms of checking for mutations.  */ | 
 |       } | 
 |     else if (varobj_value_has_mutated (var, value, value->type ())) | 
 |       { | 
 | 	/* The type has mutated, so the children are no longer valid. | 
 | 	   Just delete them, and tell our caller that the type has | 
 | 	   changed.  */ | 
 | 	varobj_delete (var, 1 /* only_children */); | 
 | 	var->num_children = -1; | 
 | 	var->to = -1; | 
 | 	var->from = -1; | 
 | 	*type_changed = true; | 
 |       } | 
 |     return value; | 
 |   } | 
 | } | 
 |  | 
 | /* What is the ``struct value *'' for the INDEX'th child of PARENT?  */ | 
 | static struct value * | 
 | value_of_child (const struct varobj *parent, int index) | 
 | { | 
 |   struct value *value; | 
 |  | 
 |   value = (*parent->root->lang_ops->value_of_child) (parent, index); | 
 |  | 
 |   return value; | 
 | } | 
 |  | 
 | /* GDB already has a command called "value_of_variable".  Sigh.  */ | 
 | static std::string | 
 | my_value_of_variable (struct varobj *var, enum varobj_display_formats format) | 
 | { | 
 |   if (var->root->is_valid) | 
 |     { | 
 |       if (var->dynamic->pretty_printer != NULL) | 
 | 	return varobj_value_get_print_value (var->value.get (), var->format, | 
 | 					     var); | 
 |       else if (var->parent != nullptr && varobj_is_dynamic_p (var->parent)) | 
 | 	return var->print_value; | 
 |  | 
 |       return (*var->root->lang_ops->value_of_variable) (var, format); | 
 |     } | 
 |   else | 
 |     return std::string (); | 
 | } | 
 |  | 
 | void | 
 | varobj_formatted_print_options (struct value_print_options *opts, | 
 | 				enum varobj_display_formats format) | 
 | { | 
 |   get_formatted_print_options (opts, format_code[(int) format]); | 
 |   opts->deref_ref = false; | 
 |   opts->raw = !pretty_printing; | 
 | } | 
 |  | 
 | std::string | 
 | varobj_value_get_print_value (struct value *value, | 
 | 			      enum varobj_display_formats format, | 
 | 			      const struct varobj *var) | 
 | { | 
 |   struct value_print_options opts; | 
 |   struct type *type = NULL; | 
 |   long len = 0; | 
 |   gdb::unique_xmalloc_ptr<char> encoding; | 
 |   /* Initialize it just to avoid a GCC false warning.  */ | 
 |   CORE_ADDR str_addr = 0; | 
 |   bool string_print = false; | 
 |  | 
 |   if (value == NULL) | 
 |     return std::string (); | 
 |  | 
 |   string_file stb; | 
 |   std::string thevalue; | 
 |  | 
 |   varobj_formatted_print_options (&opts, format); | 
 |  | 
 | #if HAVE_PYTHON | 
 |   if (gdb_python_initialized) | 
 |     { | 
 |       PyObject *value_formatter =  var->dynamic->pretty_printer; | 
 |  | 
 |       gdbpy_enter_varobj enter_py (var); | 
 |  | 
 |       if (value_formatter) | 
 | 	{ | 
 | 	  if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst)) | 
 | 	    { | 
 | 	      struct value *replacement; | 
 |  | 
 | 	      gdbpy_ref<> output = apply_varobj_pretty_printer (value_formatter, | 
 | 								&replacement, | 
 | 								&stb, | 
 | 								&opts); | 
 |  | 
 | 	      /* If we have string like output ...  */ | 
 | 	      if (output != nullptr && output != Py_None) | 
 | 		{ | 
 | 		  /* If this is a lazy string, extract it.  For lazy | 
 | 		     strings we always print as a string, so set | 
 | 		     string_print.  */ | 
 | 		  if (gdbpy_is_lazy_string (output.get ())) | 
 | 		    { | 
 | 		      gdbpy_extract_lazy_string (output.get (), &str_addr, | 
 | 						 &type, &len, &encoding); | 
 | 		      string_print = true; | 
 | 		    } | 
 | 		  else | 
 | 		    { | 
 | 		      /* If it is a regular (non-lazy) string, extract | 
 | 			 it and copy the contents into THEVALUE.  If the | 
 | 			 hint says to print it as a string, set | 
 | 			 string_print.  Otherwise just return the extracted | 
 | 			 string as a value.  */ | 
 |  | 
 | 		      gdb::unique_xmalloc_ptr<char> s | 
 | 			= python_string_to_target_string (output.get ()); | 
 |  | 
 | 		      if (s) | 
 | 			{ | 
 | 			  struct gdbarch *gdbarch; | 
 |  | 
 | 			  gdb::unique_xmalloc_ptr<char> hint | 
 | 			    = gdbpy_get_display_hint (value_formatter); | 
 | 			  if (hint) | 
 | 			    { | 
 | 			      if (!strcmp (hint.get (), "string")) | 
 | 				string_print = true; | 
 | 			    } | 
 |  | 
 | 			  thevalue = std::string (s.get ()); | 
 | 			  len = thevalue.size (); | 
 | 			  gdbarch = value->type ()->arch (); | 
 | 			  type = builtin_type (gdbarch)->builtin_char; | 
 |  | 
 | 			  if (!string_print) | 
 | 			    return thevalue; | 
 | 			} | 
 | 		      else | 
 | 			gdbpy_print_stack (); | 
 | 		    } | 
 | 		} | 
 | 	      /* If the printer returned a replacement value, set VALUE | 
 | 		 to REPLACEMENT.  If there is not a replacement value, | 
 | 		 just use the value passed to this function.  */ | 
 | 	      if (replacement) | 
 | 		value = replacement; | 
 | 	    } | 
 | 	  else | 
 | 	    { | 
 | 	      /* No to_string method, so if there is a 'children' | 
 | 		 method, return the default.  */ | 
 | 	      if (PyObject_HasAttr (value_formatter, gdbpy_children_cst)) | 
 | 		return "{...}"; | 
 | 	    } | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  /* If we've made it here, we don't want a pretty-printer -- | 
 | 	     if we had one, it would already have been used.  */ | 
 | 	  opts.raw = true; | 
 | 	} | 
 |     } | 
 | #endif | 
 |  | 
 |   /* If the THEVALUE has contents, it is a regular string.  */ | 
 |   if (!thevalue.empty ()) | 
 |     current_language->printstr (&stb, type, (gdb_byte *) thevalue.c_str (), | 
 | 				len, encoding.get (), 0, &opts); | 
 |   else if (string_print) | 
 |     /* Otherwise, if string_print is set, and it is not a regular | 
 |        string, it is a lazy string.  */ | 
 |     val_print_string (type, encoding.get (), str_addr, len, &stb, &opts); | 
 |   else | 
 |     /* All other cases.  */ | 
 |     common_val_print (value, &stb, 0, &opts, current_language); | 
 |  | 
 |   return stb.release (); | 
 | } | 
 |  | 
 | bool | 
 | varobj_editable_p (const struct varobj *var) | 
 | { | 
 |   struct type *type; | 
 |  | 
 |   if (!(var->root->is_valid && var->value != nullptr | 
 | 	&& var->value->lval ())) | 
 |     return false; | 
 |  | 
 |   type = varobj_get_value_type (var); | 
 |  | 
 |   switch (type->code ()) | 
 |     { | 
 |     case TYPE_CODE_STRUCT: | 
 |     case TYPE_CODE_UNION: | 
 |     case TYPE_CODE_ARRAY: | 
 |     case TYPE_CODE_FUNC: | 
 |     case TYPE_CODE_METHOD: | 
 |       return false; | 
 |       break; | 
 |  | 
 |     default: | 
 |       return true; | 
 |       break; | 
 |     } | 
 | } | 
 |  | 
 | /* Call VAR's value_is_changeable_p language-specific callback.  */ | 
 |  | 
 | bool | 
 | varobj_value_is_changeable_p (const struct varobj *var) | 
 | { | 
 |   return var->root->lang_ops->value_is_changeable_p (var); | 
 | } | 
 |  | 
 | /* Return true 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.  */ | 
 | bool | 
 | varobj_floating_p (const struct varobj *var) | 
 | { | 
 |   return var->root->floating; | 
 | } | 
 |  | 
 | /* Implement the "value_is_changeable_p" varobj callback for most | 
 |    languages.  */ | 
 |  | 
 | bool | 
 | varobj_default_value_is_changeable_p (const struct varobj *var) | 
 | { | 
 |   bool r; | 
 |   struct type *type; | 
 |  | 
 |   if (CPLUS_FAKE_CHILD (var)) | 
 |     return false; | 
 |  | 
 |   type = varobj_get_value_type (var); | 
 |  | 
 |   switch (type->code ()) | 
 |     { | 
 |     case TYPE_CODE_STRUCT: | 
 |     case TYPE_CODE_UNION: | 
 |     case TYPE_CODE_ARRAY: | 
 |       r = false; | 
 |       break; | 
 |  | 
 |     default: | 
 |       r = true; | 
 |     } | 
 |  | 
 |   return r; | 
 | } | 
 |  | 
 | /* Iterate all the existing _root_ VAROBJs and call the FUNC callback | 
 |    for each one.  */ | 
 |  | 
 | void | 
 | all_root_varobjs (gdb::function_view<void (struct varobj *var)> func) | 
 | { | 
 |   /* Iterate "safely" - handle if the callee deletes its passed VAROBJ.  */ | 
 |   auto iter = rootlist.begin (); | 
 |   auto end = rootlist.end (); | 
 |   while (iter != end) | 
 |     { | 
 |       auto self = iter++; | 
 |       func ((*self)->rootvar); | 
 |     } | 
 | } | 
 |  | 
 | /* Try to recreate the varobj VAR if it is a global or floating.  This is a | 
 |    helper function for varobj_re_set.  */ | 
 |  | 
 | static void | 
 | varobj_re_set_iter (struct varobj *var) | 
 | { | 
 |   /* Invalidated global varobjs must be re-evaluated.  */ | 
 |   if (!var->root->is_valid && var->root->global) | 
 |     { | 
 |       struct varobj *tmp_var; | 
 |  | 
 |       /* Try to create a varobj with same expression.  If we succeed | 
 | 	 and have a global replace the old varobj.  */ | 
 |       tmp_var = varobj_create (nullptr, var->name.c_str (), (CORE_ADDR) 0, | 
 | 			       USE_CURRENT_FRAME); | 
 |       if (tmp_var != nullptr && tmp_var->root->global) | 
 | 	{ | 
 | 	  tmp_var->obj_name = var->obj_name; | 
 | 	  varobj_delete (var, 0); | 
 | 	  install_variable (tmp_var); | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* See varobj.h.  */ | 
 |  | 
 | void  | 
 | varobj_re_set (void) | 
 | { | 
 |   all_root_varobjs (varobj_re_set_iter); | 
 | } | 
 |  | 
 | /* Ensure that no varobj keep references to OBJFILE.  */ | 
 |  | 
 | static void | 
 | varobj_invalidate_if_uses_objfile (struct objfile *objfile) | 
 | { | 
 |   if (objfile->separate_debug_objfile_backlink != nullptr) | 
 |     objfile = objfile->separate_debug_objfile_backlink; | 
 |  | 
 |   all_root_varobjs ([objfile] (struct varobj *var) | 
 |     { | 
 |       if (var->root->valid_block != nullptr) | 
 | 	{ | 
 | 	  struct objfile *bl_objfile = var->root->valid_block->objfile (); | 
 | 	  if (bl_objfile->separate_debug_objfile_backlink != nullptr) | 
 | 	    bl_objfile = bl_objfile->separate_debug_objfile_backlink; | 
 |  | 
 | 	  if (bl_objfile == objfile) | 
 | 	    { | 
 | 	      /* The varobj is tied to a block which is going away.  There is | 
 | 		 no way to reconstruct something later, so invalidate the | 
 | 		 varobj completely and drop the reference to the block which is | 
 | 		 being freed.  */ | 
 | 	      var->root->is_valid = false; | 
 | 	      var->root->valid_block = nullptr; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       if (var->root->exp != nullptr && var->root->exp->uses_objfile (objfile)) | 
 | 	{ | 
 | 	  /* The varobj's current expression references the objfile.  For | 
 | 	     globals and floating, it is possible that when we try to | 
 | 	     re-evaluate the expression later it is still valid with | 
 | 	     whatever is in scope at that moment.  Just invalidate the | 
 | 	     expression for now.  */ | 
 | 	  var->root->exp.reset (); | 
 |  | 
 | 	  /* It only makes sense to keep a floating varobj around.  */ | 
 | 	  if (!var->root->floating) | 
 | 	    var->root->is_valid = false; | 
 | 	} | 
 |  | 
 |       /* var->value->type and var->type might also reference the objfile. | 
 | 	 This is taken care of in value.c:preserve_values which deals with | 
 | 	 making sure that objfile-owned types are replaced with | 
 | 	 gdbarch-owned equivalents.  */ | 
 |     }); | 
 | } | 
 |  | 
 | /* A hash function for a varobj.  */ | 
 |  | 
 | static hashval_t | 
 | hash_varobj (const void *a) | 
 | { | 
 |   const varobj *obj = (const varobj *) a; | 
 |   return htab_hash_string (obj->obj_name.c_str ()); | 
 | } | 
 |  | 
 | /* A hash table equality function for varobjs.  */ | 
 |  | 
 | static int | 
 | eq_varobj_and_string (const void *a, const void *b) | 
 | { | 
 |   const varobj *obj = (const varobj *) a; | 
 |   const char *name = (const char *) b; | 
 |  | 
 |   return obj->obj_name == name; | 
 | } | 
 |  | 
 | INIT_GDB_FILE (varobj) | 
 | { | 
 |   varobj_table = htab_create_alloc (5, hash_varobj, eq_varobj_and_string, | 
 | 				    nullptr, xcalloc, xfree); | 
 |  | 
 |   add_setshow_zuinteger_cmd ("varobj", class_maintenance, | 
 | 			     &varobjdebug, | 
 | 			     _("Set varobj debugging."), | 
 | 			     _("Show varobj debugging."), | 
 | 			     _("When non-zero, varobj debugging is enabled."), | 
 | 			     NULL, show_varobjdebug, | 
 | 			     &setdebuglist, &showdebuglist); | 
 |  | 
 |   gdb::observers::free_objfile.attach (varobj_invalidate_if_uses_objfile, | 
 | 				       "varobj"); | 
 | } |