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]

Re: [PATCH 1/3] Refactor internal variable mechanism


On Friday, March 09 2012, Tom Tromey wrote:

>>>>>> "Sergio" == Sergio Durigan Junior <sergiodj@redhat.com> writes:
>
> Sergio> This is the first patch, which refactors the internal variable
> Sergio> mechanism.  It creates new methods, for example to compile an internal
> Sergio> variable into agent expression.
>
> Sergio> Is this OK to check-in?
>
> I intend to approve this one but I would like to wait for other comments
> first.

Sure :-).

> Really I'm replying now to point out a nit :)
>
> Sergio> +/* Implementation of `thread' variable.  */
> Sergio> +
> Sergio> +static struct internalvar_funcs thread_funcs =
>
> This one should be 'const' like the others are.

Right, thanks for that, fixed.

-- 
Sergio

2012-10-03  Sergio Durigan Junior  <sergiodj@redhat.com>
	    Tom Tromey  <tromey@redhat.com>

	* ax-gdb.c (gen_expr): Clean up code to handle internal variables
	and to compile agent expressions.
	* infrun.c (siginfo_make_value): New argument `ignore'.
	(siginfo_funcs): New struct.
	(_initialize_infrun): New argument when calling
	`create_internalvar_type_lazy'.
	* thread.c (thread_id_make_value): New argument `ignore'.
	(thread_funcs): New struct.
	(_initialize_thread): New argument when calling
	`create_internalvar_type_lazy'.
	* tracepoint.c (sdata_make_value): New argument `ignore'.
	(sdata_funcs): New struct.
	(_initialize_tracepoint): New argument when calling
	`create_internalvar_type_lazy'.
	* value.c (make_value): New struct.
	(create_internalvar_type_lazy): New argument `data'.
	(compile_internalvar_to_ax): New function.
	(value_of_internalvar): Properly handling `make_value' case.
	(clear_internalvar): Likewise.
	(show_convenience): Adding `TRY_CATCH' block.
	* value.h (internalvar_make_value): Delete, replace by...
	(struct internalvar_funcs): ... this.
	(create_internalvar_type_lazy) <fun>: Delete argument.
	(create_internalvar_type_lazy) <funcs>, <data>: New arguments.
	(compile_internalvar_to_ax): New function.
	* windows-tdep.c (tlb_make_value): New argument `ignore'.
	(tlb_funcs): New struct.
	(_initialize_windows_tdep): New argument when calling
	`create_internalvar_type_lazy'.

---
 gdb/ax-gdb.c       |    5 +++--
 gdb/infrun.c       |   14 ++++++++++++--
 gdb/thread.c       |   14 ++++++++++++--
 gdb/tracepoint.c   |   14 ++++++++++++--
 gdb/value.c        |   44 +++++++++++++++++++++++++++++++++++++++-----
 gdb/value.h        |   48 +++++++++++++++++++++++++++++++++++++++++++++---
 gdb/windows-tdep.c |   13 +++++++++++--
 7 files changed, 134 insertions(+), 18 deletions(-)

diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index bd81338..b163681 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -2041,7 +2041,8 @@ gen_expr (struct expression *exp, union exp_element **pc,
 
     case OP_INTERNALVAR:
       {
-	const char *name = internalvar_name ((*pc)[1].internalvar);
+	struct internalvar *var = (*pc)[1].internalvar;
+	const char *name = internalvar_name (var);
 	struct trace_state_variable *tsv;
 
 	(*pc) += 3;
@@ -2055,7 +2056,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
 	    value->kind = axs_rvalue;
 	    value->type = builtin_type (exp->gdbarch)->builtin_long_long;
 	  }
-	else
+	else if (! compile_internalvar_to_ax (var, ax, value))
 	  error (_("$%s is not a trace state variable; GDB agent "
 		   "expressions cannot use convenience variables."), name);
       }
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 103ef30..54e39ef 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -6589,7 +6589,8 @@ static const struct lval_funcs siginfo_value_funcs =
    if there's no object available.  */
 
 static struct value *
-siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var,
+		    void *ignore)
 {
   if (target_has_stack
       && !ptid_equal (inferior_ptid, null_ptid)
@@ -7011,6 +7012,15 @@ show_schedule_multiple (struct ui_file *file, int from_tty,
 			    "of all processes is %s.\n"), value);
 }
 
+/* Implementation of `siginfo' variable.  */
+
+static const struct internalvar_funcs siginfo_funcs =
+{
+  siginfo_make_value,
+  NULL,
+  NULL
+};
+
 void
 _initialize_infrun (void)
 {
@@ -7299,7 +7309,7 @@ enabled by default on some platforms."),
      value with a void typed value, and when we get here, gdbarch
      isn't initialized yet.  At this point, we're quite sure there
      isn't another convenience variable of the same name.  */
-  create_internalvar_type_lazy ("_siginfo", siginfo_make_value);
+  create_internalvar_type_lazy ("_siginfo", &siginfo_funcs, NULL);
 
   add_setshow_boolean_cmd ("observer", no_class,
 			   &observer_mode_1, _("\
diff --git a/gdb/thread.c b/gdb/thread.c
index 97f283c..d361dd8 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1439,7 +1439,8 @@ update_thread_list (void)
    no thread is selected, or no threads exist.  */
 
 static struct value *
-thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var,
+		      void *ignore)
 {
   struct thread_info *tp = find_thread_ptid (inferior_ptid);
 
@@ -1450,6 +1451,15 @@ thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var)
 /* Commands with a prefix of `thread'.  */
 struct cmd_list_element *thread_cmd_list = NULL;
 
+/* Implementation of `thread' variable.  */
+
+static const struct internalvar_funcs thread_funcs =
+{
+  thread_id_make_value,
+  NULL,
+  NULL
+};
+
 void
 _initialize_thread (void)
 {
@@ -1495,5 +1505,5 @@ Show printing of thread events (such as thread start and exit)."), NULL,
          show_print_thread_events,
          &setprintlist, &showprintlist);
 
-  create_internalvar_type_lazy ("_thread", thread_id_make_value);
+  create_internalvar_type_lazy ("_thread", &thread_funcs, NULL);
 }
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 89f75b6..ac8fade 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -4946,7 +4946,8 @@ info_static_tracepoint_markers_command (char *arg, int from_tty)
    available.  */
 
 static struct value *
-sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var,
+		  void *ignore)
 {
   LONGEST size;
   gdb_byte *buf;
@@ -5125,6 +5126,15 @@ traceframe_available_memory (VEC(mem_range_s) **result,
   return 0;
 }
 
+/* Implementation of `sdata' variable.  */
+
+static const struct internalvar_funcs sdata_funcs =
+{
+  sdata_make_value,
+  NULL,
+  NULL
+};
+
 /* module initialization */
 void
 _initialize_tracepoint (void)
@@ -5135,7 +5145,7 @@ _initialize_tracepoint (void)
      value with a void typed value, and when we get here, gdbarch
      isn't initialized yet.  At this point, we're quite sure there
      isn't another convenience variable of the same name.  */
-  create_internalvar_type_lazy ("_sdata", sdata_make_value);
+  create_internalvar_type_lazy ("_sdata", &sdata_funcs, NULL);
 
   traceframe_number = -1;
   tracepoint_number = -1;
diff --git a/gdb/value.c b/gdb/value.c
index e8eb33f..9a384a5 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1577,7 +1577,14 @@ struct internalvar
       struct value *value;
 
       /* The call-back routine used with INTERNALVAR_MAKE_VALUE.  */
-      internalvar_make_value make_value;
+      struct
+        {
+	  /* The functions to call.  */
+	  const struct internalvar_funcs *functions;
+
+	  /* The function's user-data.  */
+	  void *data;
+        } make_value;
 
       /* The internal function used with INTERNALVAR_FUNCTION.  */
       struct
@@ -1676,18 +1683,39 @@ create_internalvar (const char *name)
 /* Create an internal variable with name NAME and register FUN as the
    function that value_of_internalvar uses to create a value whenever
    this variable is referenced.  NAME should not normally include a
-   dollar sign.  */
+   dollar sign.  DATA is passed uninterpreted to FUN when it is
+   called.  CLEANUP, if not NULL, is called when the internal variable
+   is destroyed.  It is passed DATA as its only argument.  */
 
 struct internalvar *
-create_internalvar_type_lazy (char *name, internalvar_make_value fun)
+create_internalvar_type_lazy (const char *name,
+			      const struct internalvar_funcs *funcs,
+			      void *data)
 {
   struct internalvar *var = create_internalvar (name);
 
   var->kind = INTERNALVAR_MAKE_VALUE;
-  var->u.make_value = fun;
+  var->u.make_value.functions = funcs;
+  var->u.make_value.data = data;
   return var;
 }
 
+/* See documentation in value.h.  */
+
+int
+compile_internalvar_to_ax (struct internalvar *var,
+			   struct agent_expr *expr,
+			   struct axs_value *value)
+{
+  if (var->kind != INTERNALVAR_MAKE_VALUE
+      || var->u.make_value.functions->compile_to_ax == NULL)
+    return 0;
+
+  var->u.make_value.functions->compile_to_ax (var, expr, value,
+					      var->u.make_value.data);
+  return 1;
+}
+
 /* Look up an internal variable with name NAME.  NAME should not
    normally include a dollar sign.
 
@@ -1760,7 +1788,8 @@ value_of_internalvar (struct gdbarch *gdbarch, struct internalvar *var)
       break;
 
     case INTERNALVAR_MAKE_VALUE:
-      val = (*var->u.make_value) (gdbarch, var);
+      val = (*var->u.make_value.functions->make_value) (gdbarch, var,
+							var->u.make_value.data);
       break;
 
     default:
@@ -1956,6 +1985,11 @@ clear_internalvar (struct internalvar *var)
       xfree (var->u.string);
       break;
 
+    case INTERNALVAR_MAKE_VALUE:
+      if (var->u.make_value.functions->destroy != NULL)
+	var->u.make_value.functions->destroy (var->u.make_value.data);
+      break;
+
     default:
       break;
     }
diff --git a/gdb/value.h b/gdb/value.h
index 3ce0f88..3e4e57f 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -733,10 +733,52 @@ extern struct internalvar *lookup_only_internalvar (const char *name);
 
 extern struct internalvar *create_internalvar (const char *name);
 
-typedef struct value * (*internalvar_make_value) (struct gdbarch *,
-						  struct internalvar *);
+/* An internalvar can be dynamically computed by supplying a vector of
+   function pointers to perform various operations.  */
+
+struct internalvar_funcs
+{
+  /* Compute the value of the variable.  The DATA argument passed to
+     the function is the same argument that was passed to
+     `create_internalvar_type_lazy'.  */
+
+  struct value *(*make_value) (struct gdbarch *arch,
+			       struct internalvar *var,
+			       void *data);
+
+  /* Update the agent expression EXPR with bytecode to compute the
+     value.  VALUE is the agent value we are updating.  The DATA
+     argument passed to this function is the same argument that was
+     passed to `create_internalvar_type_lazy'.  If this pointer is
+     NULL, then the internalvar cannot be compiled to an agent
+     expression.  */
+
+  void (*compile_to_ax) (struct internalvar *var,
+			 struct agent_expr *expr,
+			 struct axs_value *value,
+			 void *data);
+
+  /* If non-NULL, this is called to destroy DATA.  The DATA argument
+     passed to this function is the same argument that was passed to
+     `create_internalvar_type_lazy'.  */
+
+  void (*destroy) (void *data);
+};
+
 extern struct internalvar *
-  create_internalvar_type_lazy (char *name, internalvar_make_value fun);
+create_internalvar_type_lazy (const char *name,
+			      const struct internalvar_funcs *funcs,
+			      void *data);
+
+/* Compile an internal variable to an agent expression.  VAR is the
+   variable to compile; EXPR and VALUE are the agent expression we are
+   updating.  This will return 0 if there is no known way to compile
+   VAR, and 1 if VAR was successfully compiled.  It may also throw an
+   exception on error.  */
+
+extern int compile_internalvar_to_ax (struct internalvar *var,
+				      struct agent_expr *expr,
+				      struct axs_value *value);
 
 extern struct internalvar *lookup_internalvar (const char *name);
 
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 6b84eff..a704599 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -268,7 +268,7 @@ static const struct lval_funcs tlb_value_funcs =
    if there's no object available.  */
 
 static struct value *
-tlb_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+tlb_make_value (struct gdbarch *gdbarch, struct internalvar *var, void *ignore)
 {
   if (target_has_stack && !ptid_equal (inferior_ptid, null_ptid))
     {
@@ -428,6 +428,15 @@ init_w32_command_list (void)
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern initialize_file_ftype _initialize_windows_tdep;
 
+/* Implementation of `tlb' variable.  */
+
+static const struct internalvar_funcs tlb_funcs =
+{
+  tlb_make_value,
+  NULL,
+  NULL
+};
+
 void
 _initialize_windows_tdep (void)
 {
@@ -454,5 +463,5 @@ even if their meaning is unknown."),
      value with a void typed value, and when we get here, gdbarch
      isn't initialized yet.  At this point, we're quite sure there
      isn't another convenience variable of the same name.  */
-  create_internalvar_type_lazy ("_tlb", tlb_make_value);
+  create_internalvar_type_lazy ("_tlb", &tlb_funcs, NULL);
 }
-- 
1.7.6.5


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