2010-03-03 Stan Shebs <stan@codesourcery.com>

* remote.c (remote_download_tracepoint): Iterate over locations.
	* tracepoint.c (validate_actionline): Ditto.
	(encode_actions): Add location argument.
	(trace_dump_command): Check all locations to see if stepping
	frame.
This commit is contained in:
Stan Shebs
2010-03-04 00:32:50 +00:00
parent 3403c96dac
commit 9355b391f3
3 changed files with 188 additions and 154 deletions

View File

@ -1,3 +1,11 @@
2010-03-03 Stan Shebs <stan@codesourcery.com>
* remote.c (remote_download_tracepoint): Iterate over locations.
* tracepoint.c (validate_actionline): Ditto.
(encode_actions): Add location argument.
(trace_dump_command): Check all locations to see if stepping
frame.
2010-03-03 H.J. Lu <hongjiu.lu@intel.com> 2010-03-03 H.J. Lu <hongjiu.lu@intel.com>
Eli Zaretskii <eliz@gnu.org> Eli Zaretskii <eliz@gnu.org>

View File

@ -72,8 +72,8 @@
static char *target_buf; static char *target_buf;
static long target_buf_size; static long target_buf_size;
/*static*/ void /*static*/ void
encode_actions (struct breakpoint *t, char ***tdp_actions, encode_actions (struct breakpoint *t, struct bp_location *tloc,
char ***stepping_actions); char ***tdp_actions, char ***stepping_actions);
/* The size to align memory write packets, when practical. The protocol /* The size to align memory write packets, when practical. The protocol
does not guarantee any alignment, and gdb will generate short does not guarantee any alignment, and gdb will generate short
@ -9253,6 +9253,7 @@ free_actions_list (char **actions_list)
static void static void
remote_download_tracepoint (struct breakpoint *t) remote_download_tracepoint (struct breakpoint *t)
{ {
struct bp_location *loc;
CORE_ADDR tpaddr; CORE_ADDR tpaddr;
char tmp[40]; char tmp[40];
char buf[2048]; char buf[2048];
@ -9264,111 +9265,116 @@ remote_download_tracepoint (struct breakpoint *t)
struct cleanup *aexpr_chain = NULL; struct cleanup *aexpr_chain = NULL;
char *pkt; char *pkt;
encode_actions (t, &tdp_actions, &stepping_actions); /* Iterate over all the tracepoint locations. It's up to the target to
old_chain = make_cleanup (free_actions_list_cleanup_wrapper, notice multiple tracepoint packets with the same number but different
tdp_actions); addresses, and treat them as multiple locations. */
(void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions); for (loc = t->loc; loc; loc = loc->next)
tpaddr = t->loc->address;
sprintf_vma (tmp, (t->loc ? tpaddr : 0));
sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number,
tmp, /* address */
(t->enable_state == bp_enabled ? 'E' : 'D'),
t->step_count, t->pass_count);
/* Fast tracepoints are mostly handled by the target, but we can
tell the target how big of an instruction block should be moved
around. */
if (t->type == bp_fast_tracepoint)
{ {
/* Only test for support at download time; we may not know encode_actions (t, loc, &tdp_actions, &stepping_actions);
target capabilities at definition time. */ old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
if (remote_supports_fast_tracepoints ()) tdp_actions);
{ (void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions);
int isize;
if (gdbarch_fast_tracepoint_valid_at (target_gdbarch, tpaddr = loc->address;
tpaddr, &isize, NULL)) sprintf_vma (tmp, (loc ? tpaddr : 0));
sprintf (buf + strlen (buf), ":F%x", isize); sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number,
tmp, /* address */
(t->enable_state == bp_enabled ? 'E' : 'D'),
t->step_count, t->pass_count);
/* Fast tracepoints are mostly handled by the target, but we can
tell the target how big of an instruction block should be moved
around. */
if (t->type == bp_fast_tracepoint)
{
/* Only test for support at download time; we may not know
target capabilities at definition time. */
if (remote_supports_fast_tracepoints ())
{
int isize;
if (gdbarch_fast_tracepoint_valid_at (target_gdbarch,
tpaddr, &isize, NULL))
sprintf (buf + strlen (buf), ":F%x", isize);
else
/* If it passed validation at definition but fails now,
something is very wrong. */
internal_error (__FILE__, __LINE__,
"Fast tracepoint not valid during download");
}
else else
/* If it passed validation at definition but fails now, /* Fast tracepoints are functionally identical to regular
something is very wrong. */ tracepoints, so don't take lack of support as a reason to
internal_error (__FILE__, __LINE__, give up on the trace run. */
"Fast tracepoint not valid during download"); warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
} }
else /* If the tracepoint has a conditional, make it into an agent
/* Fast tracepoints are functionally identical to regular expression and append to the definition. */
tracepoints, so don't take lack of support as a reason to if (loc->cond)
give up on the trace run. */
warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
}
/* If the tracepoint has a conditional, make it into an agent
expression and append to the definition. */
if (t->loc->cond)
{
/* Only test support at download time, we may not know target
capabilities at definition time. */
if (remote_supports_cond_tracepoints ())
{ {
aexpr = gen_eval_for_expr (t->loc->address, t->loc->cond); /* Only test support at download time, we may not know target
aexpr_chain = make_cleanup_free_agent_expr (aexpr); capabilities at definition time. */
sprintf (buf + strlen (buf), ":X%x,", aexpr->len); if (remote_supports_cond_tracepoints ())
pkt = buf + strlen (buf); {
for (ndx = 0; ndx < aexpr->len; ++ndx) aexpr = gen_eval_for_expr (tpaddr, loc->cond);
pkt = pack_hex_byte (pkt, aexpr->buf[ndx]); aexpr_chain = make_cleanup_free_agent_expr (aexpr);
*pkt = '\0'; sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
do_cleanups (aexpr_chain); pkt = buf + strlen (buf);
for (ndx = 0; ndx < aexpr->len; ++ndx)
pkt = pack_hex_byte (pkt, aexpr->buf[ndx]);
*pkt = '\0';
do_cleanups (aexpr_chain);
}
else
warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
} }
else
warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
}
if (t->actions || *default_collect) if (t->actions || *default_collect)
strcat (buf, "-"); strcat (buf, "-");
putpkt (buf); putpkt (buf);
remote_get_noisy_reply (&target_buf, &target_buf_size); remote_get_noisy_reply (&target_buf, &target_buf_size);
if (strcmp (target_buf, "OK")) if (strcmp (target_buf, "OK"))
error (_("Target does not support tracepoints.")); error (_("Target does not support tracepoints."));
if (!t->actions && !*default_collect) if (!t->actions && !*default_collect)
return; continue;
/* do_single_steps (t); */ /* do_single_steps (t); */
if (tdp_actions) if (tdp_actions)
{
for (ndx = 0; tdp_actions[ndx]; ndx++)
{ {
QUIT; /* allow user to bail out with ^C */ for (ndx = 0; tdp_actions[ndx]; ndx++)
sprintf (buf, "QTDP:-%x:%s:%s%c", {
t->number, tmp, /* address */ QUIT; /* allow user to bail out with ^C */
tdp_actions[ndx], sprintf (buf, "QTDP:-%x:%s:%s%c",
((tdp_actions[ndx + 1] || stepping_actions) t->number, tmp, /* address */
? '-' : 0)); tdp_actions[ndx],
putpkt (buf); ((tdp_actions[ndx + 1] || stepping_actions)
remote_get_noisy_reply (&target_buf, ? '-' : 0));
&target_buf_size); putpkt (buf);
if (strcmp (target_buf, "OK")) remote_get_noisy_reply (&target_buf,
error (_("Error on target while setting tracepoints.")); &target_buf_size);
if (strcmp (target_buf, "OK"))
error (_("Error on target while setting tracepoints."));
}
} }
} if (stepping_actions)
if (stepping_actions)
{
for (ndx = 0; stepping_actions[ndx]; ndx++)
{ {
QUIT; /* allow user to bail out with ^C */ for (ndx = 0; stepping_actions[ndx]; ndx++)
sprintf (buf, "QTDP:-%x:%s:%s%s%s", {
t->number, tmp, /* address */ QUIT; /* allow user to bail out with ^C */
((ndx == 0) ? "S" : ""), sprintf (buf, "QTDP:-%x:%s:%s%s%s",
stepping_actions[ndx], t->number, tmp, /* address */
(stepping_actions[ndx + 1] ? "-" : "")); ((ndx == 0) ? "S" : ""),
putpkt (buf); stepping_actions[ndx],
remote_get_noisy_reply (&target_buf, (stepping_actions[ndx + 1] ? "-" : ""));
&target_buf_size); putpkt (buf);
if (strcmp (target_buf, "OK")) remote_get_noisy_reply (&target_buf,
error (_("Error on target while setting tracepoints.")); &target_buf_size);
if (strcmp (target_buf, "OK"))
error (_("Error on target while setting tracepoints."));
}
} }
do_cleanups (old_chain);
} }
do_cleanups (old_chain);
return;
} }
static void static void

View File

@ -625,7 +625,8 @@ validate_actionline (char **line, struct breakpoint *t)
struct cmd_list_element *c; struct cmd_list_element *c;
struct expression *exp = NULL; struct expression *exp = NULL;
struct cleanup *old_chain = NULL; struct cleanup *old_chain = NULL;
char *p; char *p, *tmp_p;
struct bp_location *loc;
/* if EOF is typed, *line is NULL */ /* if EOF is typed, *line is NULL */
if (*line == NULL) if (*line == NULL)
@ -671,48 +672,53 @@ validate_actionline (char **line, struct breakpoint *t)
} }
/* else fall thru, treat p as an expression and parse it! */ /* else fall thru, treat p as an expression and parse it! */
} }
exp = parse_exp_1 (&p, block_for_pc (t->loc->address), 1); tmp_p = p;
old_chain = make_cleanup (free_current_contents, &exp); for (loc = t->loc; loc; loc = loc->next)
if (exp->elts[0].opcode == OP_VAR_VALUE)
{ {
if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST) 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 (_("constant %s (value %ld) will not be collected."), if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
SYMBOL_PRINT_NAME (exp->elts[2].symbol), {
SYMBOL_VALUE (exp->elts[2].symbol)); warning (_("constant %s (value %ld) will not be collected."),
return BADLINE; SYMBOL_PRINT_NAME (exp->elts[2].symbol),
} SYMBOL_VALUE (exp->elts[2].symbol));
else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT) return BADLINE;
{ }
warning (_("%s is optimized away and cannot be collected."), else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
SYMBOL_PRINT_NAME (exp->elts[2].symbol)); {
return BADLINE; 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 (loc->address, exp);
make_cleanup_free_agent_expr (aexpr);
if (aexpr->len > MAX_AGENT_EXPR_LEN)
error (_("expression too complicated, try simplifying"));
ax_reqs (aexpr, &areqs);
(void) make_cleanup (xfree, areqs.reg_mask);
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"));
do_cleanups (old_chain);
} }
/* 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);
if (aexpr->len > MAX_AGENT_EXPR_LEN)
error (_("expression too complicated, try simplifying"));
ax_reqs (aexpr, &areqs);
(void) make_cleanup (xfree, areqs.reg_mask);
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"));
do_cleanups (old_chain);
} }
while (p && *p++ == ','); while (p && *p++ == ',');
return GENERIC; return GENERIC;
@ -727,20 +733,25 @@ validate_actionline (char **line, struct breakpoint *t)
while (isspace ((int) *p)) while (isspace ((int) *p))
p++; p++;
/* Only expressions are allowed for this action. */ tmp_p = p;
exp = parse_exp_1 (&p, block_for_pc (t->loc->address), 1); for (loc = t->loc; loc; loc = loc->next)
old_chain = make_cleanup (free_current_contents, &exp); {
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 /* We have something to evaluate, make sure that the expr to
bytecode translator can handle it and that it's not too bytecode translator can handle it and that it's not too
long. */ long. */
aexpr = gen_eval_for_expr (t->loc->address, exp); aexpr = gen_eval_for_expr (loc->address, exp);
make_cleanup_free_agent_expr (aexpr); make_cleanup_free_agent_expr (aexpr);
if (aexpr->len > MAX_AGENT_EXPR_LEN) if (aexpr->len > MAX_AGENT_EXPR_LEN)
error (_("expression too complicated, try simplifying")); error (_("expression too complicated, try simplifying"));
do_cleanups (old_chain); do_cleanups (old_chain);
}
} }
while (p && *p++ == ','); while (p && *p++ == ',');
return GENERIC; return GENERIC;
@ -1238,8 +1249,8 @@ stringify_collection_list (struct collection_list *list, char *string)
/* Render all actions into gdb protocol. */ /* Render all actions into gdb protocol. */
/*static*/ void /*static*/ void
encode_actions (struct breakpoint *t, char ***tdp_actions, encode_actions (struct breakpoint *t, struct bp_location *tloc,
char ***stepping_actions) char ***tdp_actions, char ***stepping_actions)
{ {
static char tdp_buff[2048], step_buff[2048]; static char tdp_buff[2048], step_buff[2048];
char *action_exp; char *action_exp;
@ -1263,7 +1274,7 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
*stepping_actions = NULL; *stepping_actions = NULL;
gdbarch_virtual_frame_pointer (t->gdbarch, gdbarch_virtual_frame_pointer (t->gdbarch,
t->loc->address, &frame_reg, &frame_offset); tloc->address, &frame_reg, &frame_offset);
action = t->actions; action = t->actions;
@ -1322,7 +1333,7 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
{ {
add_local_symbols (collect, add_local_symbols (collect,
t->gdbarch, t->gdbarch,
t->loc->address, tloc->address,
frame_reg, frame_reg,
frame_offset, frame_offset,
'A'); 'A');
@ -1332,7 +1343,7 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
{ {
add_local_symbols (collect, add_local_symbols (collect,
t->gdbarch, t->gdbarch,
t->loc->address, tloc->address,
frame_reg, frame_reg,
frame_offset, frame_offset,
'L'); 'L');
@ -1346,7 +1357,7 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
struct agent_reqs areqs; struct agent_reqs areqs;
exp = parse_exp_1 (&action_exp, 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); old_chain = make_cleanup (free_current_contents, &exp);
switch (exp->elts[0].opcode) switch (exp->elts[0].opcode)
@ -1381,11 +1392,11 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
t->gdbarch, t->gdbarch,
frame_reg, frame_reg,
frame_offset, frame_offset,
t->loc->address); tloc->address);
break; break;
default: /* full-fledged expression */ 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); old_chain1 = make_cleanup_free_agent_expr (aexpr);
@ -1443,10 +1454,10 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
struct agent_reqs areqs; struct agent_reqs areqs;
exp = parse_exp_1 (&action_exp, 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); 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); old_chain1 = make_cleanup_free_agent_expr (aexpr);
ax_reqs (aexpr, &areqs); ax_reqs (aexpr, &areqs);
@ -2224,6 +2235,7 @@ trace_dump_command (char *args, int from_tty)
struct cleanup *old_cleanups; struct cleanup *old_cleanups;
int stepping_actions = 0; int stepping_actions = 0;
int stepping_frame = 0; int stepping_frame = 0;
struct bp_location *loc;
if (tracepoint_number == -1) if (tracepoint_number == -1)
{ {
@ -2249,7 +2261,14 @@ trace_dump_command (char *args, int from_tty)
regcache = get_current_regcache (); regcache = get_current_regcache ();
gdbarch = get_regcache_arch (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) for (action = t->actions; action; action = action->next)
{ {
@ -3239,6 +3258,7 @@ tfile_get_traceframe_address (off_t tframe_offset)
error (_("Premature end of file while reading trace file")); error (_("Premature end of file while reading trace file"));
tp = get_tracepoint_by_number_on_target (tpnum); tp = get_tracepoint_by_number_on_target (tpnum);
/* FIXME this is a poor heuristic if multiple locations */
if (tp && tp->loc) if (tp && tp->loc)
addr = tp->loc->address; addr = tp->loc->address;