/* Tracing command lists */
static struct cmd_list_element *tfindlist;
+/* List of expressions to collect by default at each tracepoint hit. */
+static char *default_collect = "";
+
static char *target_buf;
static long target_buf_size;
-
+
/* ======= Important command functions: ======= */
static void trace_actions_command (char *, int);
static void trace_start_command (char *, int);
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)
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 */
struct agent_expr *aexpr;
int frame_reg;
LONGEST frame_offset;
-
+ char *default_collect_line = NULL;
+ struct action_line *default_collect_action = NULL;
clear_collection_list (&tracepoint_list);
clear_collection_list (&stepping_list);
gdbarch_virtual_frame_pointer (t->gdbarch,
t->loc->address, &frame_reg, &frame_offset);
- for (action = t->actions; action; action = action->next)
+ action = t->actions;
+
+ /* If there are default expressions to collect, make up a collect
+ action and prepend to the action list to encode. Note that since
+ validation is per-tracepoint (local var "xyz" might be valid for
+ one tracepoint and not another, etc), we make up the action on
+ the fly, and don't cache it. */
+ if (*default_collect)
+ {
+ char *line;
+ enum actionline_type linetype;
+
+ default_collect_line = xmalloc (12 + strlen (default_collect));
+ sprintf (default_collect_line, "collect %s", default_collect);
+ line = default_collect_line;
+ linetype = validate_actionline (&line, t);
+ if (linetype != BADLINE)
+ {
+ default_collect_action = xmalloc (sizeof (struct action_line));
+ default_collect_action->next = t->actions;
+ default_collect_action->action = line;
+ action = default_collect_action;
+ }
+ }
+
+ for (; action; action = action->next)
{
QUIT; /* allow user to bail out with ^C */
action_exp = action->action;
}
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;
tdp_buff);
*stepping_actions = stringify_collection_list (&stepping_list,
step_buff);
+
+ xfree (default_collect_line);
+ xfree (default_collect_action);
}
static void
warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
}
- if (t->actions)
+ if (t->actions || *default_collect)
strcat (buf, "-");
putpkt (buf);
remote_get_noisy_reply (&target_buf, &target_buf_size);
if (strcmp (target_buf, "OK"))
error (_("Target does not support tracepoints."));
- if (!t->actions)
+ if (!t->actions && !*default_collect)
return;
encode_actions (t, &tdp_actions, &stepping_actions);
/* exported for use by the GUI */
trace_running_p = (target_buf[1] == '1');
+
+ if (trace_running_p)
+ printf_filtered (_("Trace is running on the target.\n"));
+ else
+ printf_filtered (_("Trace is not running on the target.\n"));
+
+ if (traceframe_number >= 0)
+ printf_filtered (_("Looking at trace frame %d, tracepoint %d.\n"),
+ traceframe_number, tracepoint_number);
+ else
+ printf_filtered (_("Not looking at any trace frame.\n"));
+
}
else
error (_("Trace can only be run on remote targets."));
if (target_is_remote ())
{
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
+
if (deprecated_trace_find_hook)
deprecated_trace_find_hook (args, from_tty);
if (target_is_remote ())
{
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
+
if (args == 0 || *args == 0)
pc = regcache_read_pc (get_current_regcache ());
else
if (target_is_remote ())
{
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
+
if (args == 0 || *args == 0)
{
if (tracepoint_number == -1)
if (target_is_remote ())
{
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
+
if (args == 0 || *args == 0)
{
sal = find_pc_line (get_frame_pc (get_current_frame ()), 0);
if (target_is_remote ())
{
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
+
if (args == 0 || *args == 0)
{ /* XXX FIXME: what should default behavior be? */
printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
if (target_is_remote ())
{
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
+
if (args == 0 || *args == 0)
{ /* XXX FIXME: what should default behavior be? */
printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
$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\
single-stepping, or enabling/disabling other tracepoints, \n\
depending on target's capabilities."));
+ default_collect = xstrdup ("");
+ add_setshow_string_cmd ("default-collect", class_trace,
+ &default_collect, _("\
+Set the list of expressions to collect by default"), _("\
+Show the list of expressions to collect by default"), NULL,
+ NULL, NULL,
+ &setlist, &showlist);
+
target_buf_size = 2048;
target_buf = xmalloc (target_buf_size);
}