This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfc] Simplify internal variable handling


Hello,

GDB "internal variables" are a bit in odd in how they attempt to handle
changes in current architecture (in particular byte order).  The variable
holds its data in a value object, which is in target byte order.  However,
the internal variable remembers the byte order that was in effect at the
time the value was created, and compares it to the byte order in effect
at the time the internal variable is used.  If they differ, the bytes making
up the data of the value object are byte-swapped, assuming the value is of
sufficiently "simple" type (integer or pointer).

The following patch tries to simplify this logic, and in the process
eliminate the associated references to current_gdbarch, by changing the
internal variable logic to store its data as a LONGEST or CORE_ADDR
(i.e. in *host* byte order) instead of a struct value for those simple
types (for more complex types, a struct value is still used).

When the variable is accessed, a struct value is recreated from those
LONGEST or CORE_ADDR values on the fly (automatically using the 
appropriate byte order at the time).

As a side effect, this approach also allows to simplify handling of
internal functions.  These no longer need to overlay a host pointer
onto a struct value's "target" bytes, but instead can simply use yet
another flavor of storing host data in the internal variable object.

By externally exposing a LONGEST-based interface to internal variables,
several users throughout GDB can also be simplified as they no longer
need to care about what type to use.

Overall, the patch is a pure code simplification with no expected change
in behaviour.

Tested on powerpc64-linux and amd64-linux.
Any comments are welcome; I'm planning to commit in about a week.

Bye,
Ulrich



ChangeLog:

	* value.h (struct internalvar): Remove.
	(get_internalvar_integer): Add prototype.
	(set_internalvar_integer): Add prototype.
	(clear_internalvar): Add prototype.

	* value.c (struct internalvar): Move here.  Add type member.  Remove
	endian member.  Add union_internalvar member instead of value member.
	(init_if_undefined_command): Use intvar->type.
	(create_internalvar): Do not initialize value/endian, but type.
	(create_internalvar_type_lazy): Call create_internalvar.
	(value_of_internalvar): Handle host-side internalvar contents.
	(set_internalvar_component): Likewise.
	(set_internalvar): Likewise.
	(get_internalvar_integer): New function.
	(clear_internalvar): Likewise.
	(set_internalvar_integer): Likewise.
	(preserve_values): Handle host-side internalvar contents.

	* breakpoint.c (set_breakpoint_count, set_tracepoint_count): Call
	set_internalvar_integer instead of set_internalvar.
	* findcmd.c (find_command): Likewise.
	* infrun.c (handle_inferior_event): Likewise.
	* source.c (forward_search_command, reverse_search_command): Likewise.
	* tracepoint.c (set_traceframe_num, set_tracepoint_num,
	set_traceframe_context): Likewise.

	* printcmd.c (x_command): Call clear_internalvar instead of
	set_internalvar.
	* tracepoint.c (set_traceframe_context): Likewise.
	
	* breakpoint.c (get_number_trailer): Call get_internalvar_integer
	instead of value_of_internalvar.
	* linespec.c (decode_dollar): Likewise.

	* expprint.c (dump_subexp_body_standard): Use internalvar_name
	instead of accessing internalvar private elements.
	* valops.c (value_assign): Copy from original source instead of
	accessing internalvar private elements.



Index: gdb-head/gdb/breakpoint.c
===================================================================
--- gdb-head.orig/gdb/breakpoint.c
+++ gdb-head/gdb/breakpoint.c
@@ -368,8 +368,7 @@ void
 set_breakpoint_count (int num)
 {
   breakpoint_count = num;
-  set_internalvar (lookup_internalvar ("bpnum"),
-		   value_from_longest (builtin_type_int32, (LONGEST) num));
+  set_internalvar_integer (lookup_internalvar ("bpnum"), num);
 }
 
 /* Used in run_command to zero the hit count when a new run starts. */
@@ -421,16 +420,15 @@ get_number_trailer (char **pp, int trail
          to pass to lookup_internalvar().  */
       char *varname;
       char *start = ++p;
-      struct value *val;
+      LONGEST val;
 
       while (isalnum (*p) || *p == '_')
 	p++;
       varname = (char *) alloca (p - start + 1);
       strncpy (varname, start, p - start);
       varname[p - start] = '\0';
-      val = value_of_internalvar (lookup_internalvar (varname));
-      if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
-	retval = (int) value_as_long (val);
+      if (get_internalvar_integer (lookup_internalvar (varname), &val))
+	retval = (int) val;
       else
 	{
 	  printf_filtered (_("Convenience variable must have integer value.\n"));
@@ -8243,8 +8241,7 @@ static void
 set_tracepoint_count (int num)
 {
   tracepoint_count = num;
-  set_internalvar (lookup_internalvar ("tpnum"),
-		   value_from_longest (builtin_type_int32, (LONGEST) num));
+  set_internalvar_integer (lookup_internalvar ("tpnum"), num);
 }
 
 void
Index: gdb-head/gdb/expprint.c
===================================================================
--- gdb-head.orig/gdb/expprint.c
+++ gdb-head/gdb/expprint.c
@@ -1002,7 +1002,7 @@ dump_subexp_body_standard (struct expres
       fprintf_filtered (stream, "Internal var @");
       gdb_print_host_address (exp->elts[elt].internalvar, stream);
       fprintf_filtered (stream, " (%s)",
-			exp->elts[elt].internalvar->name);
+			internalvar_name (exp->elts[elt].internalvar));
       elt += 2;
       break;
     case OP_FUNCALL:
Index: gdb-head/gdb/findcmd.c
===================================================================
--- gdb-head.orig/gdb/findcmd.c
+++ gdb-head/gdb/findcmd.c
@@ -291,9 +291,7 @@ find_command (char *args, int from_tty)
 
   /* Record and print the results.  */
 
-  set_internalvar (lookup_internalvar ("numfound"),
-		   value_from_longest (builtin_type_int32,
-				       (LONGEST) found_count));
+  set_internalvar_integer (lookup_internalvar ("numfound"), found_count);
   if (found_count > 0)
     {
       struct gdbarch *gdbarch = current_gdbarch;
Index: gdb-head/gdb/infrun.c
===================================================================
--- gdb-head.orig/gdb/infrun.c
+++ gdb-head/gdb/infrun.c
@@ -2372,9 +2372,8 @@ handle_inferior_event (struct execution_
 
       /* Record the exit code in the convenience variable $_exitcode, so
          that the user can inspect this again later.  */
-      set_internalvar (lookup_internalvar ("_exitcode"),
-		       value_from_longest (builtin_type_int32,
-					   (LONGEST) ecs->ws.value.integer));
+      set_internalvar_integer (lookup_internalvar ("_exitcode"),
+			       (LONGEST) ecs->ws.value.integer);
       gdb_flush (gdb_stdout);
       target_mourn_inferior ();
       singlestep_breakpoints_inserted_p = 0;
Index: gdb-head/gdb/linespec.c
===================================================================
--- gdb-head.orig/gdb/linespec.c
+++ gdb-head/gdb/linespec.c
@@ -1669,7 +1669,7 @@ static struct symtabs_and_lines
 decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
 	       char ***canonical, struct symtab *file_symtab)
 {
-  struct value *valx;
+  LONGEST valx;
   int index = 0;
   int need_canonical = 0;
   struct symtabs_and_lines values;
@@ -1684,10 +1684,12 @@ decode_dollar (char *copy, int funfirstl
   if (!*p)		/* Reached end of token without hitting non-digit.  */
     {
       /* We have a value history reference.  */
+      struct value *val_history;
       sscanf ((copy[1] == '$') ? copy + 2 : copy + 1, "%d", &index);
-      valx = access_value_history ((copy[1] == '$') ? -index : index);
-      if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT)
+      val_history = access_value_history ((copy[1] == '$') ? -index : index);
+      if (TYPE_CODE (value_type (val_history)) != TYPE_CODE_INT)
 	error (_("History values used in line specs must have integer values."));
+      valx = value_as_long (val_history);
     }
   else
     {
@@ -1709,8 +1711,7 @@ decode_dollar (char *copy, int funfirstl
 	return minsym_found (funfirstline, msymbol);
 
       /* Not a user variable or function -- must be convenience variable.  */
-      valx = value_of_internalvar (lookup_internalvar (copy + 1));
-      if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT)
+      if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx))
 	error (_("Convenience variables used in line specs must have integer values."));
     }
 
@@ -1718,7 +1719,7 @@ decode_dollar (char *copy, int funfirstl
 
   /* Either history value or convenience value from above, in valx.  */
   val.symtab = file_symtab ? file_symtab : default_symtab;
-  val.line = value_as_long (valx);
+  val.line = valx;
   val.pc = 0;
 
   values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
Index: gdb-head/gdb/printcmd.c
===================================================================
--- gdb-head.orig/gdb/printcmd.c
+++ gdb-head/gdb/printcmd.c
@@ -1367,8 +1367,7 @@ x_command (char *exp, int from_tty)
 	 then don't fetch it now; instead mark it by voiding the $__
 	 variable.  */
       if (value_lazy (last_examine_value))
-	set_internalvar (lookup_internalvar ("__"),
-			 allocate_value (builtin_type_void));
+	clear_internalvar (lookup_internalvar ("__"));
       else
 	set_internalvar (lookup_internalvar ("__"), last_examine_value);
     }
Index: gdb-head/gdb/source.c
===================================================================
--- gdb-head.orig/gdb/source.c
+++ gdb-head/gdb/source.c
@@ -1612,9 +1612,7 @@ forward_search_command (char *regex, int
 	  /* Match! */
 	  fclose (stream);
 	  print_source_lines (current_source_symtab, line, line + 1, 0);
-	  set_internalvar (lookup_internalvar ("_"),
-			   value_from_longest (builtin_type_int32,
-					       (LONGEST) line));
+	  set_internalvar_integer (lookup_internalvar ("_"), line);
 	  current_source_line = max (line - lines_to_list / 2, 1);
 	  return;
 	}
@@ -1692,9 +1690,7 @@ reverse_search_command (char *regex, int
 	  /* Match! */
 	  fclose (stream);
 	  print_source_lines (current_source_symtab, line, line + 1, 0);
-	  set_internalvar (lookup_internalvar ("_"),
-			   value_from_longest (builtin_type_int32,
-					       (LONGEST) line));
+	  set_internalvar_integer (lookup_internalvar ("_"), line);
 	  current_source_line = max (line - lines_to_list / 2, 1);
 	  return;
 	}
Index: gdb-head/gdb/tracepoint.c
===================================================================
--- gdb-head.orig/gdb/tracepoint.c
+++ gdb-head/gdb/tracepoint.c
@@ -208,8 +208,7 @@ static void
 set_traceframe_num (int num)
 {
   traceframe_number = num;
-  set_internalvar (lookup_internalvar ("trace_frame"),
-		   value_from_longest (builtin_type_int32, (LONGEST) num));
+  set_internalvar_integer (lookup_internalvar ("trace_frame"), num);
 }
 
 /* Set tracepoint number to NUM.  */
@@ -217,8 +216,7 @@ static void
 set_tracepoint_num (int num)
 {
   tracepoint_number = num;
-  set_internalvar (lookup_internalvar ("tracepoint"),
-		   value_from_longest (builtin_type_int32, (LONGEST) num));
+  set_internalvar_integer (lookup_internalvar ("tracepoint"), num);
 }
 
 /* Set externally visible debug variables for querying/printing
@@ -240,13 +238,9 @@ set_traceframe_context (struct frame_inf
       traceframe_fun = 0;
       traceframe_sal.pc = traceframe_sal.line = 0;
       traceframe_sal.symtab = NULL;
-      set_internalvar (lookup_internalvar ("trace_func"),
-		       allocate_value (builtin_type_void));
-      set_internalvar (lookup_internalvar ("trace_file"),
-		       allocate_value (builtin_type_void));
-      set_internalvar (lookup_internalvar ("trace_line"),
-		       value_from_longest (builtin_type_int32,
-					   (LONGEST) - 1));
+      clear_internalvar (lookup_internalvar ("trace_func"));
+      clear_internalvar (lookup_internalvar ("trace_file"));
+      set_internalvar_integer (lookup_internalvar ("trace_line"), -1);
       return;
     }
 
@@ -257,16 +251,14 @@ set_traceframe_context (struct frame_inf
 
   /* Save linenumber as "$trace_line", a debugger variable visible to
      users.  */
-  set_internalvar (lookup_internalvar ("trace_line"),
-		   value_from_longest (builtin_type_int32,
-				       (LONGEST) traceframe_sal.line));
+  set_internalvar_integer (lookup_internalvar ("trace_line"),
+			   traceframe_sal.line);
 
   /* Save func name as "$trace_func", a debugger variable visible to
      users.  */
-  if (traceframe_fun == NULL ||
-      SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL)
-    set_internalvar (lookup_internalvar ("trace_func"),
-		     allocate_value (builtin_type_void));
+  if (traceframe_fun == NULL
+      || SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL)
+    clear_internalvar (lookup_internalvar ("trace_func"));
   else
     {
       len = strlen (SYMBOL_LINKAGE_NAME (traceframe_fun));
@@ -285,10 +277,9 @@ set_traceframe_context (struct frame_inf
 
   /* Save file name as "$trace_file", a debugger variable visible to
      users.  */
-  if (traceframe_sal.symtab == NULL ||
-      traceframe_sal.symtab->filename == NULL)
-    set_internalvar (lookup_internalvar ("trace_file"),
-		     allocate_value (builtin_type_void));
+  if (traceframe_sal.symtab == NULL
+      || traceframe_sal.symtab->filename == NULL)
+    clear_internalvar (lookup_internalvar ("trace_file"));
   else
     {
       len = strlen (traceframe_sal.symtab->filename);
Index: gdb-head/gdb/valops.c
===================================================================
--- gdb-head.orig/gdb/valops.c
+++ gdb-head/gdb/valops.c
@@ -777,7 +777,7 @@ value_assign (struct value *toval, struc
     {
     case lval_internalvar:
       set_internalvar (VALUE_INTERNALVAR (toval), fromval);
-      val = value_copy (VALUE_INTERNALVAR (toval)->value);
+      val = value_copy (fromval);
       val = value_change_enclosing_type (val, 
 					 value_enclosing_type (fromval));
       set_value_embedded_offset (val, value_embedded_offset (fromval));
Index: gdb-head/gdb/value.c
===================================================================
--- gdb-head.orig/gdb/value.c
+++ gdb-head/gdb/value.c
@@ -858,6 +858,32 @@ show_values (char *num_exp, int from_tty
    The user refers to them with a '$' prefix
    that does not appear in the variable names stored internally.  */
 
+struct internalvar
+{
+  struct internalvar *next;
+  char *name;
+  struct type *type;
+
+  /* True if this internalvar is the canonical name for a convenience
+     function.  */
+  int canonical;
+
+  /* If this function is non-NULL, it is used to compute a fresh value
+     on every access to the internalvar.  */
+  internalvar_make_value make_value;
+
+  /* To reduce dependencies on target properties (like byte order) that
+     may change during the lifetime of an internal variable, we store
+     simple scalar values as host objects.  */
+  union internalvar_data
+    {
+      struct value *v;
+      struct internal_function *f;
+      LONGEST l;
+      CORE_ADDR a;
+    } u;
+};
+
 static struct internalvar *internalvars;
 
 /* If the variable does not already exist create it and give it the value given.
@@ -886,7 +912,7 @@ init_if_undefined_command (char* args, i
 
   /* Only evaluate the expression if the lvalue is void.
      This may still fail if the expresssion is invalid.  */
-  if (TYPE_CODE (value_type (intvar->value)) == TYPE_CODE_VOID)
+  if (TYPE_CODE (intvar->type) == TYPE_CODE_VOID)
     evaluate_expression (expr);
 
   do_cleanups (old_chain);
@@ -921,11 +947,9 @@ create_internalvar (const char *name)
   struct internalvar *var;
   var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
   var->name = concat (name, (char *)NULL);
-  var->value = allocate_value (builtin_type_void);
-  var->endian = gdbarch_byte_order (current_gdbarch);
+  var->type = builtin_type_void;
   var->make_value = NULL;
   var->canonical = 0;
-  release_value (var->value);
   var->next = internalvars;
   internalvars = var;
   return var;
@@ -939,14 +963,8 @@ create_internalvar (const char *name)
 struct internalvar *
 create_internalvar_type_lazy (char *name, internalvar_make_value fun)
 {
-  struct internalvar *var;
-  var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
-  var->name = concat (name, (char *)NULL);
-  var->value = NULL;
+  struct internalvar *var = create_internalvar (name);
   var->make_value = fun;
-  var->endian = gdbarch_byte_order (current_gdbarch);
-  var->next = internalvars;
-  internalvars = var;
   return var;
 }
 
@@ -972,14 +990,31 @@ struct value *
 value_of_internalvar (struct internalvar *var)
 {
   struct value *val;
-  int i, j;
-  gdb_byte temp;
 
   if (var->make_value != NULL)
     val = (*var->make_value) (var);
   else
     {
-      val = value_copy (var->value);
+      switch (TYPE_CODE (var->type))
+	{
+	case TYPE_CODE_VOID:
+	case TYPE_CODE_INTERNAL_FUNCTION:
+	  val = allocate_value (var->type);
+	  break;
+
+	case TYPE_CODE_INT:
+	  val = value_from_longest (var->type, var->u.l);
+	  break;
+
+	case TYPE_CODE_PTR:
+	  val = value_from_pointer (var->type, var->u.a);
+	  break;
+
+	default:
+	  val = value_copy (var->u.v);
+	  break;
+	}
+
       if (value_lazy (val))
 	value_fetch_lazy (val);
 
@@ -993,127 +1028,210 @@ value_of_internalvar (struct internalvar
 	 assignments to them don't just replace the previous value
 	 altogether.  At the moment, this seems like the behavior we
 	 want.  */
-      if (var->value->lval == lval_computed)
-	VALUE_LVAL (val) = lval_computed;
-      else
+      if (val->lval != lval_computed)
 	{
 	  VALUE_LVAL (val) = lval_internalvar;
 	  VALUE_INTERNALVAR (val) = var;
 	}
     }
 
-  /* Values are always stored in the target's byte order.  When connected to a
-     target this will most likely always be correct, so there's normally no
-     need to worry about it.
-
-     However, internal variables can be set up before the target endian is
-     known and so may become out of date.  Fix it up before anybody sees.
-
-     Internal variables usually hold simple scalar values, and we can
-     correct those.  More complex values (e.g. structures and floating
-     point types) are left alone, because they would be too complicated
-     to correct.  */
-
-  if (var->endian != gdbarch_byte_order (current_gdbarch))
-    {
-      gdb_byte *array = value_contents_raw (val);
-      struct type *type = check_typedef (value_enclosing_type (val));
-      switch (TYPE_CODE (type))
-	{
-	case TYPE_CODE_INT:
-	case TYPE_CODE_PTR:
-	  /* Reverse the bytes.  */
-	  for (i = 0, j = TYPE_LENGTH (type) - 1; i < j; i++, j--)
-	    {
-	      temp = array[j];
-	      array[j] = array[i];
-	      array[i] = temp;
-	    }
-	  break;
-	}
+  return val;
+}
+
+int
+get_internalvar_integer (struct internalvar *var, LONGEST *result)
+{
+  switch (TYPE_CODE (var->type))
+    {
+    case TYPE_CODE_INT:
+      *result = var->u.l;
+      return 1;
+
+    default:
+      return 0;
     }
+}
 
-  return val;
+static int
+get_internalvar_function (struct internalvar *var,
+			  struct internal_function **result)
+{
+  switch (TYPE_CODE (var->type))
+    {
+    case TYPE_CODE_INTERNAL_FUNCTION:
+      *result = var->u.f;
+      return 1;
+
+    default:
+      return 0;
+    }
 }
 
 void
 set_internalvar_component (struct internalvar *var, int offset, int bitpos,
 			   int bitsize, struct value *newval)
 {
-  gdb_byte *addr = value_contents_writeable (var->value) + offset;
+  gdb_byte *addr;
 
-  if (bitsize)
-    modify_field (addr, value_as_long (newval),
-		  bitpos, bitsize);
-  else
-    memcpy (addr, value_contents (newval), TYPE_LENGTH (value_type (newval)));
+  switch (TYPE_CODE (var->type))
+    {
+    case TYPE_CODE_VOID:
+    case TYPE_CODE_INTERNAL_FUNCTION:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_PTR:
+      /* We can never get a component of a basic type.  */
+      internal_error (__FILE__, __LINE__, "set_internalvar_component");
+
+    default:
+      addr = value_contents_writeable (var->u.v);
+
+      if (bitsize)
+	modify_field (addr + offset,
+		      value_as_long (newval), bitpos, bitsize);
+      else
+	memcpy (addr + offset, value_contents (newval),
+		TYPE_LENGTH (value_type (newval)));
+      break;
+    }
 }
 
 void
 set_internalvar (struct internalvar *var, struct value *val)
 {
-  struct value *newval;
+  struct type *new_type = check_typedef (value_type (val));
+  union internalvar_data new_data = { 0 };
 
   if (var->canonical)
     error (_("Cannot overwrite convenience function %s"), var->name);
 
-  newval = value_copy (val);
-  newval->modifiable = 1;
+  /* Prepare new contents.  */
+  switch (TYPE_CODE (new_type))
+    {
+    case TYPE_CODE_VOID:
+      break;
+
+    case TYPE_CODE_INTERNAL_FUNCTION:
+      gdb_assert (VALUE_LVAL (val) == lval_internalvar);
+      get_internalvar_function (VALUE_INTERNALVAR (val), &new_data.f);
+      break;
+
+    case TYPE_CODE_INT:
+      new_data.l = value_as_long (val);
+      break;
+
+    case TYPE_CODE_PTR:
+      new_data.a = value_as_address (val);
+      break;
+
+    default:
+      new_data.v = value_copy (val);
+      new_data.v->modifiable = 1;
+
+      /* Force the value to be fetched from the target now, to avoid problems
+	 later when this internalvar is referenced and the target is gone or
+	 has changed.  */
+      if (value_lazy (new_data.v))
+       value_fetch_lazy (new_data.v);
+
+      /* Release the value from the value chain to prevent it from being
+	 deleted by free_all_values.  From here on this function should not
+	 call error () until new_data is installed into the var->u to avoid
+	 leaking memory.  */
+      release_value (new_data.v);
+      break;
+    }
+
+  /* Clean up old contents.  */
+  clear_internalvar (var);
 
-  /* Force the value to be fetched from the target now, to avoid problems
-     later when this internalvar is referenced and the target is gone or
-     has changed.  */
-  if (value_lazy (newval))
-    value_fetch_lazy (newval);
-
-  /* Begin code which must not call error().  If var->value points to
-     something free'd, an error() obviously leaves a dangling pointer.
-     But we also get a dangling pointer if var->value points to
-     something in the value chain (i.e., before release_value is
-     called), because after the error free_all_values will get called before
-     long.  */
-  value_free (var->value);
-  var->value = newval;
-  var->endian = gdbarch_byte_order (current_gdbarch);
-  release_value (newval);
+  /* Switch over.  */
+  var->type = new_type;
+  var->u = new_data;
   /* End code which must not call error().  */
 }
 
+void
+set_internalvar_integer (struct internalvar *var, LONGEST l)
+{
+  /* Clean up old contents.  */
+  clear_internalvar (var);
+
+  /* Use a platform-independent 32-bit integer type.  */
+  var->type = builtin_type_int32;
+  var->u.l = l;
+}
+
+static void
+set_internalvar_function (struct internalvar *var, struct internal_function *f)
+{
+  /* Clean up old contents.  */
+  clear_internalvar (var);
+
+  var->type = internal_fn_type;
+  var->u.f = f;
+}
+
+void
+clear_internalvar (struct internalvar *var)
+{
+  /* Clean up old contents.  */
+  switch (TYPE_CODE (var->type))
+    {
+    case TYPE_CODE_VOID:
+    case TYPE_CODE_INTERNAL_FUNCTION:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_PTR:
+      break;
+
+    default:
+      value_free (var->u.v);
+      break;
+    }
+
+  /* Set to void type.  */
+  var->type = builtin_type_void;
+}
+
 char *
 internalvar_name (struct internalvar *var)
 {
   return var->name;
 }
 
-static struct value *
-value_create_internal_function (const char *name,
-				internal_function_fn handler,
-				void *cookie)
-{
-  struct value *result = allocate_value (internal_fn_type);
-  gdb_byte *addr = value_contents_writeable (result);
-  struct internal_function **fnp = (struct internal_function **) addr;
+static struct internal_function *
+create_internal_function (const char *name,
+			  internal_function_fn handler, void *cookie)
+{
   struct internal_function *ifn = XNEW (struct internal_function);
   ifn->name = xstrdup (name);
   ifn->handler = handler;
   ifn->cookie = cookie;
-  *fnp = ifn;
-  return result;
+  return ifn;
 }
 
 char *
 value_internal_function_name (struct value *val)
 {
-  gdb_byte *addr = value_contents_writeable (val);
-  struct internal_function *ifn = * (struct internal_function **) addr;
+  struct internal_function *ifn;
+  int result;
+
+  gdb_assert (VALUE_LVAL (val) == lval_internalvar);
+  result = get_internalvar_function (VALUE_INTERNALVAR (val), &ifn);
+  gdb_assert (result);
+
   return ifn->name;
 }
 
 struct value *
 call_internal_function (struct value *func, int argc, struct value **argv)
 {
-  gdb_byte *addr = value_contents_writeable (func);
-  struct internal_function *ifn = * (struct internal_function **) addr;
+  struct internal_function *ifn;
+  int result;
+
+  gdb_assert (VALUE_LVAL (func) == lval_internalvar);
+  result = get_internalvar_function (VALUE_INTERNALVAR (func), &ifn);
+  gdb_assert (result);
+
   return (*ifn->handler) (ifn->cookie, argc, argv);
 }
 
@@ -1145,9 +1263,11 @@ add_internal_function (const char *name,
 		       internal_function_fn handler, void *cookie)
 {
   struct cmd_list_element *cmd;
+  struct internal_function *ifn;
   struct internalvar *var = lookup_internalvar (name);
-  struct value *fnval = value_create_internal_function (name, handler, cookie);
-  set_internalvar (var, fnval);
+
+  ifn = create_internal_function (name, handler, cookie);
+  set_internalvar_function (var, ifn);
   var->canonical = 1;
 
   cmd = add_cmd (xstrdup (name), no_class, function_command, (char *) doc,
@@ -1196,8 +1316,23 @@ preserve_values (struct objfile *objfile
 	preserve_one_value (cur->values[i], objfile, copied_types);
 
   for (var = internalvars; var; var = var->next)
-    if (var->value)
-      preserve_one_value (var->value, objfile, copied_types);
+    {
+      if (TYPE_OBJFILE (var->type) == objfile)
+	var->type = copy_type_recursive (objfile, var->type, copied_types);
+
+      switch (TYPE_CODE (var->type))
+	{
+	case TYPE_CODE_VOID:
+	case TYPE_CODE_INTERNAL_FUNCTION:
+	case TYPE_CODE_INT:
+	case TYPE_CODE_PTR:
+	  break;
+
+	default:
+	  preserve_one_value (var->u.v, objfile, copied_types);
+	  break;
+	}
+    }
 
   for (val = values_in_python; val; val = val->next)
     preserve_one_value (val, objfile, copied_types);
@@ -2047,6 +2182,5 @@ Placeholder command for showing help on 
 
   internal_fn_type = alloc_type (NULL);
   TYPE_CODE (internal_fn_type) = TYPE_CODE_INTERNAL_FUNCTION;
-  TYPE_LENGTH (internal_fn_type) = sizeof (struct internal_function *);
   TYPE_NAME (internal_fn_type) = "<internal function>";
 }
Index: gdb-head/gdb/value.h
===================================================================
--- gdb-head.orig/gdb/value.h
+++ gdb-head/gdb/value.h
@@ -302,23 +302,6 @@ extern struct value *coerce_ref (struct 
 
 extern struct value *coerce_array (struct value *value);
 
-/* Internal variables (variables for convenience of use of debugger)
-   are recorded as a chain of these structures.  */
-
-typedef struct value * (*internalvar_make_value) (struct internalvar *);
-
-struct internalvar
-{
-  struct internalvar *next;
-  char *name;
-  struct value *value;
-  internalvar_make_value make_value;
-  int endian;
-  /* True if this internalvar is the canonical name for a convenience
-     function.  */
-  int canonical;
-};
-
 
 
 #include "symtab.h"
@@ -531,8 +514,14 @@ extern struct value *access_value_histor
 
 extern struct value *value_of_internalvar (struct internalvar *var);
 
+extern int get_internalvar_integer (struct internalvar *var, LONGEST *l);
+
 extern void set_internalvar (struct internalvar *var, struct value *val);
 
+extern void set_internalvar_integer (struct internalvar *var, LONGEST l);
+
+extern void clear_internalvar (struct internalvar *var);
+
 extern void set_internalvar_component (struct internalvar *var,
 				       int offset,
 				       int bitpos, int bitsize,
@@ -542,6 +531,8 @@ extern struct internalvar *lookup_only_i
 
 extern struct internalvar *create_internalvar (const char *name);
 
+typedef struct value * (*internalvar_make_value) (struct internalvar *);
+
 extern struct internalvar *
   create_internalvar_type_lazy (char *name, internalvar_make_value fun);
 
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]