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]

[PATCH] Add teval tracepoint action


The use of trace state variables in a tracepoint's action list presents a problem; the only available action is "collect", which has the side effect of saving the variable's value into the trace buffer. In some cases this might be useful; in others, the trace buffer might fill up with useless copies of variable values. So this patch introduces a new action "teval" which has the same syntax as collect, but only evaluates its expressions and does not put anything into the trace buffer.

(Tracepoint fans may remember that this was originally proposed as "do", but that is ambiguous with "down", so I changed it to be "eval" - but that reserves a term that we may want for general evaluation, so Tom Tromey suggested "teval", analogously with other t-prefixed tracepoint commands.)

Stan

2009-12-30 Stan Shebs <stan@codesourcery.com>

   Add new tracepoint action teval.
   * tracepoint.c (teval_pseudocommand): New function.
   (validate_actionline): Add teval action case.
   (encode_actions): Ditto.
   (_initialize_tracepoint): Define teval pseudocommand.
   * NEWS: Mention teval.

* tracepoint.c (trace_status_command): Add some status output.

* gdb.texinfo (Tracepoint Actions): Describe teval.
* gdb.trace/actions.exp: Test teval action.


Index: tracepoint.c
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.c,v
retrieving revision 1.131
diff -p -r1.131 tracepoint.c
*** tracepoint.c	30 Dec 2009 22:32:03 -0000	1.131
--- tracepoint.c	31 Dec 2009 01:57:05 -0000
*************** collect_pseudocommand (char *args, int f
*** 525,530 ****
--- 525,536 ----
    error (_("This command can only be used in a tracepoint actions list."));
  }
  
+ static void
+ teval_pseudocommand (char *args, int from_tty)
+ {
+   error (_("This command can only be used in a tracepoint actions list."));
+ }
+ 
  /* Enter a list of actions for a tracepoint.  */
  static void
  trace_actions_command (char *args, int from_tty)
*************** validate_actionline (char **line, struct
*** 761,766 ****
--- 767,800 ----
        while (p && *p++ == ',');
        return GENERIC;
      }
+   else if (cmd_cfunc_eq (c, teval_pseudocommand))
+     {
+       struct agent_expr *aexpr;
+ 
+       do
+ 	{			/* repeat over a comma-separated list */
+ 	  QUIT;			/* allow user to bail out with ^C */
+ 	  while (isspace ((int) *p))
+ 	    p++;
+ 
+ 	  /* Only expressions are allowed for this action.  */
+ 	  exp = parse_exp_1 (&p, block_for_pc (t->loc->address), 1);
+ 	  old_chain = make_cleanup (free_current_contents, &exp);
+ 
+ 	  /* We have something to evaluate, make sure that the expr to
+ 	     bytecode translator can handle it and that it's not too
+ 	     long.  */
+ 	  aexpr = gen_eval_for_expr (t->loc->address, exp);
+ 	  make_cleanup_free_agent_expr (aexpr);
+ 
+ 	  if (aexpr->len > MAX_AGENT_EXPR_LEN)
+ 	    error (_("expression too complicated, try simplifying"));
+ 
+ 	  do_cleanups (old_chain);
+ 	}
+       while (p && *p++ == ',');
+       return GENERIC;
+     }
    else if (cmd_cfunc_eq (c, while_stepping_pseudocommand))
      {
        char *steparg;		/* in case warning is necessary */
*************** encode_actions (struct breakpoint *t, ch
*** 1464,1469 ****
--- 1498,1543 ----
  	    }
  	  while (action_exp && *action_exp++ == ',');
  	}			/* if */
+       else if (cmd_cfunc_eq (cmd, teval_pseudocommand))
+ 	{
+ 	  do
+ 	    {			/* repeat over a comma-separated list */
+ 	      QUIT;		/* allow user to bail out with ^C */
+ 	      while (isspace ((int) *action_exp))
+ 		action_exp++;
+ 
+ 		{
+ 		  unsigned long addr, len;
+ 		  struct cleanup *old_chain = NULL;
+ 		  struct cleanup *old_chain1 = NULL;
+ 		  struct agent_reqs areqs;
+ 
+ 		  exp = parse_exp_1 (&action_exp, 
+ 				     block_for_pc (t->loc->address), 1);
+ 		  old_chain = make_cleanup (free_current_contents, &exp);
+ 
+ 		  aexpr = gen_eval_for_expr (t->loc->address, exp);
+ 		  old_chain1 = make_cleanup_free_agent_expr (aexpr);
+ 
+ 		  ax_reqs (aexpr, &areqs);
+ 		  if (areqs.flaw != agent_flaw_none)
+ 		    error (_("malformed expression"));
+ 
+ 		  if (areqs.min_height < 0)
+ 		    error (_("gdb: Internal error: expression has min height < 0"));
+ 		  if (areqs.max_height > 20)
+ 		    error (_("expression too complicated, try simplifying"));
+ 
+ 		  discard_cleanups (old_chain1);
+ 		  /* Even though we're not officially collecting, add
+ 		     to the collect list anyway.  */
+ 		  add_aexpr (collect, aexpr);
+ 
+ 		  do_cleanups (old_chain);
+ 		}		/* do */
+ 	    }
+ 	  while (action_exp && *action_exp++ == ',');
+ 	}			/* if */
        else if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
  	{
  	  collect = &stepping_list;
*************** Also accepts the following special argum
*** 2606,2611 ****
--- 2680,2691 ----
      $locals -- all variables local to the block/function scope.\n\
  Note: this command can only be used in a tracepoint \"actions\" list."));
  
+   add_com ("teval", class_trace, teval_pseudocommand, _("\
+ Specify one or more expressions to be evaluated at a tracepoint.\n\
+ Accepts a comma-separated list of (one or more) expressions.\n\
+ The result of each evaluation will be discarded.\n\
+ Note: this command can only be used in a tracepoint \"actions\" list."));
+ 
    add_com ("actions", class_trace, trace_actions_command, _("\
  Specify the actions to be taken at a tracepoint.\n\
  Tracepoint actions may include collecting of specified data, \n\
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.343
diff -p -r1.343 NEWS
*** NEWS	30 Dec 2009 16:11:06 -0000	1.343
--- NEWS	31 Dec 2009 01:57:05 -0000
*************** info tvariables
*** 97,102 ****
--- 97,106 ----
  delete tvariable $NAME ...
    Delete one or more trace state variables.
  
+ teval EXPR, ...
+   Evaluate the given expressions without collecting anything into the
+   trace buffer. (Valid in tracepoint actions only.)
+ 
  * New options
  
  set follow-exec-mode new|same
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.652
diff -p -r1.652 gdb.texinfo
*** doc/gdb.texinfo	30 Dec 2009 16:11:07 -0000	1.652
--- doc/gdb.texinfo	31 Dec 2009 01:57:06 -0000
*************** arguments separated by commas: the effec
*** 9626,9631 ****
--- 9626,9640 ----
  The command @code{info scope} (@pxref{Symbols, info scope}) is
  particularly useful for figuring out what data to collect.
  
+ @kindex teval @r{(tracepoints)}
+ @item teval @var{expr1}, @var{expr2}, @dots{}
+ Evaluate the given expressions when the tracepoint is hit.  This
+ command accepts a comma-separated list of expressions.  The results
+ are discarded, so this is mainly useful for assigning values to trace
+ state variables (@pxref{Trace State Variables}) without adding those
+ values to the trace buffer, as would be the case if the @code{collect}
+ action were used.
+ 
  @kindex while-stepping @r{(tracepoints)}
  @item while-stepping @var{n}
  Perform @var{n} single-step traces after the tracepoint, collecting
Index: testsuite/gdb.trace/actions.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.trace/actions.exp,v
retrieving revision 1.13
diff -p -r1.13 actions.exp
*** testsuite/gdb.trace/actions.exp	30 Dec 2009 16:11:08 -0000	1.13
--- testsuite/gdb.trace/actions.exp	31 Dec 2009 01:57:06 -0000
*************** gdb_test "set default-collect gdb_char_t
*** 212,214 ****
--- 212,242 ----
  gdb_test "show default-collect" \
      "The list of expressions to collect by default is \"gdb_char_test, gdb_long_test - 100\"..*" \
      "5.9b: show default-collect"
+ 
+ # 5.10 teval
+ 
+ gdb_test "tvariable \$tsv" \
+   "Trace state variable \\\$tsv created, with initial value 0." \
+   "Create a trace state variable"
+ 
+ gdb_trace_setactions "5.10a: set teval action for first tracepoint" \
+ 	"$trcpt1" \
+ 	"teval gdb_char_test" "^$"
+ 
+ gdb_trace_setactions "5.10a: set teval action for second tracepoint" \
+ 	"$trcpt2" \
+ 	"teval \$tsv += 1" "^$"
+ 
+ gdb_test "info tracepoints" \
+     "Num     Type\[ \]+Disp Enb Address\[ \]+What.*
+ \[0-9\]+\[\t \]+tracepoint     keep y.* in gdb_c_test at .*$srcfile:\[0-9\]+.
+ \[\t \]+A\[\t \]+teval gdb_char_test.
+ \[\t \]+A\[\t \]+end.
+ \[0-9\]+\[\t \]+tracepoint     keep y.* in gdb_asm_test at .*$srcfile:\[0-9\]+.
+ \[\t \]+A\[\t \]+teval \\\$tsv \\\+= 1.
+ \[\t \]+A\[\t \]+end.
+ \[0-9\]+\[\t \]+tracepoint     keep y.* in gdb_recursion_test at .*$srcfile:\[0-9\]+.
+ \[\t \]+A\[\t \]+collect gdb_long_test.
+ \[\t \]+A\[\t \]+end." \
+ 		"5.10a: verify teval actions set for two tracepoints"
+ 

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