static void trace_find_line_command (char *, int);
static void trace_find_range_command (char *, int);
static void trace_find_outside_command (char *, int);
-static void tracepoint_save_command (char *, int);
static void trace_dump_command (char *, int);
/* support routines */
struct cmd_list_element *c;
struct expression *exp = NULL;
struct cleanup *old_chain = NULL;
- char *p;
+ char *p, *tmp_p;
+ struct bp_location *loc;
/* if EOF is typed, *line is NULL */
if (*line == NULL)
}
/* else fall thru, treat p as an expression and parse it! */
}
- exp = parse_exp_1 (&p, block_for_pc (t->loc->address), 1);
- old_chain = make_cleanup (free_current_contents, &exp);
-
- if (exp->elts[0].opcode == OP_VAR_VALUE)
+ tmp_p = p;
+ for (loc = t->loc; loc; loc = loc->next)
{
- if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
- {
- warning (_("constant %s (value %ld) will not be collected."),
- SYMBOL_PRINT_NAME (exp->elts[2].symbol),
- SYMBOL_VALUE (exp->elts[2].symbol));
- return BADLINE;
- }
- else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
+ p = tmp_p;
+ exp = parse_exp_1 (&p, block_for_pc (loc->address), 1);
+ old_chain = make_cleanup (free_current_contents, &exp);
+
+ if (exp->elts[0].opcode == OP_VAR_VALUE)
{
- warning (_("%s is optimized away and cannot be collected."),
- SYMBOL_PRINT_NAME (exp->elts[2].symbol));
- return BADLINE;
+ if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
+ {
+ warning (_("constant %s (value %ld) will not be collected."),
+ SYMBOL_PRINT_NAME (exp->elts[2].symbol),
+ SYMBOL_VALUE (exp->elts[2].symbol));
+ return BADLINE;
+ }
+ else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
+ {
+ warning (_("%s is optimized away and cannot be collected."),
+ SYMBOL_PRINT_NAME (exp->elts[2].symbol));
+ return BADLINE;
+ }
}
- }
- /* We have something to collect, make sure that the expr to
- bytecode translator can handle it and that it's not too
- long. */
- aexpr = gen_trace_for_expr (t->loc->address, exp);
- make_cleanup_free_agent_expr (aexpr);
+ /* We have something to collect, make sure that the expr to
+ bytecode translator can handle it and that it's not too
+ long. */
+ aexpr = gen_trace_for_expr (loc->address, exp);
+ make_cleanup_free_agent_expr (aexpr);
- if (aexpr->len > MAX_AGENT_EXPR_LEN)
- error (_("expression too complicated, try simplifying"));
+ if (aexpr->len > MAX_AGENT_EXPR_LEN)
+ error (_("expression too complicated, try simplifying"));
- ax_reqs (aexpr, &areqs);
- (void) make_cleanup (xfree, areqs.reg_mask);
+ ax_reqs (aexpr, &areqs);
+ (void) make_cleanup (xfree, areqs.reg_mask);
- if (areqs.flaw != agent_flaw_none)
- error (_("malformed expression"));
+ 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.min_height < 0)
+ error (_("gdb: Internal error: expression has min height < 0"));
- if (areqs.max_height > 20)
- error (_("expression too complicated, try simplifying"));
+ if (areqs.max_height > 20)
+ error (_("expression too complicated, try simplifying"));
- do_cleanups (old_chain);
+ do_cleanups (old_chain);
+ }
}
while (p && *p++ == ',');
return GENERIC;
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);
+ tmp_p = p;
+ for (loc = t->loc; loc; loc = loc->next)
+ {
+ p = tmp_p;
+ /* Only expressions are allowed for this action. */
+ exp = parse_exp_1 (&p, block_for_pc (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);
+ /* 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 (loc->address, exp);
+ make_cleanup_free_agent_expr (aexpr);
- if (aexpr->len > MAX_AGENT_EXPR_LEN)
- error (_("expression too complicated, try simplifying"));
+ if (aexpr->len > MAX_AGENT_EXPR_LEN)
+ error (_("expression too complicated, try simplifying"));
- do_cleanups (old_chain);
+ do_cleanups (old_chain);
+ }
}
while (p && *p++ == ',');
return GENERIC;
/* Render all actions into gdb protocol. */
/*static*/ void
-encode_actions (struct breakpoint *t, char ***tdp_actions,
- char ***stepping_actions)
+encode_actions (struct breakpoint *t, struct bp_location *tloc,
+ char ***tdp_actions, char ***stepping_actions)
{
static char tdp_buff[2048], step_buff[2048];
char *action_exp;
*stepping_actions = NULL;
gdbarch_virtual_frame_pointer (t->gdbarch,
- t->loc->address, &frame_reg, &frame_offset);
+ tloc->address, &frame_reg, &frame_offset);
action = t->actions;
{
add_local_symbols (collect,
t->gdbarch,
- t->loc->address,
+ tloc->address,
frame_reg,
frame_offset,
'A');
{
add_local_symbols (collect,
t->gdbarch,
- t->loc->address,
+ tloc->address,
frame_reg,
frame_offset,
'L');
struct agent_reqs areqs;
exp = parse_exp_1 (&action_exp,
- block_for_pc (t->loc->address), 1);
+ block_for_pc (tloc->address), 1);
old_chain = make_cleanup (free_current_contents, &exp);
switch (exp->elts[0].opcode)
t->gdbarch,
frame_reg,
frame_offset,
- t->loc->address);
+ tloc->address);
break;
default: /* full-fledged expression */
- aexpr = gen_trace_for_expr (t->loc->address, exp);
+ aexpr = gen_trace_for_expr (tloc->address, exp);
old_chain1 = make_cleanup_free_agent_expr (aexpr);
struct agent_reqs areqs;
exp = parse_exp_1 (&action_exp,
- block_for_pc (t->loc->address), 1);
+ block_for_pc (tloc->address), 1);
old_chain = make_cleanup (free_current_contents, &exp);
- aexpr = gen_eval_for_expr (t->loc->address, exp);
+ aexpr = gen_eval_for_expr (tloc->address, exp);
old_chain1 = make_cleanup_free_agent_expr (aexpr);
ax_reqs (aexpr, &areqs);
reinit_frame_cache ();
registers_changed ();
+ target_dcache_invalidate ();
set_traceframe_num (target_frameno);
set_tracepoint_num (tp ? tp->number : target_tracept);
if (target_frameno == -1)
struct cleanup *old_cleanups;
int stepping_actions = 0;
int stepping_frame = 0;
+ struct bp_location *loc;
if (tracepoint_number == -1)
{
regcache = get_current_regcache ();
gdbarch = get_regcache_arch (regcache);
- stepping_frame = (t->loc->address != (regcache_read_pc (regcache)));
+ /* If the traceframe's address matches any of the tracepoint's
+ locations, assume it is a direct hit rather than a while-stepping
+ frame. (FIXME this is not reliable, should record each frame's
+ type.) */
+ stepping_frame = 1;
+ for (loc = t->loc; loc; loc = loc->next)
+ if (loc->address == regcache_read_pc (regcache))
+ stepping_frame = 0;
for (action = t->actions; action; action = action->next)
{
return traceframe_number;
}
+/* Make the traceframe NUM be the current trace frame. Does nothing
+ if NUM is already current. */
+
+void
+set_traceframe_number (int num)
+{
+ int newnum;
+
+ if (traceframe_number == num)
+ {
+ /* Nothing to do. */
+ return;
+ }
+
+ newnum = target_trace_find (tfind_number, num, 0, 0, NULL);
+
+ if (newnum != num)
+ warning (_("could not change traceframe"));
+
+ traceframe_number = newnum;
+
+ /* Changing the traceframe changes our view of registers and of the
+ frame chain. */
+ registers_changed ();
+}
+
+/* A cleanup used when switching away and back from tfind mode. */
+
+struct current_traceframe_cleanup
+{
+ /* The traceframe we were inspecting. */
+ int traceframe_number;
+};
+
+static void
+do_restore_current_traceframe_cleanup (void *arg)
+{
+ struct current_traceframe_cleanup *old = arg;
+
+ set_traceframe_number (old->traceframe_number);
+}
+
+static void
+restore_current_traceframe_cleanup_dtor (void *arg)
+{
+ struct current_traceframe_cleanup *old = arg;
+
+ xfree (old);
+}
+
+struct cleanup *
+make_cleanup_restore_current_traceframe (void)
+{
+ struct current_traceframe_cleanup *old;
+
+ old = xmalloc (sizeof (struct current_traceframe_cleanup));
+ old->traceframe_number = traceframe_number;
+
+ return make_cleanup_dtor (do_restore_current_traceframe_cleanup, old,
+ restore_current_traceframe_cleanup_dtor);
+}
/* Given a number and address, return an uploaded tracepoint with that
number, creating if necessary. */
unpush_target (&tfile_ops);
push_target (&tfile_ops);
- discard_cleanups (old_chain);
trace_filename = xstrdup (filename);
trace_fd = scratch_chan;
/* Add the file's tracepoints and variables into the current mix. */
- merge_uploaded_tracepoints (&uploaded_tps);
-
+ /* Get trace state variables first, they may be checked when parsing
+ uploaded commands. */
merge_uploaded_trace_state_variables (&uploaded_tsvs);
+ merge_uploaded_tracepoints (&uploaded_tps);
+
/* Record the starting offset of the binary trace data. */
trace_frames_offset = bytes;
error (_("Premature end of file while reading trace file"));
tp = get_tracepoint_by_number_on_target (tpnum);
+ /* FIXME this is a poor heuristic if multiple locations */
if (tp && tp->loc)
addr = tp->loc->address;
&tfindlist, "tfind ", 1, &cmdlist);
add_cmd ("outside", class_trace, trace_find_outside_command, _("\
-Select a trace frame whose PC is outside the given range.\n\
+Select a trace frame whose PC is outside the given range (exclusive).\n\
Usage: tfind outside addr1, addr2"),
&tfindlist);
add_cmd ("range", class_trace, trace_find_range_command, _("\
-Select a trace frame whose PC is in the given range.\n\
+Select a trace frame whose PC is in the given range (inclusive).\n\
Usage: tfind range addr1,addr2"),
&tfindlist);